boxen23 3.1.3a

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (63) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +11 -0
  3. data/.travis.yml +6 -0
  4. data/Gemfile +2 -0
  5. data/LICENSE +20 -0
  6. data/README.md +50 -0
  7. data/boxen.gemspec +29 -0
  8. data/lib/boxen/check.rb +72 -0
  9. data/lib/boxen/checkout.rb +25 -0
  10. data/lib/boxen/cli.rb +61 -0
  11. data/lib/boxen/config.rb +345 -0
  12. data/lib/boxen/error.rb +4 -0
  13. data/lib/boxen/flags.rb +291 -0
  14. data/lib/boxen/hook.rb +47 -0
  15. data/lib/boxen/hook/github_issue.rb +120 -0
  16. data/lib/boxen/hook/web.rb +56 -0
  17. data/lib/boxen/keychain.rb +61 -0
  18. data/lib/boxen/postflight.rb +13 -0
  19. data/lib/boxen/postflight/active.rb +16 -0
  20. data/lib/boxen/postflight/env.rb +29 -0
  21. data/lib/boxen/preflight.rb +13 -0
  22. data/lib/boxen/preflight/creds.rb +149 -0
  23. data/lib/boxen/preflight/directories.rb +32 -0
  24. data/lib/boxen/preflight/etc_my_cnf.rb +12 -0
  25. data/lib/boxen/preflight/identity.rb +16 -0
  26. data/lib/boxen/preflight/os.rb +33 -0
  27. data/lib/boxen/preflight/rbenv.rb +12 -0
  28. data/lib/boxen/preflight/rvm.rb +12 -0
  29. data/lib/boxen/project.rb +20 -0
  30. data/lib/boxen/puppeteer.rb +122 -0
  31. data/lib/boxen/runner.rb +149 -0
  32. data/lib/boxen/service.rb +58 -0
  33. data/lib/boxen/util.rb +19 -0
  34. data/lib/facter/boxen.rb +34 -0
  35. data/script/Boxen +0 -0
  36. data/script/bootstrap +7 -0
  37. data/script/build-keychain-helper +6 -0
  38. data/script/release +38 -0
  39. data/script/tests +10 -0
  40. data/src/keychain-helper.c +85 -0
  41. data/test/boxen/test.rb +7 -0
  42. data/test/boxen_check_test.rb +55 -0
  43. data/test/boxen_checkout_test.rb +42 -0
  44. data/test/boxen_cli_test.rb +39 -0
  45. data/test/boxen_config_test.rb +400 -0
  46. data/test/boxen_directories_test.rb +40 -0
  47. data/test/boxen_flags_test.rb +223 -0
  48. data/test/boxen_hook_github_issue_test.rb +294 -0
  49. data/test/boxen_hook_web_test.rb +58 -0
  50. data/test/boxen_keychain_test.rb +21 -0
  51. data/test/boxen_postflight_active_test.rb +29 -0
  52. data/test/boxen_postflight_env_test.rb +6 -0
  53. data/test/boxen_preflight_creds_test.rb +177 -0
  54. data/test/boxen_preflight_etc_my_cnf_test.rb +10 -0
  55. data/test/boxen_preflight_rvm_test.rb +10 -0
  56. data/test/boxen_project_test.rb +14 -0
  57. data/test/boxen_puppeteer_test.rb +101 -0
  58. data/test/boxen_runner_test.rb +171 -0
  59. data/test/boxen_service_test.rb +39 -0
  60. data/test/boxen_util_test.rb +21 -0
  61. data/test/fixtures/repo/modules/projects/manifests/first-project.pp +0 -0
  62. data/test/fixtures/repo/modules/projects/manifests/second-project.pp +0 -0
  63. metadata +257 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 6bb9a890428b37ca3a51cd2d89c0338f9c499f437eca543fdb397ce78a402541
