boxen-halyard 2.8.0.akerl9

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ac8e5374a808cca4dfea64707dce54651817b3c0
4
+ data.tar.gz: a3d4f295176a14dcc4db0f96be0220b8cb90cc28
5
+ SHA512:
6
+ metadata.gz: c36e553d2f89ff62f98d6c0950f279ba569f7f45200d3a002c634cc75d5666a2932127a228901742d07af5a53d412b520db2ada93b232e41a00159551414fe8d
7
+ data.tar.gz: e6c42c58500bba2a6ca01c080a8bfd1dd5a8531c9f633508a155808b4de908ab8ef5b3e669865c3ae6f7ad1656ce05aaa80411ebc9cfab394381688d17f07dca
data/.gitignore ADDED
@@ -0,0 +1,12 @@
1
+ /.bundle
2
+ /.env.local.rb
3
+ /.projects
4
+ /.rbenv-version
5
+ /Gemfile.lock
6
+ /bin
7
+ /boxen-*.gem
8
+ /log
9
+ /puppet
10
+ /script/Boxen.dSYM
11
+ /.ruby-version
12
+ /pkg/
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source "https://rubygems.org"
2
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2012 GitHub, Inc.
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
17
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
18
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
19
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
20
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,64 @@
1
+ boxen
2
+ ==========
3
+
4
+ [![Dependency Status](https://img.shields.io/gemnasium/halyard/boxen.svg)](https://gemnasium.com/halyard/boxen)
5
+ [![Build Status](https://img.shields.io/circleci/project/halyard/boxen.svg)](https://circleci.com/gh/halyard/boxen)
6
+ [![Coverage Status](https://img.shields.io/codecov/c/github/halyard/boxen.svg)](https://codecov.io/github/halyard/boxen)
7
+ [![Code Quality](https://img.shields.io/codacy/51f97f9fdf8b45caa259ccbfa132164e.svg)](https://www.codacy.com/app/akerl/boxen)
8
+ [![MIT Licensed](https://img.shields.io/badge/license-MIT-green.svg)](https://tldrlegal.com/license/mit-license)
9
+
10
+ Manage Mac development boxes with love (and Puppet).
11
+
12
+ ## Changes from upstream
13
+
14
+ * Switched to CircleCI builds
15
+ * Update dependency versions, specifically targeting Puppet 4
16
+ * Create a GitHub token with admin:public_key access
17
+ * Add the verbose flag if run with debug enabled
18
+
19
+ ## Rules for Services
20
+
21
+ 0. Run on a nonstandard port, usually default port + 1000 or 10000.
22
+
23
+ 0. Install with a custom Boxen homebrew formula.
24
+
25
+ 0. Suffix the Homebrew package's version, starting with `-boxen1`.
26
+
27
+ 0. Run as a launchd service in the `dev` namespace, e.g.,
28
+ `dev.dnsmasq`.
29
+
30
+ 0. Store config, data, and log files in
31
+ `$BOXEN_HOME/{config,data,log}`. This will normally require
32
+ customization of a service's Homebrew formula.
33
+
34
+ Sometimes it's not possible to follow these rules, but try hard.
35
+
36
+ ## Projects from the CLI
37
+
38
+ We use a totally awful hack to do from-the-cli project installs of projects.
39
+ We create a file in "$BOXEN_HOME/repodir" called .projects, with a single line.
40
+ That line is made up of projects separated by commas.
41
+ We then read that into a Puppet fact in Puppet-land, and that checks for
42
+ classes that match those project names, and includes them in the catalog.
43
+
44
+ We can't pass a `FACTER_` env var because sudo has `env_reset`
45
+ and we can't just modify the sudoers file due to a chicken-egg problem.
46
+
47
+ ## Hooks
48
+
49
+ 0. All hooks must be in the namespace `Boxen::Hook::MyThing`.
50
+
51
+ 0. All hooks must subclass from `Boxen::Hook`
52
+
53
+ 0. All hooks must provide a private instance method `required_environment_variables` that returns an array with at least one entry.
54
+
55
+ 0. All hooks must provide a private instance method `#call`.
56
+
57
+ ## Contributing
58
+
59
+ Use the OS X system Ruby (1.8.7 or 2.0.0). Run `script/tests` often. Open PR's.
60
+ Use the CI.
61
+
62
+ ## Halp!
63
+
64
+ Use Issues or #boxen on irc.freenode.net.
data/Rakefile ADDED
@@ -0,0 +1,14 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+ require 'rubocop/rake_task'
4
+
5
+ desc 'Run tests'
6
+ RSpec::Core::RakeTask.new(:spec)
7
+
8
+ desc 'Run Rubocop on the gem'
9
+ RuboCop::RakeTask.new(:rubocop) do |task|
10
+ task.patterns = ['lib/**/*.rb', 'spec/**/*.rb']
11
+ task.fail_on_error = true
12
+ end
13
+
14
+ task default: [:spec, :build, :install]
data/boxen.gemspec ADDED
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+ #
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "boxen-halyard"
6
+ gem.version = "2.8.0.akerl9"
7
+ gem.authors = ["John Barnette", "Will Farrington", "David Goodlad", "Mike McQuaid"]
8
+ gem.email = ["jbarnette@github.com", "wfarr@github.com", "dgoodlad@github.com", "mikemcquaid@github.com"]
9
+ gem.description = "Manage Mac development boxes with love (and Puppet)."
10
+ gem.summary = "You know, for laptops and stuff."
11
+ gem.homepage = "https://github.com/halyard/boxen"
12
+ gem.license = 'MIT'
13
+
14
+ gem.files = `git ls-files`.split $/
15
+ gem.test_files = gem.files.grep /^test/
16
+ gem.require_paths = ["lib"]
17
+
18
+ gem.add_dependency 'ansi', '~> 1.5.0'
19
+ gem.add_dependency 'highline', '~> 1.7.0'
20
+ gem.add_dependency 'json_pure', '~> 1.8.0'
21
+ gem.add_dependency 'librarian-puppet', '~> 2.2.0'
22
+ gem.add_dependency 'octokit', '~> 4.2.0'
23
+ gem.add_dependency 'puppet', '~> 4.3.0'
24
+
25
+ gem.add_development_dependency 'rubocop', '~> 0.35.0'
26
+ gem.add_development_dependency 'rake', '~> 10.4.0'
27
+ gem.add_development_dependency 'codecov', '~> 0.1.1'
28
+ gem.add_development_dependency 'rspec', '~> 3.4.0'
29
+ gem.add_development_dependency 'fuubar', '~> 2.0.0'
30
+ end
data/circle.yml ADDED
@@ -0,0 +1,8 @@
1
+ dependencies:
2
+ override:
3
+ - 'rvm-exec 2.0.0-p645 bundle install'
4
+ - 'rvm-exec 2.2.3 bundle install'
5
+ test:
6
+ override:
7
+ - 'rvm-exec 2.0.0-p645 bundle exec rake'
8
+ - 'rvm-exec 2.2.3 bundle exec rake'
@@ -0,0 +1,72 @@
1
+ require "ansi"
2
+
3
+ module Boxen
4
+
5
+ # The superclass for preflight and postflight sanity checks.
6
+
7
+ class Check
8
+
9
+ # A collection of preflight instances for `config`. An instance is
10
+ # created for every constant under `self` that's also a
11
+ # subclass of `self`.
12
+
13
+ def self.checks(config)
14
+ constants.map { |n| const_get n }.
15
+ select { |c| c < self }.
16
+ map { |c| c.new config }
17
+ end
18
+
19
+ # Search `dir` and load all Ruby files under it.
20
+
21
+ def self.register(dir)
22
+ Dir["#{dir}/*.rb"].sort.each { |f| load f }
23
+ end
24
+
25
+ # Check each instance against `config`.
26
+
27
+ def self.run(config)
28
+ checks(config).each { |check| check.run unless check.ok? }
29
+ end
30
+
31
+ attr_reader :config
32
+
33
+ def initialize(config)
34
+ @config = config
35
+ end
36
+
37
+ # Is everything good to go? Implemented by subclasses.
38
+
39
+ def ok?
40
+ raise "Subclasses must implement this method."
41
+ end
42
+
43
+ # Warn, fix, or abort. Implemented by subclasses.
44
+
45
+ def run
46
+ raise "Subclasses must implement this method."
47
+ end
48
+
49
+ # A fancier `abort` and `warn`. This will probably really annoy
50
+ # someone at some point because it's overriding a Kernel method,
51
+ # but it's limited to checks.
52
+
53
+ def abort(message, *extras)
54
+ extras << { :color => :red }
55
+ warn message, *extras
56
+ exit 1
57
+ end
58
+
59
+ def warn(message, *extras)
60
+ options = Hash === extras.last ? extras.pop : {}
61
+ color = options[:color] || :yellow
62
+
63
+ $stderr.puts ANSI.send(color) { "--> #{message}" }
64
+
65
+ unless extras.empty?
66
+ extras.each { |line| $stderr.puts " #{line}" }
67
+ end
68
+
69
+ $stderr.puts
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,25 @@
1
+ module Boxen
2
+ class Checkout
3
+ attr_reader :config
4
+
5
+ def initialize(config)
6
+ @config = config
7
+ end
8
+
9
+ def sha
10
+ Dir.chdir(config.repodir) { `git rev-parse HEAD`.strip }
11
+ end
12
+
13
+ def master?
14
+ Dir.chdir(config.repodir) { `git symbolic-ref HEAD`.strip == 'refs/heads/master' }
15
+ end
16
+
17
+ def dirty?
18
+ !changes.empty?
19
+ end
20
+
21
+ def changes
22
+ Dir.chdir(config.repodir) { `git status --porcelain`.strip }
23
+ end
24
+ end
25
+ end
data/lib/boxen/cli.rb ADDED
@@ -0,0 +1,61 @@
1
+ require "boxen/config"
2
+ require "boxen/flags"
3
+ require "boxen/postflight"
4
+ require "boxen/preflight"
5
+ require "boxen/runner"
6
+ require "boxen/util"
7
+
8
+ module Boxen
9
+ class CLI
10
+ attr_reader :config
11
+ attr_reader :flags
12
+ attr_reader :runner
13
+
14
+ def initialize(config, flags)
15
+ @config = config
16
+ @flags = flags
17
+ @runner = Boxen::Runner.new(@config, @flags)
18
+ end
19
+
20
+ def run
21
+ if flags.help?
22
+ puts flags
23
+ exit
24
+ end
25
+
26
+ runner.run
27
+ end
28
+
29
+ # Run Boxen by wiring together the command-line flags, config,
30
+ # preflights, Puppet execution, and postflights. Returns Puppet's
31
+ # exit code.
32
+
33
+ def self.run(*args)
34
+ config = Boxen::Config.load
35
+ flags = Boxen::Flags.new args
36
+
37
+ # Apply command-line flags to the config in case we're changing or
38
+ # overriding anything.
39
+ flags.apply config
40
+
41
+ if flags.run?
42
+ # Run the preflight checks.
43
+ Boxen::Preflight.run config
44
+
45
+ # Save the config for Puppet (and next time).
46
+ Boxen::Config.save config
47
+ end
48
+
49
+ # Make the magic happen.
50
+ status = Boxen::CLI.new(config, flags).run
51
+
52
+ if flags.run?
53
+ # Run the postflight checks.
54
+ Boxen::Postflight.run config if status.success?
55
+ end
56
+
57
+ # Return Puppet's exit status.
58
+ return status.code
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,330 @@
1
+ require "boxen/keychain"
2
+ require "boxen/project"
3
+ require "fileutils"
4
+ require "json"
5
+ require "octokit"
6
+ require "shellwords"
7
+
8
+ module Boxen
9
+
10
+ # All configuration for Boxen, whether it's loaded from command-line
11
+ # args, environment variables, config files, or the keychain.
12
+
13
+ class Config
14
+ def self.load(&block)
15
+ new do |config|
16
+ file = "#{config.homedir}/config/boxen/defaults.json"
17
+
18
+ if File.file? file
19
+ attrs = JSON.parse File.read file
20
+
21
+ attrs.each do |key, value|
22
+ if !value.nil? && config.respond_to?(selector = "#{key}=")
23
+ config.send selector, value
24
+ end
25
+ end
26
+ end
27
+
28
+ keychain = Boxen::Keychain.new config.login, config.user
29
+ config.token = keychain.token
30
+
31
+ if config.enterprise?
32
+ # configure to talk to GitHub Enterprise
33
+ Octokit.configure do |c|
34
+ c.api_endpoint = "#{config.ghurl}/api/v3"
35
+ c.web_endpoint = config.ghurl
36
+ end
37
+ end
38
+
39
+ yield config if block_given?
40
+ end
41
+ end
42
+
43
+ # Save `config`. Returns `config`. Note that this only saves data,
44
+ # not flags. For example, `login` will be saved, but `stealth?`
45
+ # won't.
46
+
47
+ def self.save(config)
48
+ attrs = {
49
+ :email => config.email,
50
+ :fde => config.fde?,
51
+ :homedir => config.homedir,
52
+ :login => config.login,
53
+ :name => config.name,
54
+ :puppetdir => config.puppetdir,
55
+ :repodir => config.repodir,
56
+ :reponame => config.reponame,
57
+ :ghurl => config.ghurl,
58
+ :srcdir => config.srcdir,
59
+ :user => config.user,
60
+ :repotemplate => config.repotemplate,
61
+ :s3host => config.s3host,
62
+ :s3bucket => config.s3bucket
63
+ }
64
+
65
+ file = "#{config.homedir}/config/boxen/defaults.json"
66
+ FileUtils.mkdir_p File.dirname file
67
+
68
+ File.open file, "wb" do |f|
69
+ f.write JSON.generate Hash[attrs.reject { |k, v| v.nil? }]
70
+ end
71
+
72
+ keychain = Boxen::Keychain.new config.login, config.user
73
+ keychain.token = config.token
74
+
75
+ config
76
+ end
77
+
78
+ # Create a new instance. Yields `self` if `block` is given.
79
+
80
+ def initialize(&block)
81
+ @fde = true
82
+ @pull = true
83
+
84
+ yield self if block_given?
85
+ end
86
+
87
+ # Create an API instance using the current user creds. A new
88
+ # instance is created any time `token` changes.
89
+
90
+ def api
91
+ @api ||= Octokit::Client.new :login => token, :password => 'x-oauth-basic'
92
+ end
93
+
94
+ # Spew a bunch of debug logging? Default is `false`.
95
+
96
+ def debug?
97
+ !!@debug
98
+ end
99
+
100
+ attr_writer :debug
101
+
102
+ # A GitHub user's public email.
103
+
104
+ attr_accessor :email
105
+
106
+ # The shell script that loads Boxen's environment.
107
+
108
+ def envfile
109
+ "#{homedir}/env.sh"
110
+ end
111
+
112
+ # Is full disk encryption required? Default is `true`. Respects
113
+ # the `BOXEN_NO_FDE` environment variable.
114
+
115
+ def fde?
116
+ !ENV["BOXEN_NO_FDE"] && @fde
117
+ end
118
+
119
+ attr_writer :fde
120
+
121
+ # Boxen's home directory. Default is `"/opt/boxen"`. Respects the
122
+ # `BOXEN_HOME` environment variable.
123
+
124
+ def homedir
125
+ @homedir || ENV["BOXEN_HOME"] || "/opt/boxen"
126
+ end
127
+
128
+ attr_writer :homedir
129
+
130
+ # Boxen's log file. Default is `"#{repodir}/log/boxen.log"`.
131
+ # Respects the `BOXEN_LOG_FILE` environment variable. The log is
132
+ # overwritten on every run.
133
+
134
+ def logfile
135
+ @logfile || ENV["BOXEN_LOG_FILE"] || "#{repodir}/log/boxen.log"
136
+ end
137
+
138
+ attr_writer :logfile
139
+
140
+ # A GitHub user login. Default is `nil`.
141
+
142
+ attr_accessor :login
143
+
144
+ # A GitHub user's profile name.
145
+
146
+ attr_accessor :name
147
+
148
+ # Just go through the motions? Default is `false`.
149
+
150
+ def pretend?
151
+ !!@pretend
152
+ end
153
+
154
+ attr_writer :pretend
155
+
156
+ # Run a profiler on Puppet? Default is `false`.
157
+
158
+ def profile?
159
+ !!@profile
160
+ end
161
+
162
+ attr_writer :profile
163
+
164
+ # Enable the Puppet future parser? Default is `false`.
165
+
166
+ def future_parser?
167
+ !!@future_parser
168
+ end
169
+
170
+ attr_writer :future_parser
171
+
172
+ # Enable puppet reports ? Default is `false`.
173
+
174
+ def report?
175
+ !!@report
176
+ end
177
+
178
+ attr_writer :report
179
+
180
+ # Enable generation of dependency graphs.
181
+
182
+ def graph?
183
+ !!@graph
184
+ end
185
+
186
+ attr_writer :graph
187
+
188
+ # An Array of Boxen::Project entries, one for each project Boxen
189
+ # knows how to manage.
190
+ #
191
+ # FIX: Revisit this once we restructure template projects. It's
192
+ # broken for several reasons: It assumes paths that won't be
193
+ # right, and it assumes projects live in the same repo as this
194
+ # file.
195
+
196
+ def projects
197
+ files = Dir["#{repodir}/modules/projects/manifests/*.pp"]
198
+ names = files.map { |m| File.basename m, ".pp" }.sort
199
+
200
+ names.map do |name|
201
+ Boxen::Project.new "#{srcdir}/#{name}"
202
+ end
203
+ end
204
+
205
+ # The directory where Puppet expects configuration (which we don't
206
+ # use) and runtime information (which we generally don't care
207
+ # about). Default is `/tmp/boxen/puppet`. Respects the
208
+ # `BOXEN_PUPPET_DIR` environment variable.
209
+
210
+ def puppetdir
211
+ @puppetdir || ENV["BOXEN_PUPPET_DIR"] || "/tmp/boxen/puppet"
212
+ end
213
+
214
+ attr_writer :puppetdir
215
+
216
+ # The directory of the custom Boxen repo for an org. Default is
217
+ # `Dir.pwd`. Respects the `BOXEN_REPO_DIR` environment variable.
218
+
219
+ def repodir
220
+ @repodir || ENV["BOXEN_REPO_DIR"] || Dir.pwd
221
+ end
222
+
223
+ attr_writer :repodir
224
+
225
+ # The repo on GitHub to use for error reports and automatic
226
+ # updates, in `owner/repo` format. Default is the `origin` of a
227
+ # Git repo in `repodir`, if it exists and points at GitHub.
228
+ # Respects the `BOXEN_REPO_NAME` environment variable.
229
+
230
+ def reponame
231
+ override = @reponame || ENV["BOXEN_REPO_NAME"]
232
+ return override unless override.nil?
233
+
234
+ if File.directory? repodir
235
+ ghuri = URI(ghurl)
236
+ url = Dir.chdir(repodir) { `git config remote.origin.url`.strip }
237
+
238
+ # find the path and strip off the .git suffix
239
+ repo_exp = Regexp.new Regexp.escape(ghuri.host) + "[/:]([^/]+/[^/]+)"
240
+ if $?.success? && repo_exp.match(url)
241
+ @reponame = $1.sub /\.git$/, ""
242
+ end
243
+ end
244
+ end
245
+
246
+ attr_writer :reponame
247
+
248
+ # GitHub location (public or GitHub Enterprise)
249
+
250
+ def ghurl
251
+ @ghurl || ENV["BOXEN_GITHUB_ENTERPRISE_URL"] || "https://github.com"
252
+ end
253
+
254
+ attr_writer :ghurl
255
+
256
+ # Repository URL template (required for GitHub Enterprise)
257
+
258
+ def repotemplate
259
+ default = 'https://github.com/%s'
260
+ @repotemplate || ENV["BOXEN_REPO_URL_TEMPLATE"] || default
261
+ end
262
+
263
+ attr_writer :repotemplate
264
+
265
+ # Does this Boxen use a GitHub Enterprise instance?
266
+
267
+ def enterprise?
268
+ ghurl != "https://github.com"
269
+ end
270
+
271
+ # The directory where repos live. Default is
272
+ # `"/Users/#{user}/src"`.
273
+
274
+ def srcdir
275
+ @srcdir || ENV["BOXEN_SRC_DIR"] || "/Users/#{user}/src"
276
+ end
277
+
278
+ attr_writer :srcdir
279
+
280
+ # Don't auto-create issues on failure? Default is `false`.
281
+ # Respects the `BOXEN_NO_ISSUE` environment variable.
282
+
283
+ def stealth?
284
+ !!ENV["BOXEN_NO_ISSUE"] || @stealth
285
+ end
286
+
287
+ attr_writer :stealth
288
+
289
+ # A GitHub OAuth token. Default is `nil`.
290
+
291
+ attr_reader :token
292
+
293
+ def token=(token)
294
+ @token = token
295
+ @api = nil
296
+ end
297
+
298
+ # A local user login. Default is the `USER` environment variable.
299
+
300
+ def user
301
+ @user || ENV["USER"]
302
+ end
303
+
304
+ attr_writer :user
305
+
306
+ def color?
307
+ @color
308
+ end
309
+
310
+ attr_writer :color
311
+
312
+ # The S3 host name. Default is `"s3.amazonaws.com"`.
313
+ # Respects the `BOXEN_S3_HOST` environment variable.
314
+
315
+ def s3host
316
+ @s3host || ENV["BOXEN_S3_HOST"] || "s3.amazonaws.com"
317
+ end
318
+
319
+ attr_writer :s3host
320
+
321
+ # The S3 bucket name. Default is `"boxen-downloads"`.
322
+ # Respects the `BOXEN_S3_BUCKET` environment variable.
323
+
324
+ def s3bucket
325
+ @s3bucket || ENV["BOXEN_S3_BUCKET"] || "boxen-downloads"
326
+ end
327
+
328
+ attr_writer :s3bucket
329
+ end
330
+ end