4
+ data.tar.gz: 4ef6d21ec943420af24918e68c9743920b84354f24f2441065b2d186a994d51c
5
+ SHA512:
6
+ metadata.gz: 629e944de0253d6bb554d22b58c8714088c13b2ea1c938e07a348f0cc56e811483c3e5892bbdb6b0a9c12db0c1cd95bf4f2cc3a8ed844fff9b0a4c4678d2c7ab
7
+ data.tar.gz: eb5ab9e2ad44962ef06a0823cfff10f52573e52aa751267754b3b4021b21e501bcb06712f3debf165c28e2617b4f253eb2cd8198413e345caaffc39477c88f29
data/.gitignore ADDED
@@ -0,0 +1,11 @@
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
data/.travis.yml ADDED
@@ -0,0 +1,6 @@
1
+ ---
2
+ script: "./script/tests"
3
+ gemfile: "this/does/not/exist"
4
+ rvm:
5
+ - 2.0.0
6
+ - 2.3.3
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,50 @@
1
+ # Boxen [![Build Status](https://travis-ci.org/boxen/boxen.png?branch=master)](https://travis-ci.org/boxen/boxen)
2
+
3
+ Manage Mac development boxes with love (and Puppet).
4
+
5
+ ## Rules for Services
6
+
7
+ 0. Run on a nonstandard port, usually default port + 1000 or 10000.
8
+
9
+ 0. Install with a custom Boxen homebrew formula.
10
+
11
+ 0. Suffix the Homebrew package's version, starting with `-boxen1`.
12
+
13
+ 0. Run as a launchd service in the `dev` namespace, e.g.,
14
+ `dev.dnsmasq`.
15
+
16
+ 0. Store config, data, and log files in
17
+ `$BOXEN_HOME/{config,data,log}`. This will normally require
18
+ customization of a service's Homebrew formula.
19
+
20
+ Sometimes it's not possible to follow these rules, but try hard.
21
+
22
+ ## Projects from the CLI
23
+
24
+ We use a totally awful hack to do from-the-cli project installs of projects.
25
+ We create a file in "$BOXEN_HOME/repodir" called .projects, with a single line.
26
+ That line is made up of projects separated by commas.
27
+ We then read that into a Puppet fact in Puppet-land, and that checks for
28
+ classes that match those project names, and includes them in the catalog.
29
+
30
+ We can't pass a `FACTER_` env var because sudo has `env_reset`
31
+ and we can't just modify the sudoers file due to a chicken-egg problem.
32
+
33
+ ## Hooks
34
+
35
+ 0. All hooks must be in the namespace `Boxen::Hook::MyThing`.
36
+
37
+ 0. All hooks must subclass from `Boxen::Hook`
38
+
39
+ 0. All hooks must provide a private instance method `required_environment_variables` that returns an array with at least one entry.
40
+
41
+ 0. All hooks must provide a private instance method `#call`.
42
+
43
+ ## Contributing
44
+
45
+ Use the OS X system Ruby (2.0 or newer). Run `script/tests` often. Open PR's.
46
+ Use the CI.
47
+
48
+ ## Halp!
49
+
50
+ Use Issues or #boxen on irc.freenode.net.
data/boxen.gemspec ADDED
@@ -0,0 +1,29 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |gem|
4
+ gem.name = "boxen23"
5
+ gem.version = "3.1.3a"
6
+ # Thanks go out to the previous maintainers John Barnette, Will
7
+ # Farrington, David Goodlad and Mike McQuaid for getting this project
8
+ # to where it is today.
9
+ gem.authors = ["Jacob Bednarz"]
10
+ gem.email = ["jacob.bednarz@gmail.com"]
11
+ gem.description = "Manage Mac development boxes with love (and Puppet). for Ruby 2.3"
12
+ gem.summary = "You know, for laptops and stuff."
13
+ gem.homepage = "https://github.com/boxen/boxen"
14
+ gem.license = 'MIT'
15
+
16
+ gem.files = `git ls-files`.split $/
17
+ gem.test_files = gem.files.grep /^test/
18
+ gem.require_paths = ["lib"]
19
+
20
+ gem.add_dependency "ansi", "~> 1.5"
21
+ gem.add_dependency "hiera", "~> 3.4.2"
22
+ gem.add_dependency "highline", "~> 1.7.8"
23
+ gem.add_dependency "json_pure", [">= 1.8.3", "< 2.0"]
24
+ gem.add_dependency "octokit", ["~> 3.8", ">= 3.8.0"]
25
+ gem.add_dependency "puppet", "~> 4.10"
26
+
27
+ gem.add_development_dependency "minitest", "4.4.0" # pinned for mocha
28
+ gem.add_development_dependency "mocha", ["~> 1.2", "< 1.2.1"]
29
+ end
@@ -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,345 @@
1
+ require "boxen/keychain"
2
+ require "boxen/project"
3
+ require "boxen/util"
4
+ require "fileutils"
5
+ require "json"
6
+ require "octokit"
7
+ require "shellwords"
8
+
9
+ module Boxen
10
+
11
+ # All configuration for Boxen, whether it's loaded from command-line
12
+ # args, environment variables, config files, or the keychain.
13
+
14
+ class Config
15
+ def self.load(&block)
16
+ new do |config|
17
+ file = "#{config.homedir}/config/boxen/defaults.json"
18
+
19
+ if File.file? file
20
+ attrs = JSON.parse File.read file
21
+
22
+ attrs.each do |key, value|
23
+ if !value.nil? && config.respond_to?(selector = "#{key}=")
24
+ config.send selector, value
25
+ end
26
+ end
27
+ end
28
+
29
+ if Boxen::Util.osx?
30
+ keychain = Boxen::Keychain.new config.user
31
+ config.token = keychain.token
32
+ else
33
+ config.token = ''
34
+ end
35
+
36
+ if config.enterprise?
37
+ # configure to talk to GitHub Enterprise
38
+ Octokit.configure do |c|
39
+ c.api_endpoint = "#{config.ghurl}/api/v3"
40
+ c.web_endpoint = config.ghurl
41
+ end
42
+ end
43
+
44
+ yield config if block_given?
45
+ end
46
+ end
47
+
48
+ # Save `config`. Returns `config`. Note that this only saves data,
49
+ # not flags. For example, `login` will be saved, but `stealth?`
50
+ # won't.
51
+
52
+ def self.save(config)
53
+ attrs = {
54
+ :email => config.email,
55
+ :fde => config.fde?,
56
+ :homedir => config.homedir,
57
+ :login => config.login,
58
+ :name => config.name,
59
+ :puppetdir => config.puppetdir,
60
+ :repodir => config.repodir,
61
+ :reponame => config.reponame,
62
+ :ghurl => config.ghurl,
63
+ :srcdir => config.srcdir,
64
+ :user => config.user,
65
+ :repotemplate => config.repotemplate,
66
+ :s3host => config.s3host,
67
+ :s3bucket => config.s3bucket
68
+ }
69
+
70
+ file = "#{config.homedir}/config/boxen/defaults.json"
71
+ FileUtils.mkdir_p File.dirname file
72
+
73
+ File.open file, "wb" do |f|
74
+ f.write JSON.generate Hash[attrs.reject { |k, v| v.nil? }]
75
+ end
76
+
77
+ if Boxen::Util.osx?
78
+ keychain = Boxen::Keychain.new config.user
79
+ keychain.token = config.token
80
+ end
81
+
82
+ config
83
+ end
84
+
85
+ # Create a new instance. Yields `self` if `block` is given.
86
+
87
+ def initialize(&block)
88
+ @fde = true
89
+ @pull = true
90
+
91
+ yield self if block_given?
92
+ end
93
+
94
+ # Create an API instance using the current user creds. A new
95
+ # instance is created any time `token` changes.
96
+
97
+ def api
98
+ @api ||= Octokit::Client.new :login => token, :password => 'x-oauth-basic'
99
+ end
100
+
101
+ # Spew a bunch of debug logging? Default is `false`.
102
+
103
+ def debug?
104
+ !!@debug
105
+ end
106
+
107
+ attr_writer :debug
108
+
109
+ # A GitHub user's public email.
110
+
111
+ attr_accessor :email
112
+
113
+ # The shell script that loads Boxen's environment.
114
+
115
+ def envfile
116
+ "#{homedir}/env.sh"
117
+ end
118
+
119
+ # Is full disk encryption required? Default is `true`. Respects
120
+ # the `BOXEN_NO_FDE` environment variable.
121
+
122
+ def fde?
123
+ !ENV["BOXEN_NO_FDE"] && @fde
124
+ end
125
+
126
+ attr_writer :fde
127
+
128
+ # Boxen's home directory. Default is `"/opt/boxen"`. Respects the
129
+ # `BOXEN_HOME` environment variable.
130
+
131
+ def homedir
132
+ @homedir || ENV["BOXEN_HOME"] || "/opt/boxen"
133
+ end
134
+
135
+ attr_writer :homedir
136
+
137
+ # Boxen's log file. Default is `"#{repodir}/log/boxen.log"`.
138
+ # Respects the `BOXEN_LOG_FILE` environment variable. The log is
139
+ # overwritten on every run.
140
+
141
+ def logfile
142
+ @logfile || ENV["BOXEN_LOG_FILE"] || "#{repodir}/log/boxen.log"
143
+ end
144
+
145
+ attr_writer :logfile
146
+
147
+ # A GitHub user login. Default is `nil`.
148
+
149
+ attr_accessor :login
150
+
151
+ # A GitHub user's profile name.
152
+
153
+ attr_accessor :name
154
+
155
+ # Just go through the motions? Default is `false`.
156
+
157
+ def pretend?
158
+ !!@pretend
159
+ end
160
+
161
+ attr_writer :pretend
162
+
163
+ # Run a profiler on Puppet? Default is `false`.
164
+
165
+ def profile?
166
+ !!@profile
167
+ end
168
+
169
+ attr_writer :profile
170
+
171
+ # Enable the Puppet future parser? Default is `false`.
172
+
173
+ def future_parser?
174
+ !!@future_parser
175
+ end
176
+
177
+ attr_writer :future_parser
178
+
179
+ # Skip installing librarian-puppet
180
+
181
+ def skip_puppetfile?
182
+ !!@skip_puppetfile
183
+ end
184
+
185
+ attr_writer :skip_puppetfile
186
+
187
+ # Enable puppet reports ? Default is `false`.
188
+
189
+ def report?
190
+ !!@report
191
+ end
192
+
193
+ attr_writer :report
194
+
195
+ # Enable generation of dependency graphs.
196
+
197
+ def graph?
198
+ !!@graph
199
+ end
200
+
201
+ attr_writer :graph
202
+
203
+ # An Array of Boxen::Project entries, one for each project Boxen
204
+ # knows how to manage.
205
+ #
206
+ # FIX: Revisit this once we restructure template projects. It's
207
+ # broken for several reasons: It assumes paths that won't be
208
+ # right, and it assumes projects live in the same repo as this
209
+ # file.
210
+
211
+ def projects
212
+ files = Dir["#{repodir}/modules/projects/manifests/*.pp"]
213
+ names = files.map { |m| File.basename m, ".pp" }.sort
214
+
215
+ names.map do |name|
216
+ Boxen::Project.new "#{srcdir}/#{name}"
217
+ end
218
+ end
219
+
220
+ # The directory where Puppet expects configuration (which we don't
221
+ # use) and runtime information (which we generally don't care
222
+ # about). Default is `/tmp/boxen/puppet`. Respects the
223
+ # `BOXEN_PUPPET_DIR` environment variable.
224
+
225
+ def puppetdir
226
+ @puppetdir || ENV["BOXEN_PUPPET_DIR"] || "/tmp/boxen/puppet"
227
+ end
228
+
229
+ attr_writer :puppetdir
230
+
231
+ # The directory of the custom Boxen repo for an org. Default is
232
+ # `Dir.pwd`. Respects the `BOXEN_REPO_DIR` environment variable.
233
+
234
+ def repodir
235
+ @repodir || ENV["BOXEN_REPO_DIR"] || Dir.pwd
236
+ end
237
+
238
+ attr_writer :repodir
239
+
240
+ # The repo on GitHub to use for error reports and automatic
241
+ # updates, in `owner/repo` format. Default is the `origin` of a
242
+ # Git repo in `repodir`, if it exists and points at GitHub.
243
+ # Respects the `BOXEN_REPO_NAME` environment variable.
244
+
245
+ def reponame
246
+ override = @reponame || ENV["BOXEN_REPO_NAME"]
247
+ return override unless override.nil?
248
+
249
+ if File.directory? repodir
250
+ ghuri = URI(ghurl)
251
+ url = Dir.chdir(repodir) { `git config remote.origin.url`.strip }
252
+
253
+ # find the path and strip off the .git suffix
254
+ repo_exp = Regexp.new Regexp.escape(ghuri.host) + "[/:]([^/]+/[^/]+)"
255
+ if $?.success? && repo_exp.match(url)
256
+ @reponame = $1.sub /\.git$/, ""
257
+ end
258
+ end
259
+ end
260
+
261
+ attr_writer :reponame
262
+
263
+ # GitHub location (public or GitHub Enterprise)
264
+
265
+ def ghurl
266
+ @ghurl || ENV["BOXEN_GITHUB_ENTERPRISE_URL"] || "https://github.com"
267
+ end
268
+
269
+ attr_writer :ghurl
270
+
271
+ # Repository URL template (required for GitHub Enterprise)
272
+
273
+ def repotemplate
274
+ default = 'https://github.com/%s'
275
+ @repotemplate || ENV["BOXEN_REPO_URL_TEMPLATE"] || default
276
+ end
277
+
278
+ attr_writer :repotemplate
279
+
280
+ # Does this Boxen use a GitHub Enterprise instance?
281
+
282
+ def enterprise?
283
+ ghurl != "https://github.com"
284
+ end
285
+
286
+ # The directory where repos live. Default is
287
+ # `"/Users/#{user}/src"`.
288
+
289
+ def srcdir
290
+ @srcdir || ENV["BOXEN_SRC_DIR"] || "/Users/#{user}/src"
291
+ end
292
+
293
+ attr_writer :srcdir
294
+
295
+ # Don't auto-create issues on failure? Default is `false`.
296
+ # Respects the `BOXEN_NO_ISSUE` environment variable.
297
+
298
+ def stealth?
299
+ !!ENV["BOXEN_NO_ISSUE"] || @stealth
300
+ end
301
+
302
+ attr_writer :stealth
303
+
304
+ # A GitHub OAuth token. Default is `nil`.
305
+
306
+ attr_reader :token
307
+
308
+ def token=(token)
309
+ @token = token
310
+ @api = nil
311
+ end
312
+
313
+ # A local user login. Default is the `USER` environment variable.
314
+
315
+ def user
316
+ @user || ENV["USER"]
317
+ end
318
+
319
+ attr_writer :user
320
+
321
+ def color?
322
+ @color
323
+ end
324
+
325
+ attr_writer :color
326
+
327
+ # The S3 host name. Default is `"s3.amazonaws.com"`.
328
+ # Respects the `BOXEN_S3_HOST` environment variable.
329
+
330
+ def s3host
331
+ @s3host || ENV["BOXEN_S3_HOST"] || "s3.amazonaws.com"
332
+ end
333
+
334
+ attr_writer :s3host
335
+
336
+ # The S3 bucket name. Default is `"boxen-downloads"`.
337
+ # Respects the `BOXEN_S3_BUCKET` environment variable.
338
+
339
+ def s3bucket
340
+ @s3bucket || ENV["BOXEN_S3_BUCKET"] || "boxen-downloads"
341
+ end
342
+
343
+ attr_writer :s3bucket
344
+ end
345
+ end