3a516de9 by Jeff Balicki

Drop files from .gitignore

1 parent 1907bd8c
Showing 1000 changed files with 0 additions and 3151 deletions

Too many changes to show.

To preserve performance only 1000 of 1000+ files are displayed.

No preview for this file type
1 DB_HOST=127.0.0.1
2 DB_NAME=commonwell_broker
3 DB_USER=root
4 DB_PASS=jeff518862
5
6
7 merchant_id = "376299332"
8 api_id = "bdE8c883e75941978540fab06b857C7B"
9
10
11 external_payment_client_id = "i3dgneUrHPXFyfDQWCyueNmNcI5uh441"
12 external_payment_client_secret = "0TtB9dgxvXZYSk7QjI8Ib15Q29Bl-wZYHjW-V1O3vrxAa$
13 external_payment_audience = "https://cmig-dev-payment-service.insurcloud.ca/"
14 external_payment = "https://api-dev03.nonprod.cmig.insurcloud.ca/payment-online$
15 external_payment_token = "https://insurcloud-dev.auth0.com/oauth/token"
...\ No newline at end of file ...\ No newline at end of file
No preview for this file type
1 <?php
2
3 // autoload.php @generated by Composer
4
5 require_once __DIR__ . '/composer/autoload_real.php';
6
7 return ComposerAutoloaderInitc870c977e69b00574a49c4be5d77a175::getLoader();
1 #!/usr/bin/env ruby
2 #
3 # This file was generated by RubyGems.
4 #
5 # The application 'bundler' is installed as part of a gem, and
6 # this file is here to facilitate running it.
7 #
8
9 require 'rubygems'
10
11 version = ">= 0.a"
12
13 str = ARGV.first
14 if str
15 str = str.b[/\A_(.*)_\z/, 1]
16 if str and Gem::Version.correct?(str)
17 version = str
18 ENV['BUNDLER_VERSION'] = str
19
20 ARGV.shift
21 end
22 end
23
24 if Gem.respond_to?(:activate_bin_path)
25 load Gem.activate_bin_path('bundler', 'bundle', version)
26 else
27 gem "bundler", version
28 load Gem.bin_path("bundler", "bundle", version)
29 end
1 #!/usr/bin/env ruby
2 #
3 # This file was generated by RubyGems.
4 #
5 # The application 'bundler' is installed as part of a gem, and
6 # this file is here to facilitate running it.
7 #
8
9 require 'rubygems'
10
11 version = ">= 0.a"
12
13 str = ARGV.first
14 if str
15 str = str.b[/\A_(.*)_\z/, 1]
16 if str and Gem::Version.correct?(str)
17 version = str
18 ENV['BUNDLER_VERSION'] = str
19
20 ARGV.shift
21 end
22 end
23
24 if Gem.respond_to?(:activate_bin_path)
25 load Gem.activate_bin_path('bundler', 'bundler', version)
26 else
27 gem "bundler", version
28 load Gem.bin_path("bundler", "bundler", version)
29 end
1 #!/usr/bin/env ruby
2 #
3 # This file was generated by RubyGems.
4 #
5 # The application 'capistrano' is installed as part of a gem, and
6 # this file is here to facilitate running it.
7 #
8
9 require 'rubygems'
10
11 Gem.use_gemdeps
12
13 version = ">= 0.a"
14
15 str = ARGV.first
16 if str
17 str = str.b[/\A_(.*)_\z/, 1]
18 if str and Gem::Version.correct?(str)
19 version = str
20 ARGV.shift
21 end
22 end
23
24 if Gem.respond_to?(:activate_bin_path)
25 load Gem.activate_bin_path('capistrano', 'cap', version)
26 else
27 gem "capistrano", version
28 load Gem.bin_path("capistrano", "cap", version)
29 end
1 #!/usr/bin/env ruby
2 #
3 # This file was generated by RubyGems.
4 #
5 # The application 'capistrano' is installed as part of a gem, and
6 # this file is here to facilitate running it.
7 #
8
9 require 'rubygems'
10
11 Gem.use_gemdeps
12
13 version = ">= 0.a"
14
15 str = ARGV.first
16 if str
17 str = str.b[/\A_(.*)_\z/, 1]
18 if str and Gem::Version.correct?(str)
19 version = str
20 ARGV.shift
21 end
22 end
23
24 if Gem.respond_to?(:activate_bin_path)
25 load Gem.activate_bin_path('capistrano', 'capify', version)
26 else
27 gem "capistrano", version
28 load Gem.bin_path("capistrano", "capify", version)
29 end
1 #!/usr/bin/env ruby
2 #
3 # This file was generated by RubyGems.
4 #
5 # The application 'rake' is installed as part of a gem, and
6 # this file is here to facilitate running it.
7 #
8
9 require 'rubygems'
10
11 Gem.use_gemdeps
12
13 version = ">= 0.a"
14
15 str = ARGV.first
16 if str
17 str = str.b[/\A_(.*)_\z/, 1]
18 if str and Gem::Version.correct?(str)
19 version = str
20 ARGV.shift
21 end
22 end
23
24 if Gem.respond_to?(:activate_bin_path)
25 load Gem.activate_bin_path('rake', 'rake', version)
26 else
27 gem "rake", version
28 load Gem.bin_path("rake", "rake", version)
29 end
1 /.bundle/
2 /.yardoc
3 /Gemfile.lock
4 /_yardoc/
5 /coverage/
6 /doc/
7 /log/
8 /pkg/
9 /spec/reports/
10 /tmp/
11 *.bundle
12 *.so
13 *.o
14 *.a
15 mkmf.log
1 AllCops:
2 DisplayCopNames: true
3 DisplayStyleGuide: true
4 TargetRubyVersion: 1.9
5 Exclude:
6 - "*.gemspec"
7
8 Metrics/AbcSize:
9 Exclude:
10 - "test/**/*"
11
12 Metrics/MethodLength:
13 Exclude:
14 - "test/**/*"
15
16 Metrics/ClassLength:
17 Exclude:
18 - "test/**/*"
19
20 Style/BarePercentLiterals:
21 EnforcedStyle: percent_q
22
23 Style/ClassAndModuleChildren:
24 Enabled: false
25
26 Style/Documentation:
27 Enabled: false
28
29 Style/DoubleNegation:
30 Enabled: false
31
32 Style/HashSyntax:
33 EnforcedStyle: hash_rockets
34
35 Style/SpaceAroundEqualsInParameterDefault:
36 EnforcedStyle: no_space
37
38 Style/StringLiterals:
39 EnforcedStyle: double_quotes
40
41 Style/TrivialAccessors:
42 AllowPredicates: true
1 language: ruby
2 rvm:
3 - 1.9
4 - 2.0
5 - 2.1
6 - 2.2
7 - 2.3.1
8 - 2.4.0
9 env:
10 - sshkit="master"
11 - sshkit="= 1.7.1"
12 - sshkit="= 1.6.1"
13 matrix:
14 exclude:
15 # Older versions of SSHKit don't work with Ruby 2.4, so skip those
16 - rvm: 2.4.0
17 env: sshkit="= 1.7.1"
18 - rvm: 2.4.0
19 env: sshkit="= 1.6.1"
20 include:
21 # Run Danger only once, on 2.4.0
22 - rvm: 2.4.0
23 script: bundle exec danger
24
25 before_install: gem install bundler --conservative --version '~> 1.13.7'
1 # Airbrussh Change Log
2
3 All notable changes to this project will be documented in this file. This project adheres to [Semantic Versioning][Semver].
4
5 ## [Unreleased]
6
7 * Your contribution here!
8
9 ## [1.3.0][] (2017-06-16)
10
11 * [#109](https://github.com/mattbrictson/airbrussh/pull/109): Add configurable task prefix - [@gondalez](https://github.com/gondalez)
12
13 ## [1.2.0][] (2017-04-14)
14
15 * [#95](https://github.com/mattbrictson/airbrussh/pull/95): colorize LogMessage label on WARN level and above - [@klyonrad](https://github.com/klyonrad)
16 * [#106](https://github.com/mattbrictson/airbrussh/pull/106): Remove the `log_file` parameter from the `CommandFormatter#exit_message` method; it was unused - [@mattbrictson](https://github.com/mattbrictson)
17
18 ## [1.1.2][] (2017-01-02)
19
20 * Add Ruby 2.4.0 to testing matrix and fix Ruby 2.4 deprecation warnings
21
22 ## [1.1.1][] (2016-09-09)
23
24 * When a Capistrano deploy fails and the error log is dumped to the console,
25 Airbrussh no longer truncates the error output. This ensures that important
26 troubleshooting information is not lost.
27 [#91](https://github.com/mattbrictson/airbrussh/issues/91)
28
29 ## [1.1.0][] (2016-07-26)
30
31 * Use default color for info messages.
32 When using the `gray` color on some implementation of the `solarized`
33 theme the text is not visible. The `solarized` theme is popular and
34 bugs have been reported about missed error messages, so this patch
35 switches these messages to the default color.
36 (see [#84](https://github.com/mattbrictson/airbrussh/issues/84))
37
38 ## [1.0.2][] (2016-05-13)
39
40 * Fix a crash that can happen in certain multi-server deployments when
41 Capistrano's `invoke` is used to switch Rake tasks in the middle of SSHKit
42 execution ([#78](https://github.com/mattbrictson/airbrussh/issues/78),
43 [#80](https://github.com/mattbrictson/airbrussh/pull/80))
44
45 ## [1.0.1][] (2016-03-21)
46
47 * Fix support for fake TTYs reporting a 0 width console like Ruby's PTY library [#76](https://github.com/mattbrictson/airbrussh/pull/76)
48
49 ## [1.0.0][] (2016-02-27)
50
51 * No changes since 1.0.0.beta1.
52
53 ## [1.0.0.beta1][] (2015-12-27)
54
55 Breaking Changes:
56
57 * None
58
59 Added:
60
61 * Airbrussh can now be configured with an options Hash passed to the
62 `Airbrussh::Formatter` constructor. This is in order to standardize how all
63 SSHKit formatters are configured
64 (see [SSHKit #308](https://github.com/capistrano/sshkit/pull/308)).
65
66 ## [0.8.0][] (2015-11-20)
67
68 * Airbrussh now displays the correct user@host output in the following edge-cases:
69 * Inside an SSHKit `as(:user => "...")` block
70 * When a user is specified using `set :ssh_options, :user => "..."` ([see #65](https://github.com/mattbrictson/airbrussh/issues/65))
71
72 ## [0.7.0][] (2015-08-08)
73
74 Fixes:
75
76 * Handle truncation of raw/non-UTF8 output without crashing ([#57](https://github.com/mattbrictson/airbrussh/issues/57))
77
78 Other changes:
79
80 * Re-implement the "tail log on deploy failure" feature in pure Ruby ([#59](https://github.com/mattbrictson/airbrussh/issues/59))
81 * Code of contact added to the project
82 * Tests now run on Windows ([#55](https://github.com/mattbrictson/airbrussh/issues/55))
83
84 ## [0.6.0][] (2015-07-10)
85
86 This is another release with mostly behind-the-scenes changes. If you notice any differences in Airbrussh's behavior in this version, [please report an issue](https://github.com/mattbrictson/airbrussh/issues).
87
88 Other changes:
89
90 * Bundler 1.10 is now required to build and test airbrussh (this doesn't affect users of airbrussh at all).
91 * If the directory containing the log file doesn't exist, Airbrussh will now attempt to create it using `FileUtils.mkdir_p` ([#30](https://github.com/mattbrictson/airbrussh/issues/30))
92 * By default Airbrussh now always prints `Using airbrussh format.` when it starts up. In previous versions, a bug caused this message to sometimes not be shown. To change or disable this message, set the `banner` configuration option as explained in the README.
93
94 ## [0.5.1][] (2015-06-24)
95
96 * Fix `NameError: uninitialized constant Airbrussh::SimpleDelegator`
97
98 ## [0.5.0][] (2015-06-24)
99
100 There are no changes to the actual behavior and feature set of Airbrussh in this release.
101
102 There are, however, many behind-the-scenes changes and improvements to overall code quality. This release also adds support for upcoming versions of SSHKit.
103
104 * Added Rubocop enforcement to Travis
105 * Added Code Climate and Coveralls checks (see badges in the README)
106 * Airbrussh now has good test coverage, and is tested by Travis against a matrix of Ruby and SSHKit versions ([@robd](https://github.com/robd))
107 * Changes to support the new SSHKit formatter API, as introduced in [SSHKit #257](https://github.com/capistrano/sshkit/pull/257) ([@robd](https://github.com/robd))
108 * `Airbrussh.reset` has been removed
109 * Airbrussh now has its own ANSI color code; it no longer relies on a third-party gem (i.e. `colorize`)
110
111 ## [0.4.1][] (2015-05-06)
112
113 * Fix `Marshal.dump` warnings by removing `deep_copy` workaround that it is no longer needed for the latest SSHKit ([#10](https://github.com/mattbrictson/airbrussh/issues/10)).
114
115 ## [0.4.0][] (2015-05-03)
116
117 * Changes to ensure compatibility with the upcoming version of SSHKit ([ec3122b](https://github.com/mattbrictson/airbrussh/commit/ec3122b101de53f2304723da842d5c8b6f70f4f3)).
118 * Explicitly specify UTF-8 encoding for source files, for Ruby 1.9.3 compatibility ([#9](https://github.com/mattbrictson/airbrussh/issues/9)).
119
120 ## [0.3.0][] (2015-03-28)
121
122 * New `config.banner` option allows startup message to be disabled or changed (suggestion from [@justindowning](https://github.com/justindowning))
123 * New `config.command_output` option gives full control of whether airbrussh shows or hides the stderr and stdout data received from remote commands; see the usage section of the README for further explanation (suggestion from [@carlesso](https://github.com/carlesso))
124
125 ## [0.2.1][] (2015-03-02)
126
127 * Un-pin SSHKit dependency now that SSHKit 1.7.1 has been released.
128
129 ## [0.2.0][] (2015-03-02)
130
131 * Pin SSHKit dependency at `~> 1.6.1` to avoid a [bug in 1.7.0](https://github.com/capistrano/sshkit/issues/226) that causes command exit statuses to be omitted from the log.
132
133 ## 0.0.1 (2015-02-19)
134
135 * Initial release
136
137 [Semver]: http://semver.org
138 [Unreleased]: https://github.com/mattbrictson/airbrussh/compare/v1.3.0...HEAD
139 [1.3.0]: https://github.com/mattbrictson/airbrussh/compare/v1.2.0...v1.3.0
140 [1.2.0]: https://github.com/mattbrictson/airbrussh/compare/v1.1.2...v1.2.0
141 [1.1.2]: https://github.com/mattbrictson/airbrussh/compare/v1.1.1...v1.1.2
142 [1.1.1]: https://github.com/mattbrictson/airbrussh/compare/v1.1.0...v1.1.1
143 [1.1.0]: https://github.com/mattbrictson/airbrussh/compare/v1.0.2...v1.1.0
144 [1.0.2]: https://github.com/mattbrictson/airbrussh/compare/v1.0.1...v1.0.2
145 [1.0.1]: https://github.com/mattbrictson/airbrussh/compare/v1.0.0...v1.0.1
146 [1.0.0]: https://github.com/mattbrictson/airbrussh/compare/v1.0.0.beta1...v1.0.0
147 [1.0.0.beta1]: https://github.com/mattbrictson/airbrussh/compare/v0.8.0...v1.0.0.beta1
148 [0.8.0]: https://github.com/mattbrictson/airbrussh/compare/v0.7.0...v0.8.0
149 [0.7.0]: https://github.com/mattbrictson/airbrussh/compare/v0.6.0...v0.7.0
150 [0.6.0]: https://github.com/mattbrictson/airbrussh/compare/v0.5.1...v0.6.0
151 [0.5.1]: https://github.com/mattbrictson/airbrussh/compare/v0.5.0...v0.5.1
152 [0.5.0]: https://github.com/mattbrictson/airbrussh/compare/v0.4.1...v0.5.0
153 [0.4.1]: https://github.com/mattbrictson/airbrussh/compare/v0.4.0...v0.4.1
154 [0.4.0]: https://github.com/mattbrictson/airbrussh/compare/v0.3.0...v0.4.0
155 [0.3.0]: https://github.com/mattbrictson/airbrussh/compare/v0.2.1...v0.3.0
156 [0.2.1]: https://github.com/mattbrictson/airbrussh/compare/v0.2.0...v0.2.1
157 [0.2.0]: https://github.com/mattbrictson/airbrussh/compare/v0.0.1...v0.2.0
1 Contributor Code of Conduct
2
3 As contributors and maintainers of this project, we pledge to respect all
4 people who contribute through reporting issues, posting feature requests,
5 updating documentation, submitting pull requests or patches, and other
6 activities.
7
8 We are committed to making participation in this project a harassment-free
9 experience for everyone, regardless of level of experience, gender, gender
10 identity and expression, sexual orientation, disability, personal appearance,
11 body size, race, ethnicity, age, or religion.
12
13 Examples of unacceptable behavior by participants include the use of sexual
14 language or imagery, derogatory comments or personal attacks, trolling, public
15 or private harassment, insults, or other unprofessional conduct.
16
17 Project maintainers have the right and responsibility to remove, edit, or
18 reject comments, commits, code, wiki edits, issues, and other contributions
19 that are not aligned to this Code of Conduct. Project maintainers who do not
20 follow the Code of Conduct may be removed from the project team.
21
22 This code of conduct applies both within project spaces and in public spaces
23 when an individual is representing the project or its community.
24
25 Instances of abusive, harassing, or otherwise unacceptable behavior may be
26 reported by opening an issue or contacting one or more of the project
27 maintainers.
28
29 This Code of Conduct is adapted from the Contributor Covenant
30 (http://contributor-covenant.org), version 1.1.0, available at
31 http://contributor-covenant.org/version/1/1/0/
1 # Contributing to airbrussh
2
3 Have a feature idea, bug fix, or refactoring suggestion? Contributions are welcome!
4
5 ## Pull requests
6
7 1. Check [Issues][] to see if your contribution has already been discussed and/or implemented.
8 2. If not, open an issue to discuss your contribution. I won't accept all changes and do not want to waste your time.
9 3. Once you have the :thumbsup:, fork the repo, make your changes, and open a PR.
10 4. Don't forget to add your contribution and credit yourself in `CHANGELOG.md`!
11
12 ## Coding guidelines
13
14 * This project has a coding style enforced by [RuboCop][]. Use hash rockets and double-quoted strings, and otherwise try to follow the [Ruby style guide][style].
15 * Writing tests is strongly encouraged! This project uses Minitest.
16
17 ## Getting started
18
19 Note that Bundler 1.10 is required for development. Run `gem update bundler` to get the latest version.
20
21 After checking out the airbrussh repo, run `bin/setup` to install dependencies. Run `rake` to execute airbrussh's tests and RuboCop checks.
22
23 Airbrussh is designed to work against multiple versions of SSHKit and Ruby. In order to test this, we use the environment variable `sshkit` in order to run the tests against a specific version. The combinations of sshkit and ruby we support are specified in [.travis.yml](.travis.yml). To test all the versions locally, there is a `test_all.rb` bin file. This installs the gems and runs the tests for each sshkit version in [.travis.yml](.travis.yml). *Note: this will update your `Gemfile.lock` as each SSHKit gem version is installed. The gem version is restored to the default when the script exits.*
24
25 A Guardfile is also present, so if you'd like to use Guard to do a TDD workflow, then:
26
27 1. Run `bundle install --with extras` to get the optional guard dependencies
28 2. Run `guard` to monitor the filesystem and automatically run tests as you work
29
30 [Issues]: https://github.com/mattbrictson/airbrussh/issues
31 [RuboCop]: https://github.com/bbatsov/rubocop
32 [style]: https://github.com/bbatsov/ruby-style-guide
1 danger.import_dangerfile(github: "capistrano/danger")
1 source "https://rubygems.org"
2
3 # Specify your gem's dependencies in airbrussh.gemspec
4 gemspec
5
6 # Optional development dependencies; requires bundler >= 1.10.
7 # Note that these gems assume a Ruby 2.2 environment. Install them using:
8 #
9 # bundle install --with extras
10 #
11 group :extras, :optional => true do
12 gem "chandler"
13 gem "guard", ">= 2.2.2"
14 gem "guard-minitest"
15 gem "rb-fsevent"
16 gem "terminal-notifier-guard"
17 end
18
19 # Danger is used by Travis, but only for Ruby 2.0+
20 gem "danger", "~> 4.3" unless RUBY_VERSION == "1.9.3"
21
22 if (sshkit_version = ENV["sshkit"])
23 requirement = begin
24 Gem::Dependency.new("sshkit", sshkit_version).requirement
25 rescue ArgumentError
26 user, branch =
27 if sshkit_version.include?("#")
28 sshkit_version.split("#")
29 else
30 ["capistrano", sshkit_version]
31 end
32 { :github => "#{user}/sshkit", :branch => branch }
33 end
34 gem "sshkit", requirement
35 end
36
37 # json 2.0+ is not compatible with Ruby 1.9, so pin at older version.
38 gem "json", "~> 1.8" if RUBY_VERSION == "1.9.3"
39
40 # net-ssh 3.0+ is not compatible with Ruby 1.9, so pin at older version.
41 gem "net-ssh", "~> 2.8" if RUBY_VERSION == "1.9.3"
42
43 # term-ansicolor 1.4.0+ is not compatible with Ruby 1.9, so pin older version.
44 gem "term-ansicolor", "~> 1.3.2" if RUBY_VERSION == "1.9.3"
45
46 # tins 1.7.0+ is not compatible with Ruby 1.9, so pin at older version.
47 gem "tins", "~> 1.6.0" if RUBY_VERSION == "1.9.3"
1 guard :minitest do
2 # with Minitest::Unit
3 watch(%r{^test/(.*)\/?(.*)_test\.rb$})
4 watch(%r{^lib/(.*/)?([^/]+)\.rb$}) { |m| "test/#{m[1]}#{m[2]}_test.rb" }
5 watch(%r{^test/minitest_helper\.rb$}) { "test" }
6 end
1 The MIT License (MIT)
2
3 Copyright (c) 2016 Matt Brictson
4
5 Permission is hereby granted, free of charge, to any person obtaining a copy
6 of this software and associated documentation files (the "Software"), to deal
7 in the Software without restriction, including without limitation the rights
8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 copies of the Software, and to permit persons to whom the Software is
10 furnished to do so, subject to the following conditions:
11
12 The above copyright notice and this permission notice shall be included in
13 all copies or substantial portions of the Software.
14
15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21 THE SOFTWARE.
1 # Airbrussh
2
3 [![Gem Version](https://badge.fury.io/rb/airbrussh.svg)](http://badge.fury.io/rb/airbrussh)
4 [![Build Status](https://travis-ci.org/mattbrictson/airbrussh.svg?branch=master)](https://travis-ci.org/mattbrictson/airbrussh)
5 [![Build status](https://ci.appveyor.com/api/projects/status/h052rlq54sne3md6/branch/master?svg=true)](https://ci.appveyor.com/project/mattbrictson/airbrussh/branch/master)
6 [![Code Climate](https://codeclimate.com/github/mattbrictson/airbrussh/badges/gpa.svg)](https://codeclimate.com/github/mattbrictson/airbrussh)
7 [![Coverage Status](https://coveralls.io/repos/mattbrictson/airbrussh/badge.svg?branch=master)](https://coveralls.io/r/mattbrictson/airbrussh?branch=master)
8
9
10 Airbrussh is a concise log formatter for Capistrano and SSHKit. It displays well-formatted, useful log output that is easy to read. Airbrussh also saves Capistrano's verbose output to a separate log file just in case you need additional details for troubleshooting.
11
12 **As of April 2016, Airbrussh is bundled with Capistrano 3.5, and is Capistrano's default formatter! There is nothing additional to install or enable.** Continue reading to learn more about Airbrussh's features and configuration options.
13
14 If you aren't yet using Capistrano 3.5 (or wish to use Airbrussh with SSHKit directly), refer to the [advanced/legacy usage](#advancedlegacy-usage) section for installation instructions.
15
16 ![Sample output](https://raw.github.com/mattbrictson/airbrussh/master/demo.gif)
17
18 For more details on how exactly Airbrussh affects Capistrano's output and the reasoning behind it, check out the blog post: [Introducing Airbrussh](https://mattbrictson.com/airbrussh).
19
20 -----
21
22 * [Usage](#usage)
23 * [Configuration](#configuration)
24 * [FAQ](#faq)
25 * [Advanced/legacy usage](#advancedlegacy-usage)
26
27 ## Usage
28
29 Airbrussh is enabled by default in Capistrano 3.5 and newer. To manually enable Airbrussh (for example, when upgrading an existing project), set the Capistrano format like this:
30
31 ```ruby
32 # In deploy.rb
33 set :format, :airbrussh
34 ```
35
36 ### What's displayed
37
38 When you run a Capistrano command, Airbrussh provides the following information in its output:
39
40 ![Sample output](https://raw.github.com/mattbrictson/airbrussh/master/formatting.png)
41
42 * Name of Capistrano task being executed
43 * When each task started (minutes:seconds elapsed since the deploy began)
44 * The SSH command-line strings that are executed; for Capistrano tasks that involve running multiple commands, the numeric prefix indicates the command in the sequence, starting from `01`
45 * Stdout and stderr output from each command
46 * The duration of each command execution, per server
47
48 ### What's *not* displayed
49
50 For brevity, Airbrussh does not show *everything* that Capistrano is doing. For example, it will omit Capistrano's `test` commands, which can be noisy and confusing. Airbrussh also hides things like environment variables, as well as `cd` and `env` invocations. To see a full audit of Capistrano's execution, including *exactly* what commands were run on each server, look at `log/capistrano.log`.
51
52 ## Configuration
53
54 You can customize many aspects of Airbrussh's output. In Capistrano 3.5 and newer, this is done via the `:format_options` variable, like this:
55
56 ```ruby
57 # Pass options to Airbrussh
58 set :format_options, color: false, truncate: 80
59 ```
60
61 Here are the options you can use, and their effects (note that the defaults may be different depending on where Airbrussh is used; these are the defaults used by Capistrano 3.5):
62
63 |Option|Default|Usage|
64 |---|---|---|
65 |`banner`|`nil`|Provide a string (e.g. "Capistrano started!") that will be printed when Capistrano starts up.|
66 |`color`|`:auto`|Use `true` or `false` to enable or disable ansi color. If set to `:auto`, Airbrussh automatically uses color based on whether the output is a TTY, or if the SSHKIT_COLOR environment variable is set.|
67 |`command_output`|`true`|Set to `:stdout`, `:stderr`, or `true` to display the SSH output received via stdout, stderr, or both, respectively. Set to `false` to not show any SSH output, for a minimal look.|
68 |`log_file`|`log/capistrano.log`|Capistrano's verbose output is saved to this file to facilitate debugging. Set to `nil` to disable completely.|
69 |`truncate`|`:auto`|Set to a number (e.g. 80) to truncate the width of the output to that many characters, or `false` to disable truncation. If `:auto`, output is automatically truncated to the width of the terminal window, if it can be determined.|
70 |`task_prefix`|`nil`|A string to prefix to task output. Handy for output collapsing like [buildkite](https://buildkite.com/docs/builds/managing-log-output)'s `---` prefix|
71
72 ## FAQ
73
74 **Airbrussh is not displaying the output of my commands! For example, I run `tail` in one of my capistrano tasks and airbrussh doesn't show anything. How do I fix this?**
75
76 Make sure Airbrussh is configured to show SSH output.
77
78 ```ruby
79 set :format_options, command_output: true
80 ```
81
82 **I haven't upgraded to Capistrano 3.5 yet. Can I still use Airbrussh?**
83
84 Yes! Capistrano 3.4.x is also supported. Refer to the [advanced/legacy usage](#advancedlegacy-usage) section for installation instructions.
85
86 **Does Airbrussh work with Capistrano 2?**
87
88 No, Capistrano 3 is required. We recommend Capistrano 3.4.0 or higher. Capistrano 3.5.0 and higher have Airbrussh enabled by default, with no installation needed.
89
90 **Does Airbrussh work with JRuby?**
91
92 JRuby is not officially supported or tested, but may work. You must disable automatic truncation to work around a known bug in the JRuby 9.0 standard library. See [#62](https://github.com/mattbrictson/airbrussh/issues/62) for more details.
93
94 ```ruby
95 set :format_options, truncate: false
96 ```
97
98 **I have a question that’s not answered here or elsewhere in the README.**
99
100 Please [open a GitHub issue](https://github.com/mattbrictson/airbrussh/issues/new) and we’ll be happy to help!
101
102 ## Advanced/legacy usage
103
104 Although Airbrussh is built into Capistrano 3.5.0 and higher, it is also available as a plug-in for older versions. Airbrussh has been tested with MRI 1.9+, Capistrano 3.4.0+, and SSHKit 1.6.1+.
105
106 ### Capistrano 3.4.x
107
108 Add this line to your application's Gemfile:
109
110 ```ruby
111 gem "airbrussh", require: false
112 ```
113
114 And then execute:
115
116 $ bundle
117
118 Finally, add this line to your application's Capfile:
119
120 ```ruby
121 require "airbrussh/capistrano"
122 ```
123
124 **Important:** explicitly setting Capistrano's `:format` option in your deploy.rb will override airbrussh. Remove this line if you have it:
125
126 ```ruby
127 # Remove this
128 set :format, :pretty
129 ```
130
131 Capistrano 3.4.x doesn't have the `:format_options` configuration system, so you will need to configure Airbrussh using this technique:
132
133 ```ruby
134 Airbrussh.configure do |config|
135 config.color = false
136 config.command_output = true
137 # etc.
138 end
139 ```
140
141 Refer to the [configuration](#configuration) section above for the list of supported options.
142
143 ### SSHKit
144
145 If you are using SSHKit directly (i.e. without Capistrano), you can use Airbrussh like this:
146
147 ```ruby
148 require "airbrussh"
149 SSHKit.config.output = Airbrussh::Formatter.new($stdout)
150
151 # You can also pass configuration options like this
152 SSHKit.config.output = Airbrussh::Formatter.new($stdout, color: false)
153 ```
154
155 ## History
156
157 Airbrussh started life as custom logging code within the [capistrano-mb][] collection of opinionated Capistrano recipes. In February 2015, the logging code was refactored into a standalone gem with its own configuration and documentation, and renamed `airbrussh`. In February 2016, Airbrussh was added as the default formatter in Capistrano 3.5.0.
158
159 ## Roadmap
160
161 Airbrussh now has a stable feature set, excellent test coverage, is being used for production deployments, and has reached 1.0.0! If you have ideas for improvements to Airbrussh, please open a [GitHub issue](https://github.com/mattbrictson/airbrussh/issues/new).
162
163 ## Contributing
164
165 Contributions are welcome! Read [CONTRIBUTING.md](CONTRIBUTING.md) to get started.
166
167 [capistrano-mb]: https://github.com/mattbrictson/capistrano-mb
1 require "bundler/gem_tasks"
2
3 require "rake/testtask"
4 Rake::TestTask.new(:test) do |t|
5 t.libs << "test"
6 t.libs << "lib"
7 t.test_files = FileList["test/**/*_test.rb"]
8 end
9
10 require "rubocop/rake_task"
11 RuboCop::RakeTask.new
12
13 # rubocop:disable Lint/HandleExceptions
14 begin
15 require "chandler/tasks"
16 rescue LoadError
17 end
18 task "release:rubygem_push" => "chandler:push" if defined?(Chandler)
19
20 task :default => [:test, :rubocop]
1 # Capistrano 3.5 upgrade guide for existing Airbrussh users
2
3 If you have been using Airbrussh with Capistrano, and are upgrading to Capistrano 3.5, then this guide is for you.
4
5 ## What changed?
6
7 * Airbrussh is built into Capistrano starting with Capistrano 3.5.0, and is enabled by default.
8 * Capistrano 3.5 initializes Airbrussh with a default configuration that is different than Airbrussh+Capistrano 3.4.0.
9 * In Capistrano 3.5, `set :format_options, ...` is now the preferred mechanism for configuring Airbrussh.
10
11 ## How to upgrade
12
13 1. Remove `gem "airbrussh"` from your Gemfile. Airbrussh is now included automatically by Capistrano.
14 2. Likewise, remove `require "capistrano/airbrussh"` from your Capfile. Capistrano now does this internally.
15 3. Remove `Airbrussh.configure do ... end` from your deploy.rb and replace with `set :format_options, ...` (see below).
16
17 ## New configuration system
18
19 In Capistrano 3.5, Airbrussh is configured by assigning a configuration Hash to the `:format_options` variable. Here is a comparison of the old and new syntaxes:
20
21 ```ruby
22 # Old syntax
23 Airbrussh.configure do |config|
24 config.color = false
25 end
26
27 # New syntax
28 set :format_options, color: false
29 ```
30
31 Although the syntax is different, the names of the configuration keys have not changed.
32
33 ## New defaults
34
35 Capistrano 3.5.0 changes Airbrussh defaults as follows:
36
37 * `banner: false`
38 * `command_output: true`
39
40 Therefore, after upgrading to Capistrano 3.5.0, you may notice Airbrussh's output has changed and become more verbose. To restore the defaults to what you were used to in older versions, do this:
41
42 ```ruby
43 set :format_options, banner: :auto, command_output: false
44 ```
45
46 ## Trouble?
47
48 If you have any Airbrussh-related trouble with the upgrade, please [open an issue](https://github.com/mattbrictson/airbrussh/issues).
1 # coding: utf-8
2 lib = File.expand_path("../lib", __FILE__)
3 $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4 require "airbrussh/version"
5
6 Gem::Specification.new do |spec|
7 spec.name = "airbrussh"
8 spec.version = Airbrussh::VERSION
9 spec.authors = ["Matt Brictson"]
10 spec.email = ["airbrussh@mattbrictson.com"]
11 spec.summary = "Airbrussh pretties up your SSHKit and Capistrano output"
12 spec.description = "A replacement log formatter for SSHKit that makes "\
13 "Capistrano output much easier on the eyes. Just add "\
14 "Airbrussh to your Capfile and enjoy concise, useful "\
15 "log output that is easy to read."
16 spec.homepage = "https://github.com/mattbrictson/airbrussh"
17 spec.license = "MIT"
18
19 spec.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
20 spec.bindir = "exe"
21 spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22 spec.require_paths = ["lib"]
23
24 spec.add_dependency "sshkit", [">= 1.6.1", "!= 1.7.0"]
25
26 spec.add_development_dependency "bundler", "~> 1.10"
27 spec.add_development_dependency "coveralls", "~> 0.8.15"
28 spec.add_development_dependency "rake", "~> 12.0"
29 spec.add_development_dependency "minitest", "~> 5.10"
30 spec.add_development_dependency "minitest-reporters", "~> 1.1"
31 spec.add_development_dependency "mocha", "~> 1.2"
32 spec.add_development_dependency "rubocop", "~> 0.41.2"
33 end
1 version: '{build}'
2
3 skip_tags: true
4
5 environment:
6 matrix:
7 - ruby_version: "23"
8 - ruby_version: "23-x64"
9
10 install:
11 - SET PATH=C:\Ruby%ruby_version%\bin;%PATH%
12 - gem install bundler --no-document --conservative --version 1.10.5
13 - bundle install --retry=3
14
15 test_script:
16 - bundle exec rake
17
18 build: off
1 #!/usr/bin/env ruby
2
3 require "bundler/setup"
4 require "airbrussh"
5
6 # You can add fixtures and/or initialization code here to make experimenting
7 # with your gem easier. You can also use a different console, if you like.
8
9 # (If you use this, don't forget to add pry to your Gemfile!)
10 # require "pry"
11 # Pry.start
12
13 require "irb"
14 IRB.start
1 #!/bin/bash
2 set -euo pipefail
3 IFS=$'\n\t'
4
5 bundle install
6
7 # Do any other automated setup that you need to do here
1 #!/usr/bin/env ruby
2 require "yaml"
3 require "English"
4
5 ruby24 = Gem::Version.new(RUBY_VERSION) >= Gem::Version.new("2.4.0")
6
7 YAML.load_file(".travis.yml")["env"].each do |sshkit_version|
8 # Older versions of SSHKit don't work with Ruby 2.4, so skip those
9 next if ruby24 && sshkit_version !~ /master/
10 puts "\e[0;34;49m== Running tests against #{sshkit_version} ==\e[0m"
11 output = `#{sshkit_version} bundle update`
12 raise "bundle update failed: #{output}" unless $CHILD_STATUS.success?
13 system("#{sshkit_version} bundle exec rake test")
14 end
15
16 system("bundle exec rake rubocop")
17
18 at_exit do
19 puts "\e[0;34;49m== Resetting sshkit ==\e[0m"
20 system("bundle update")
21 end
1 require "airbrussh/configuration"
2 require "airbrussh/formatter"
3 require "airbrussh/version"
4
5 module Airbrussh
6 def self.configuration(options={})
7 return options if options.is_a?(::Airbrussh::Configuration)
8 @configuration ||= Configuration.new
9 @configuration.apply_options(options)
10 end
11
12 def self.configure
13 yield(configuration)
14 end
15 end
1 require "airbrussh/capistrano/tasks"
2
3 tasks = Airbrussh::Capistrano::Tasks.new(self)
4
5 # Hook into Capistrano's init process to set the formatter
6 namespace :load do
7 task :defaults do
8 tasks.load_defaults
9 end
10 end
11
12 # Capistrano failure hook
13 namespace :deploy do
14 task :failed do
15 tasks.deploy_failed
16 end
17 end
1 require "airbrussh"
2 require "airbrussh/colors"
3 require "airbrussh/console"
4 require "forwardable"
5 require "shellwords"
6
7 module Airbrussh
8 module Capistrano
9 # Encapsulates the rake behavior that integrates Airbrussh into Capistrano.
10 # This class allows us to easily test the behavior using a mock to stand in
11 # for the Capistrano DSL.
12 #
13 # See airbrussh/capistrano.rb to see how this class is used.
14 #
15 class Tasks
16 extend Forwardable
17 def_delegators :dsl, :set, :env
18 def_delegators :config, :log_file
19
20 include Airbrussh::Colors
21
22 def initialize(dsl, stderr=$stderr, config=Airbrussh.configuration)
23 @dsl = dsl
24 @stderr = stderr
25 @config = config
26
27 configure
28 warn_if_missing_dsl
29 end
30
31 # Behavior for the rake load:defaults task.
32 def load_defaults
33 require "sshkit/formatter/airbrussh"
34 set :format, :airbrussh
35 end
36
37 # Behavior for the rake deploy:failed task.
38 def deploy_failed
39 return unless airbrussh_is_being_used?
40 return if log_file.nil?
41
42 error_line
43 error_line(red("** DEPLOY FAILED"))
44 error_line(yellow("** Refer to #{log_file} for details. "\
45 "Here are the last 20 lines:"))
46 error_line
47 error_line(tail_log_file)
48 end
49
50 private
51
52 attr_reader :dsl, :stderr, :config
53
54 # Change airbrussh's default configuration to be more appropriate for
55 # capistrano.
56 def configure
57 config.log_file = "log/capistrano.log"
58 config.monkey_patch_rake = true
59 end
60
61 # Verify that capistrano and rake DSLs are present
62 def warn_if_missing_dsl
63 return if %w(set namespace task).all? { |m| dsl.respond_to?(m, true) }
64
65 error_line(
66 red("WARNING: airbrussh/capistrano must be loaded by Capistrano in "\
67 "order to work.\nRequire this gem within your application's "\
68 "Capfile, as described here:\n"\
69 "https://github.com/mattbrictson/airbrussh#installation")
70 )
71 end
72
73 def err_console
74 @err_console ||= begin
75 # Ensure we do not truncate the error output
76 err_config = config.dup
77 err_config.truncate = false
78 Airbrussh::Console.new(stderr, err_config)
79 end
80 end
81
82 def error_line(line="\n")
83 line.each_line(&err_console.method(:print_line))
84 end
85
86 # Returns a String containing the last 20 lines of the log file. Since
87 # this method uses a fixed-size buffer, fewer than 20 lines may be
88 # returned in cases where the lines are extremely long.
89 def tail_log_file
90 open(log_file) do |file|
91 file.seek(-[8192, file.size].min, IO::SEEK_END)
92 file.readlines.last(20).join
93 end
94 end
95
96 def airbrussh_is_being_used?
97 # Obtain the current formatter from the SSHKit backend
98 output = env.backend.config.output
99 output.is_a?(Airbrussh::Formatter)
100 end
101 end
102 end
103 end
1 module Airbrussh
2 # Very basic support for ANSI color, so that we don't have to rely on
3 # any external dependencies.
4 module Colors
5 ANSI_CODES = {
6 :red => 31,
7 :green => 32,
8 :yellow => 33,
9 :blue => 34,
10 :gray => 90
11 }.freeze
12
13 # Define red, green, blue, etc. methods that return a copy of the
14 # String that is wrapped in the corresponding ANSI color escape
15 # sequence.
16 ANSI_CODES.each do |name, code|
17 define_method(name) do |string|
18 "\e[0;#{code};49m#{string}\e[0m"
19 end
20 module_function(name)
21 end
22 end
23 end
1 # encoding: UTF-8
2 require "airbrussh/colors"
3 require "delegate"
4 # rubocop:disable Style/AsciiComments
5
6 module Airbrussh
7 # Decorates an SSHKit Command to add string output helpers and the
8 # command's position within currently executing rake task:
9 #
10 # * position - zero-based position of this command in the list of
11 # all commands that have been run in the current rake task; in
12 # some cases this could be nil
13 class CommandFormatter < SimpleDelegator
14 include Airbrussh::Colors
15
16 def initialize(command, position)
17 super(command)
18 @position = position
19 end
20
21 # Prefixes the line with the command number and removes the newline.
22 #
23 # format_output("hello\n") # => "01 hello"
24 #
25 def format_output(line)
26 "#{number} #{line.chomp}"
27 end
28
29 # Returns the abbreviated command (in yellow) with the number prefix.
30 #
31 # start_message # => "01 echo hello"
32 #
33 def start_message
34 "#{number} #{yellow(abbreviated)}"
35 end
36
37 # Returns a green (success) or red (failure) message depending on the
38 # exit status.
39 #
40 # exit_message # => "✔ 01 user@host 0.084s"
41 # exit_message # => "✘ 01 user@host 0.084s"
42 #
43 def exit_message
44 message = if failure?
45 red(failure_message)
46 else
47 green(success_message)
48 end
49 message << " #{runtime}"
50 end
51
52 private
53
54 def user_at_host
55 user_str = host.user || (host.ssh_options || {})[:user]
56 host_str = host.hostname
57 [user_str, host_str].compact.join("@")
58 end
59
60 def runtime
61 format("%5.3fs", super)
62 end
63
64 def abbreviated
65 to_s.sub(%r{^/usr/bin/env }, "")
66 end
67
68 def number
69 format("%02d", @position.to_i + 1)
70 end
71
72 def success_message
73 "✔ #{number} #{user_at_host}"
74 end
75
76 def failure_message
77 "✘ #{number} #{user_at_host}"
78 end
79 end
80 end
1 require "airbrussh/colors"
2 require "airbrussh/console_formatter"
3 require "airbrussh/log_file_formatter"
4
5 module Airbrussh
6 class Configuration
7 attr_accessor :log_file, :monkey_patch_rake, :color, :truncate, :banner,
8 :command_output, :task_prefix
9
10 def initialize
11 self.log_file = nil
12 self.monkey_patch_rake = false
13 self.color = :auto
14 self.truncate = :auto
15 self.banner = :auto
16 self.command_output = false
17 self.task_prefix = nil
18 end
19
20 def apply_options(options)
21 return self if options.nil?
22
23 options.each do |key, value|
24 if respond_to?(writer = "#{key}=")
25 public_send(writer, value)
26 else
27 warn_unrecognized_key(key)
28 end
29 end
30 self
31 end
32
33 def banner_message
34 return nil unless banner
35 return banner unless banner == :auto
36 msg = "Using airbrussh format."
37 if log_file
38 msg << "\n"
39 msg << "Verbose output is being written to #{Colors.blue(log_file)}."
40 end
41 msg
42 end
43
44 # This returns an array of formatters appropriate for the configuration.
45 # Depending on whether a log file is configured, this could be just the
46 # Airbrussh:ConsoleFormatter, or that plus the LogFileFormatter.
47 def formatters(io)
48 fmts = [Airbrussh::ConsoleFormatter.new(io, self)]
49 fmts.unshift(Airbrussh::LogFileFormatter.new(log_file)) if log_file
50 fmts
51 end
52
53 def show_command_output?(sym)
54 command_output == true || Array(command_output).include?(sym)
55 end
56
57 private
58
59 def warn_unrecognized_key(key)
60 $stderr.puts("Ignoring unrecognized Airbrussh option: #{key}")
61 end
62 end
63 end
1 # encoding: UTF-8
2 require "io/console"
3
4 module Airbrussh
5 # Helper class that wraps an IO object and provides methods for truncating
6 # output, assuming the IO object represents a console window.
7 #
8 # This is useful for writing log messages that will typically show up on
9 # an ANSI color-capable console. When a console is not present (e.g. when
10 # running on a CI server) the output will gracefully degrade.
11 class Console
12 attr_reader :output, :config
13
14 def initialize(output, config=Airbrussh.configuration)
15 @output = output
16 @config = config
17 end
18
19 # Writes to the IO after first truncating the output to fit the console
20 # width. If the underlying IO is not a TTY, ANSI colors are removed from
21 # the output. A newline is always added. Color output can be forced by
22 # setting the SSHKIT_COLOR environment variable.
23 def print_line(obj="")
24 string = obj.to_s
25
26 string = truncate_to_console_width(string) if console_width
27 string = strip_ascii_color(string) unless color_enabled?
28
29 write(string + "\n")
30 output.flush
31 end
32
33 # Writes directly through to the IO with no truncation or color logic.
34 # No newline is added.
35 def write(string)
36 output.write(string || "")
37 end
38 alias << write
39
40 def truncate_to_console_width(string)
41 string = (string || "").rstrip
42 ellipsis = utf8_supported?(string) ? "…" : "..."
43 width = console_width
44
45 if strip_ascii_color(string).length > width
46 width -= ellipsis.length
47 string.chop! while strip_ascii_color(string).length > width
48 string << "#{ellipsis}\e[0m"
49 else
50 string
51 end
52 end
53
54 def strip_ascii_color(string)
55 (string || "").gsub(/\033\[[0-9;]*m/, "")
56 end
57
58 def console_width
59 width = case (truncate = config.truncate)
60 when :auto
61 IO.console.winsize.last if @output.tty?
62 when Integer
63 truncate
64 end
65
66 width if width.to_i > 0
67 end
68
69 private
70
71 def color_enabled?
72 case config.color
73 when true
74 true
75 when :auto
76 ENV["SSHKIT_COLOR"] || @output.tty?
77 else
78 false
79 end
80 end
81
82 def utf8_supported?(string)
83 string.encode("UTF-8").valid_encoding?
84 rescue Encoding::UndefinedConversionError
85 false
86 end
87 end
88 end
1 require "airbrussh/colors"
2 require "airbrussh/command_formatter"
3 require "airbrussh/console"
4 require "airbrussh/rake/context"
5 require "sshkit"
6
7 module Airbrussh
8 class ConsoleFormatter < SSHKit::Formatter::Abstract
9 include Airbrussh::Colors
10 extend Forwardable
11
12 attr_reader :config, :context
13 def_delegators :context, :current_task_name, :register_new_command
14
15 def initialize(io, config=Airbrussh.configuration)
16 super(io)
17
18 @config = config
19 @context = Airbrussh::Rake::Context.new(config)
20 @console = Airbrussh::Console.new(original_output, config)
21
22 write_banner
23 end
24
25 def write_banner
26 print_line(config.banner_message) if config.banner_message
27 end
28
29 def log_command_start(command)
30 return if debug?(command)
31 first_execution = register_new_command(command)
32 command = decorate(command)
33 print_task_if_changed
34 print_indented_line(command.start_message) if first_execution
35 end
36
37 def log_command_data(command, stream_type, string)
38 return if debug?(command)
39 return unless config.show_command_output?(stream_type)
40 command = decorate(command)
41 string.each_line do |line|
42 print_indented_line(command.format_output(line))
43 end
44 end
45
46 def log_command_exit(command)
47 return if debug?(command)
48 command = decorate(command)
49 print_indented_line(command.exit_message, -2)
50 end
51
52 def write(obj)
53 case obj
54 when SSHKit::Command
55 log_command_start(obj)
56 log_and_clear_command_output(obj, :stderr)
57 log_and_clear_command_output(obj, :stdout)
58 log_command_exit(obj) if obj.finished?
59 when SSHKit::LogMessage
60 write_log_message(obj)
61 end
62 end
63 alias << write
64
65 private
66
67 attr_accessor :last_printed_task
68
69 def write_log_message(log_message)
70 return if debug?(log_message)
71 print_task_if_changed
72 print_indented_line(format_log_message(log_message))
73 end
74
75 def format_log_message(log_message)
76 case log_message.verbosity
77 when SSHKit::Logger::WARN
78 "#{yellow('WARN')} #{log_message}"
79 when SSHKit::Logger::ERROR
80 "#{red('ERROR')} #{log_message}"
81 when SSHKit::Logger::FATAL
82 "#{red('FATAL')} #{log_message}"
83 else
84 log_message.to_s
85 end
86 end
87
88 # For SSHKit versions up to and including 1.7.1, the stdout and stderr
89 # output was available as attributes on the Command. Print the data for
90 # the specified command and stream if enabled and clear the stream.
91 # (see Airbrussh::Configuration#command_output).
92 def log_and_clear_command_output(command, stream)
93 output = command.public_send(stream)
94 log_command_data(command, stream, output)
95 command.public_send("#{stream}=", "")
96 end
97
98 def print_task_if_changed
99 return if current_task_name.nil?
100 return if current_task_name == last_printed_task
101
102 self.last_printed_task = current_task_name
103 print_line("#{config.task_prefix}#{clock} #{blue(current_task_name)}")
104 end
105
106 def clock
107 @start_at ||= Time.now
108 duration = Time.now - @start_at
109
110 minutes = (duration / 60).to_i
111 seconds = (duration - minutes * 60).to_i
112
113 format("%02d:%02d", minutes, seconds)
114 end
115
116 def debug?(obj)
117 obj.verbosity <= SSHKit::Logger::DEBUG
118 end
119
120 def decorate(command)
121 Airbrussh::CommandFormatter.new(command, @context.position(command))
122 end
123
124 def print_line(string)
125 @console.print_line(string)
126 end
127
128 def print_indented_line(string, offset=0)
129 indent = " " * (6 + offset)
130 print_line([indent, string].join)
131 end
132 end
133 end
1 require "sshkit"
2
3 module Airbrussh
4 # This class quacks like an SSHKit::Formatter, but when any formatting
5 # methods are called, it simply forwards them to one more more concrete
6 # formatters. This allows us to split out the responsibilities of
7 # ConsoleFormatter and LogFileFormatter into two separate classes, with
8 # DelegatingFormatter forwarding the logging messages to both at once.
9 #
10 class DelegatingFormatter
11 FORWARD_METHODS = %w(
12 fatal error warn info debug log
13 log_command_start log_command_data log_command_exit
14 ).freeze
15 DUP_AND_FORWARD_METHODS = %w(<< write).freeze
16
17 attr_reader :formatters
18
19 def initialize(formatters)
20 @formatters = formatters
21 end
22
23 FORWARD_METHODS.each do |method|
24 define_method(method) do |*args|
25 formatters.map { |f| f.public_send(method, *args) }.last
26 end
27 end
28
29 # For versions of SSHKit up to and including 1.7.1, the LogfileFormatter
30 # and ConsoleFormatter (and all of SSHKit's built in formatters) clear
31 # the stdout and stderr data in the command obj. Therefore, ensure only
32 # one of the formatters (the last one) gets the original command. This is
33 # also the formatter whose return value is passed to the caller.
34 #
35 DUP_AND_FORWARD_METHODS.each do |method|
36 define_method(method) do |command_or_log_message|
37 formatters[0...-1].each do |f|
38 f.public_send(method, command_or_log_message.dup)
39 end
40 formatters.last.public_send(method, command_or_log_message)
41 end
42 end
43 end
44 end
1 require "airbrussh"
2 require "airbrussh/delegating_formatter"
3
4 # This is the formatter class that conforms to the SSHKit Formatter API and
5 # provides the airbrussh functionality to SSHKit. Note however that this class
6 # doesn't do much by itself; instead, it delegates to the ConsoleFormatter
7 # and (optionally) the LogFileFormatter, which handle the bulk of the logic.
8 #
9 module Airbrussh
10 class Formatter < Airbrussh::DelegatingFormatter
11 def initialize(io, options_or_config_object={})
12 config = ::Airbrussh.configuration(options_or_config_object)
13 # Delegate to ConsoleFormatter and (optionally) LogFileFormatter,
14 # based on the configuration.
15 super(config.formatters(io))
16 end
17 end
18 end
1 require "delegate"
2 require "fileutils"
3 require "logger"
4 require "sshkit"
5
6 module Airbrussh
7 # A Pretty formatter that sends its output to a specified log file path.
8 # LogFileFormatter takes care of creating the file (and its parent
9 # directory) if it does not already exist, opens it for appending, and writes
10 # a delimiter message. The file is automatically rotated if it reaches 20 MB.
11 #
12 class LogFileFormatter < SimpleDelegator
13 attr_reader :path
14
15 def initialize(path, formatter_class=SSHKit::Formatter::Pretty)
16 @path = path
17 ensure_directory_exists if path.is_a?(String)
18 super(formatter_class.new(log_file_io))
19 write_delimiter
20 end
21
22 private
23
24 def write_delimiter
25 delimiter = []
26 delimiter << "-" * 75
27 delimiter << "START #{Time.now} cap #{ARGV.join(' ')}"
28 delimiter << "-" * 75
29 delimiter.each do |line|
30 write(SSHKit::LogMessage.new(SSHKit::Logger::INFO, line))
31 end
32 end
33
34 def ensure_directory_exists
35 FileUtils.mkdir_p(File.dirname(path))
36 end
37
38 def log_file_io
39 @io ||= ::Logger.new(path, 1, 20_971_520)
40 end
41 end
42 end
1 require "rake"
2
3 module Airbrussh
4 module Rake
5 # Maintains information about what Rake task is currently being invoked,
6 # in order to be able to decorate SSHKit commands with additional
7 # context-sensitive information. Works via a monkey patch to Rake::Task,
8 # which can be disabled via by setting
9 # Airbrussh.configuration.monkey_patch_rake = false.
10 #
11 # Note that this class is not thread-safe. Normally this is not a problem,
12 # but some Capistrano users are known to use `invoke` to switch the Rake
13 # task in the middle of an SSHKit thread, which causes Context to get very
14 # confused. It such scenarios Context is not reliable and may return `nil`
15 # for the `position` of a command.
16 #
17 class Context
18 def initialize(config=Airbrussh.configuration)
19 @history = []
20 @enabled = config.monkey_patch_rake
21 self.class.install_monkey_patch if enabled?
22 end
23
24 # Returns the name of the currently-executing rake task, if it can be
25 # determined. If monkey patching is disabled, this will be nil.
26 def current_task_name
27 return nil unless enabled?
28 self.class.current_task_name
29 end
30
31 # Update the context when a new command starts by:
32 # * Clearing the command history if the rake task has changed
33 # * Recording the command in the history
34 #
35 # Returns whether or not this command was the first execution
36 # of this command in the current rake task
37 def register_new_command(command)
38 reset_history_if_task_changed
39
40 first_execution = !history.include?(command.to_s)
41 history << command.to_s
42 history.uniq!
43 first_execution
44 end
45
46 # The zero-based position of the specified command in the current rake
47 # task. May be `nil` in certain multi-threaded scenarios, so be careful!
48 def position(command)
49 history.index(command.to_s)
50 end
51
52 class << self
53 attr_accessor :current_task_name
54
55 def install_monkey_patch
56 return if ::Rake::Task.instance_methods.include?(:_airbrussh_execute)
57
58 ::Rake::Task.class_exec do
59 alias_method :_airbrussh_execute, :execute
60 def execute(args=nil) # rubocop:disable Lint/NestedMethodDefinition
61 ::Airbrussh::Rake::Context.current_task_name = name.to_s
62 _airbrussh_execute(args)
63 end
64 end
65 end
66 end
67
68 private
69
70 attr_reader :history
71 attr_accessor :last_task_name
72
73 def reset_history_if_task_changed
74 history.clear if last_task_name != current_task_name
75 self.last_task_name = current_task_name
76 end
77
78 def enabled?
79 @enabled
80 end
81 end
82 end
83 end
1 # frozen_string_literal: true
2 module Airbrussh
3 VERSION = "1.3.0".freeze
4 end
1 require "airbrussh/formatter"
2
3 # Capistrano's formatter configuration requires that the formatter class
4 # be in the SSHKit::Formatter namespace. So we declare
5 # SSHKit::Formatter::Airbrussh that simply functions as an alias for
6 # Airbrussh::Formatter.
7 module SSHKit
8 module Formatter
9 class Airbrussh < Airbrussh::Formatter
10 end
11 end
12 end
1 ---
2 engines:
3 duplication:
4 enabled: true
5 config:
6 languages:
7 - ruby
8 fixme:
9 enabled: true
10 rubocop:
11 enabled: false
12 ratings:
13 paths:
14 - "**.rb"
15 - "bin/*"
16 - "exe/*"
17 exclude_paths:
18 - bundler.gemspec
19 - "*.md"
20 - lib/bundler/ssl_certs/*.pem
21 - lib/bundler/vendor/**/*
22 - lib/bundler/templates/**/*.tt
23 - man/*
24 - spec/**/*
25 - Rakefile
1 # Please do not submit patches for including directives to ignore IDE/editor
2 # generated files. Use a global gitignore as described in
3 # https://help.github.com/articles/ignoring-files and find useful gitignore
4 # samples at https://github.com/github/gitignore
5
6 # files created by running the specs
7 /tmp/
8
9 # gems built by `rake build`
10 /pkg/
11
12 # output from ronn
13 /lib/bundler/man/
14 man/*
15 !man/*.ronn
16
17 # rspec failure tracking
18 .rspec_status
1 --format documentation
2 --color
3 --warnings
1 inherit_from:
2 - .rubocop_todo.yml
3
4 AllCops:
5 TargetRubyVersion: 1.9
6 Exclude:
7 - tmp/**/*
8 - lib/bundler/vendor/**/*
9 DisplayCopNames: true
10
11 # Lint
12
13 # They are idiomatic
14 Lint/AssignmentInCondition:
15 Enabled: false
16
17 Lint/EndAlignment:
18 EnforcedStyleAlignWith: variable
19 AutoCorrect: true
20
21 Lint/UnusedMethodArgument:
22 Enabled: false
23
24 # Style
25
26 Style/AccessModifierIndentation:
27 EnforcedStyle: outdent
28
29 Style/Alias:
30 EnforcedStyle: prefer_alias_method
31
32 Style/AlignParameters:
33 EnforcedStyle: with_fixed_indentation
34
35 Style/FrozenStringLiteralComment:
36 EnforcedStyle: always
37
38 Style/MultilineBlockChain:
39 Enabled: false
40
41 Style/MultilineOperationIndentation:
42 EnforcedStyle: indented
43
44 Style/PerlBackrefs:
45 Enabled: false
46
47 Style/SingleLineBlockParams:
48 Enabled: false
49
50 Style/SpaceInsideBlockBraces:
51 SpaceBeforeBlockParameters: false
52
53 Style/TrivialAccessors:
54 Enabled: false
55
56 # We adopted raise instead of fail.
57 Style/SignalException:
58 EnforcedStyle: only_raise
59
60 Style/StringLiterals:
61 EnforcedStyle: double_quotes
62
63 Style/StringLiteralsInInterpolation:
64 EnforcedStyle: double_quotes
65
66 # Having these make it easier to *not* forget to add one when adding a new
67 # value and you can simply copy the previous line.
68 Style/TrailingCommaInLiteral:
69 EnforcedStyleForMultiline: comma
70
71 Style/TrailingUnderscoreVariable:
72 Enabled: false
73
74 # `String.new` is preferred style with enabled frozen string literal
75 Style/EmptyLiteral:
76 Enabled: false
77
78 # 1.8.7 support
79
80 Style/HashSyntax:
81 EnforcedStyle: hash_rockets
82
83 Style/Lambda:
84 Enabled: false
85
86 Style/DotPosition:
87 EnforcedStyle: trailing
88
89 Style/EachWithObject:
90 Enabled: false
91
92 Style/SpecialGlobalVars:
93 Enabled: false
94
95 Style/TrailingCommaInArguments:
96 Enabled: false
97
98 Performance/FlatMap:
99 Enabled: false
100
101 # Metrics
102
103 # We've chosen to use Rubocop only for style, and not for complexity or quality checks.
104 Metrics/ClassLength:
105 Enabled: false
106
107 Metrics/ModuleLength:
108 Enabled: false
109
110 Metrics/MethodLength:
111 Enabled: false
112
113 Metrics/BlockNesting:
114 Enabled: false
115
116 Metrics/AbcSize:
117 Enabled: false
118
119 Metrics/CyclomaticComplexity:
120 Enabled: false
121
122 Metrics/ParameterLists:
123 Enabled: false
124
125 Metrics/BlockLength:
126 Enabled: false
127
128 # It will be obvious which code is complex, Rubocop should only lint simple
129 # rules for us.
130 Metrics/PerceivedComplexity:
131 Enabled: false
1 language: ruby
2 script: rake spec:travis
3 before_script:
4 - travis_retry rake spec:travis:deps
5 - travis_retry rake man:build
6 - travis_retry rake spec:rubygems:clone_rubygems_$RGV
7
8 branches:
9 only:
10 - master
11 - auto
12 - /.+-dev$/
13 - /.+-stable$/
14
15 notifications:
16 slack:
17 on_success: change
18 on_failure: always
19 rooms:
20 - secure: JxBi7DDJGkIF/7f/FSN/HUHpvV4EKfQccZHTPd1b2pNJn3GXo6u+tNVbAw2WjxYzPyPQI3ZcYBCU9SEXp/i7VmG8uMzh8Kyildw+miSKYKVb90uYqcsXWzbxwyNBgJLvyDkzST45H5lgnyAicee3WkFes/WDZikIajbH7ztdb04=
21
22 addons:
23 code_climate:
24 repo_token:
25 secure: "TrzIv116JLGUxm6PAUskCYrv8KTDguncKROVwbnjVPKTGDAgoDderd8JUdDEXrKoZ9qGLD2TPYKExt9/QDl71E+qHdWnVqWv4HKCUk2P9z/VLKzHuggOUBkCXiJUhjywUieCJhI3N92bfq2EjSBbu2/OFHqWOjLQ+QCooTEBjv8="
26
27 rvm:
28 - 2.4.1
29 - 2.3.4
30 - 2.2.7
31 - 2.1.10
32 - 2.0.0
33 - 1.9.3
34 - 1.8.7
35
36 # Rubygems versions MUST be available as rake tasks
37 # see Rakefile:125 for the list of possible RGV values
38 env:
39 # We need to know if changes to rubygems will break bundler on release
40 - RGV=master
41 # Test the latest rubygems release with all of our supported rubies
42 - RGV=v2.6.8
43
44 matrix:
45 include:
46 # Ruby 2.4, Rubygems 2.6.8 and up
47 # Ruby 2.3, Rubygems 2.5.1 and up
48 - rvm: 2.2.6
49 env: RGV=v2.5.2
50 # Ruby 2.2, Rubygems 2.4.5 and up
51 - rvm: 2.2.6
52 env: RGV=v2.4.8
53 # Ruby 2.1, Rubygems 2.2.2 and up
54 - rvm: 2.1.10
55 env: RGV=v2.2.5
56 # Ruby 2.0.0, Rubygems 2.0.0 and up
57 - rvm: 2.0.0
58 env: RGV=v2.2.5
59 - rvm: 2.0.0
60 env: RGV=v2.1.11
61 - rvm: 2.0.0
62 env: RGV=v2.0.14
63 # Ruby 1.9.3, Rubygems 1.5.3 and up
64 - rvm: 1.9.3
65 env: RGV=v2.2.5
66 - rvm: 1.9.3
67 env: RGV=v2.1.11
68 - rvm: 1.9.3
69 env: RGV=v2.0.14
70 - rvm: 1.9.3
71 env: RGV=v1.8.29
72 - rvm: 1.9.3
73 env: RGV=v1.7.2
74 - rvm: 1.9.3
75 env: RGV=v1.6.2
76 - rvm: 1.9.3
77 env: RGV=v1.5.3
78
79 # Ruby 1.8.7, Rubygems 1.3.6 and up
80 - rvm: 1.8.7
81 env: RGV=v2.2.5
82 # ALLOWED FAILURES
83 # since the great Travis image outage, frequent random segfaults :'(
84 - rvm: 1.8.7
85 env: RGV=v2.0.14
86 - rvm: 1.8.7
87 env: RGV=v1.8.29
88 - rvm: 1.8.7
89 env: RGV=v1.7.2
90 - rvm: 1.8.7
91 env: RGV=v1.6.2
92 - rvm: 1.8.7
93 env: RGV=v1.5.3
94 - rvm: 1.8.7
95 env: RGV=v1.4.2
96 - rvm: 1.8.7
97 env: RGV=v1.3.7
98 - rvm: 1.8.7
99 env: RGV=v1.3.6
100 # Ruby-head (we want to know how we're doing, but not fail the build)
101 - rvm: ruby-head
102 env: RGV=master
103
104 allow_failures:
105 - rvm: 1.8.7
106 env: RGV=v2.0.14
107 - rvm: 1.8.7
108 env: RGV=v1.8.29
109 - rvm: 1.8.7
110 env: RGV=v1.7.2
111 - rvm: 1.8.7
112 env: RGV=v1.6.2
113 - rvm: 1.8.7
114 env: RGV=v1.5.3
115 - rvm: 1.8.7
116 env: RGV=v1.4.2
117 - rvm: 1.8.7
118 env: RGV=v1.3.7
119 - rvm: 1.8.7
120 env: RGV=v1.3.6
121 - rvm: ruby-head
122 env: RGV=master
This diff could not be displayed because it is too large.
1 # Bundler Code of Conduct
2
3 The Bundler project strongly values contributors from anywhere, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, physical appearance, body size, race, ethnicity, age, religion, or nationality. As a result, the Bundler team has agreed to and enforces this code of conduct in order to provide a harassment-free experience for everyone who participates in the development of Bundler.
4
5 ### Summary
6
7 Harassment in code and discussion or violation of physical boundaries is completely unacceptable anywhere in the Bundler project’s codebases, issue trackers, chat rooms, mailing lists, meetups, and any other events. Violators will be warned and then blocked or banned by the core team at or before the 3rd violation.
8
9 ### In detail
10
11 Harassment includes offensive verbal comments related to level of experience, gender, gender identity and expression, sexual orientation, disability, physical appearance, body size, race, ethnicity, age, religion, nationality, the use of sexualized language or imagery, deliberate intimidation, stalking, sustained disruption, and unwelcome sexual attention.
12
13 Individuals asked to stop any harassing behavior are expected to comply immediately.
14
15 Maintainers, including the core team, are also subject to the anti-harassment policy.
16
17 If anyone engages in abusive, harassing, or otherwise unacceptable behavior, including maintainers, we may take appropriate action, up to and including warning the offender, deletion of comments, removal from the project’s codebase and communication systems, and escalation to GitHub support.
18
19 If you are being harassed, notice that someone else is being harassed, or have any other concerns, please contact a member of [the core team](http://bundler.io/contributors.html) or [email the core team](mailto:team@bundler.io) immediately.
20
21 We expect everyone to follow these rules anywhere in the Bundler project’s codebases, issue trackers, IRC channel, group chat, and mailing lists.
22
23 This code of conduct applies both within project spaces and in public spaces when an individual is representing the project or its community.
24
25 Finally, don't forget that it is human to make mistakes! We all do. Let’s work together to help each other, resolve issues, and learn from the mistakes that we will all inevitably make from time to time.
26
27
28 ### Thanks
29
30 Thanks to the [JSConf Code of Conduct](http://jsconf.com/codeofconduct.html) and [Fedora Code of Conduct](http://fedoraproject.org/code-of-conduct) for inspiration and ideas. Additional thanks to [Contributor Covenant](http://contributor-covenant.org) for the [default code of conduct](https://github.com/bundler/bundler/blob/master/lib/bundler/templates/newgem/CODE_OF_CONDUCT.md.tt) included in generated gems.
31
32
33 ### License
34
35 <p class="license" xmlns:dct="http://purl.org/dc/terms/" xmlns:vcard="http://www.w3.org/2001/vcard-rdf/3.0#">
36 To the extent possible under law, <a rel="dct:publisher" href="http://bundler.io">The Bundler Team</a> has waived all copyright and related or neighboring rights to the <span property="dct:title">Bundler Code of Conduct</span>. This work is published from the <span property="vcard:Country" datatype="dct:ISO3166" content="US" about="http://bundler.io">United States.</span>
37 <br>
38 <br>
39 <a rel="license" href="http://creativecommons.org/publicdomain/zero/1.0/">
40 <img src="http://i.creativecommons.org/p/zero/1.0/88x31.png" style="border-style: none;" alt="CC0">
41 </a>
42 </p>
1 # Contributing to Bundler
2
3 Welcome to Bundler! We are so happy that you're here. We know it can be daunting to joining a new open source project, so here's a quick overview of what you can expect from this documentation.
4
5 Bundler welcomes contributions from *everyone*. While contributing, please follow the project [code of conduct](http://bundler.io/conduct.html), so that everyone can be included.
6
7 ## Quick start
8
9 Some guides you might find useful:
10
11 * [Submitting pull requests](doc/development/PULL_REQUESTS.md)
12 * [Filing an issue](doc/contributing/ISSUES.md)
13 * [Bug triage](doc/contributing/BUG_TRIAGE.md)
14
15 ## Comprehensive guides
16
17 Not finding what you're looking for? More comprehensive guides are [available here](doc/README.md).
1 Portions copyright (c) 2010 Andre Arko
2 Portions copyright (c) 2009 Engine Yard
3
4 MIT License
5
6 Permission is hereby granted, free of charge, to any person obtaining
7 a copy of this software and associated documentation files (the
8 "Software"), to deal in the Software without restriction, including
9 without limitation the rights to use, copy, modify, merge, publish,
10 distribute, sublicense, and/or sell copies of the Software, and to
11 permit persons to whom the Software is furnished to do so, subject to
12 the following conditions:
13
14 The above copyright notice and this permission notice shall be
15 included in all copies or substantial portions of the Software.
16
17 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
18 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
20 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
21 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
22 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
23 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
1 [![Version ](https://img.shields.io/gem/v/bundler.svg?style=flat)](https://rubygems.org/gems/bundler)
2 [![Build Status](https://img.shields.io/travis/bundler/bundler/master.svg?style=flat)](https://travis-ci.org/bundler/bundler)
3 [![Code Climate](https://img.shields.io/codeclimate/github/bundler/bundler.svg?style=flat)](https://codeclimate.com/github/bundler/bundler)
4 [![Inline docs ](http://inch-ci.org/github/bundler/bundler.svg?style=flat)](http://inch-ci.org/github/bundler/bundler)
5
6 # Bundler: a gem to bundle gems
7
8 Bundler makes sure Ruby applications run the same code on every machine.
9
10 It does this by managing the gems that the application depends on. Given a list of gems, it can automatically download and install those gems, as well as any other gems needed by the gems that are listed. Before installing gems, it checks the versions of every gem to make sure that they are compatible, and can all be loaded at the same time. After the gems have been installed, Bundler can help you update some or all of them when new versions become available. Finally, it records the exact versions that have been installed, so that others can install the exact same gems.
11
12 ### Installation and usage
13
14 To install:
15
16 ```
17 gem install bundler
18 ```
19
20 Bundler is most commonly used to manage your application's dependencies. To use it for this:
21
22 ```
23 bundle init
24 echo 'gem "rspec"' >> Gemfile
25 bundle install
26 bundle exec rspec
27 ```
28
29 See [bundler.io](http://bundler.io) for the full documentation.
30
31 ### Troubleshooting
32
33 For help with common problems, see [TROUBLESHOOTING](doc/TROUBLESHOOTING.md).
34
35 Still stuck? Try [filing an issue](doc/contributing/ISSUES.md).
36
37 ### Supporting
38
39 <a href="https://rubytogether.org/"><img src="https://rubytogether.org/images/rubies.svg" width=200></a><br/>
40 Bundler is maintained by <a href="https://rubytogether.org/">Ruby Together</a>, a grassroots initiative committed to supporting the critical Ruby infrastructure you rely on. Contribute today <a href="https://rubytogether.org/developers">as an individual</a> or even better, <a href="https://rubytogether.org/companies">as a company</a>, and ensure that Bundler, RubyGems, and other shared tooling is around for years to come.
41
42 ### Other questions
43
44 To see what has changed in recent versions of Bundler, see the [CHANGELOG](CHANGELOG.md).
45
46 To get in touch with the Bundler core team and other Bundler users, please see [getting help](doc/contributing/GETTING_HELP.md).
47
48 ### Contributing
49
50 If you'd like to contribute to Bundler, that's awesome, and we <3 you. There's a guide to contributing to Bundler (both code and general help) over in [our documentation section](doc/README.md).
51
52 ### Code of Conduct
53
54 Everyone interacting in the Bundler project’s codebases, issue trackers, chat rooms, and mailing lists is expected to follow the [Bundler code of conduct](https://github.com/bundler/bundler/blob/master/CODE_OF_CONDUCT.md).
1 #!/usr/bin/env ruby
2 # frozen_string_literal: true
3
4 load File.expand_path("../with_rubygems", __FILE__) if ENV["RGV"]
5
6 require "rubygems"
7
8 bundler_spec = Gem::Specification.load(File.expand_path("../../bundler.gemspec", __FILE__))
9 bundler_spec.dependencies.each do |dep|
10 begin
11 gem dep.name, dep.requirement
12 rescue Gem::LoadError => e
13 $stderr.puts "#{e.message} (#{e.class})"
14 end
15 end
16
17 Gem.finish_resolve if Gem.respond_to?(:finish_resolve)
18
19 load Gem.bin_path("rake", "rake")
1 #!/usr/bin/env ruby
2 # frozen_string_literal: true
3
4 load File.expand_path("../with_rubygems", __FILE__) if ENV["RGV"]
5
6 require "rubygems"
7
8 bundler_spec = Gem::Specification.load(File.expand_path("../../bundler.gemspec", __FILE__))
9 bundler_spec.dependencies.each do |dep|
10 gem dep.name, dep.requirement
11 end
12
13 Gem.finish_resolve if Gem.respond_to?(:finish_resolve)
14
15 load Gem.bin_path("rspec-core", "rspec")
1 #!/usr/bin/env ruby
2 # frozen_string_literal: true
3
4 load File.expand_path("../with_rubygems", __FILE__) if ENV["RGV"]
5
6 require "rubygems"
7
8 bundler_spec = Gem::Specification.load(File.expand_path("../../bundler.gemspec", __FILE__))
9 bundler_spec.dependencies.each do |dep|
10 gem dep.name, dep.requirement
11 end
12
13 gem "rubocop", "= 0.48.0"
14
15 Gem.finish_resolve if Gem.respond_to?(:finish_resolve)
16
17 load Gem.bin_path("rubocop", "rubocop")
1 #!/usr/bin/env ruby
2 # frozen_string_literal: true
3
4 require "pathname"
5
6 def run(*cmd)
7 return if system(*cmd)
8 raise "Running `#{cmd.join(" ")}` failed"
9 end
10
11 version = ENV.delete("RGV")
12 rubygems_path = Pathname.new(__FILE__).join("../../tmp/rubygems").expand_path
13 unless rubygems_path.directory?
14 rubygems_path.parent.mkpath unless rubygems_path.directory?
15 run("git", "clone", "https://github.com/rubygems/rubygems.git", rubygems_path.to_s)
16 end
17 Dir.chdir(rubygems_path) do
18 version = "v#{version}" if version =~ /\A\d/
19 run("git", "checkout", version, "--quiet")
20 end if version
21
22 rubygems_lib = rubygems_path + "lib"
23 ENV["RUBYOPT"] = %(-I#{rubygems_lib} #{ENV["RUBYOPT"]})
24
25 if $0 != __FILE__
26 ARGV.unshift($0)
27 elsif cmd = ARGV.first
28 possible_dirs = [
29 Pathname.new(__FILE__) + "..",
30 Pathname.new(__FILE__) + "../../exe",
31 rubygems_path + "bin",
32 ]
33 cmd = possible_dirs.map do |dir|
34 dir.join(cmd).expand_path
35 end.find(&:file?)
36 ARGV[0] = cmd.to_s if cmd
37 end
38
39 exec(*ARGV)
1 # coding: utf-8
2 # frozen_string_literal: true
3 lib = File.expand_path("../lib/", __FILE__)
4 $:.unshift lib unless $:.include?(lib)
5 require "bundler/version"
6
7 Gem::Specification.new do |s|
8 s.name = "bundler"
9 s.version = Bundler::VERSION
10 s.license = "MIT"
11 s.authors = [
12 "André Arko", "Samuel Giddins", "Chris Morris", "James Wen", "Tim Moore",
13 "André Medeiros", "Jessica Lynn Suttles", "Terence Lee", "Carl Lerche",
14 "Yehuda Katz"
15 ]
16 s.email = ["team@bundler.io"]
17 s.homepage = "http://bundler.io"
18 s.summary = "The best way to manage your application's dependencies"
19 s.description = "Bundler manages an application's dependencies through its entire life, across many machines, systematically and repeatably"
20
21 if s.respond_to?(:metadata=)
22 s.metadata = {
23 "bug_tracker_uri" => "http://github.com/bundler/bundler/issues",
24 "changelog_uri" => "https://github.com/bundler/bundler/blob/master/CHANGELOG.md",
25 "homepage_uri" => "https://bundler.io/",
26 "source_code_uri" => "http://github.com/bundler/bundler/",
27 }
28 end
29
30 s.required_ruby_version = ">= 1.8.7"
31 s.required_rubygems_version = ">= 1.3.6"
32
33 s.add_development_dependency "automatiek", "~> 0.1.0"
34 s.add_development_dependency "mustache", "0.99.6"
35 s.add_development_dependency "rake", "~> 10.0"
36 s.add_development_dependency "rdiscount", "~> 2.2"
37 s.add_development_dependency "ronn", "~> 0.7.3"
38 s.add_development_dependency "rspec", "~> 3.5"
39
40 s.files = `git ls-files -z`.split("\x0").reject {|f| f.match(%r{^(test|spec|features)/}) }
41 # we don't check in man pages, but we need to ship them because
42 # we use them to generate the long-form help for each command.
43 s.files += Dir.glob("man/**/*")
44
45 s.bindir = "exe"
46 s.executables = %w(bundle bundler)
47 s.require_paths = ["lib"]
48 end
1 # Docs: Contributing and developing Bundler
2
3 _If you're looking for documentation on how to use Bundler: visit [bundler.io](http://bundler.io/), or run `bundle help` from the command line. You may also be interested in [troubleshooting common issues](TROUBLESHOOTING.md) found when using Bundler._
4
5 Bundler welcomes contributions from *everyone*. While contributing, please follow the project [code of conduct](http://bundler.io/conduct.html), so that everyone can be included.
6
7 If you'd like to help make Bundler better, you totally rock! Thanks for helping us make Bundler better.
8
9 ## Contributing
10
11 * [Overview & getting started](contributing/README.md)
12 * [How you can help: your first contributions!](contributing/HOW_YOU_CAN_HELP.md)
13 * [Bug triage](contributing/BUG_TRIAGE.md)
14 * [Getting help](contributing/GETTING_HELP.md)
15 * [Filing issues](contributing/ISSUES.md)
16 * [Community](contributing/COMMUNITY.md)
17
18 ## Development
19
20 * [Overview](development/README.md)
21 * [Development setup](development/SETUP.md)
22 * [Submitting pull requests](development/PULL_REQUESTS.md)
23 * [Adding new features](development/NEW_FEATURES.md)
24 * [Releasing Bundler](development/RELEASING.md)
25
26 ## Documentation
27
28 * [Overview](documentation/README.md)
29 * [Writing docs for man pages](documentation/WRITING.md)
30 * [Documentation vision](documentation/VISION.md)
1 # Troubleshooting common issues
2
3 Stuck using Bundler? Browse these common issues before [filing a new issue](contributing/ISSUES.md).
4
5 ## Permission denied when installing bundler
6
7 Certain operating systems such as MacOS and Ubuntu have versions of Ruby that require elevated privileges to install gems.
8
9 ERROR: While executing gem ... (Gem::FilePermissionError)
10 You don't have write permissions for the /Library/Ruby/Gems/2.0.0 directory.
11
12 There are multiple ways to solve this issue. You can install bundler with elevated privilges using `sudo` or `su`.
13
14 sudo gem install bundler
15
16 If you cannot elevated your privileges or do not want to globally install Bundler, you can use the `--user-install` option.
17
18 gem install bundler --user-install
19
20 This will install Bundler into your home directory. Note that you will need to append `~/.gem/ruby/<ruby version>/bin` to your `$PATH` variable to use `bundle`.
21
22 ## Heroku errors
23
24 Please open a ticket with [Heroku](https://www.heroku.com) if you're having trouble deploying. They have a professional support team who can help you resolve Heroku issues far better than the Bundler team can. If the problem that you are having turns out to be a bug in Bundler itself, [Heroku support](https://www.heroku.com/support) can get the exact details to us.
25
26 ## Other problems
27
28 First, figure out exactly what it is that you're trying to do (see [XY Problem](http://xyproblem.info/)). Then, go to the [Bundler documentation website](http://bundler.io) and see if we have instructions on how to do that.
29
30 Second, check [the compatibility
31 list](http://bundler.io/compatibility.html), and make sure that the version of Bundler that you are using works with the versions of Ruby and Rubygems that you are using. To see your versions:
32
33 # Bundler version
34 bundle -v
35
36 # Ruby version
37 ruby -v
38
39 # Rubygems version
40 gem -v
41
42 If these instructions don't work, or you can't find any appropriate instructions, you can try these troubleshooting steps:
43
44 # Remove user-specific gems and git repos
45 rm -rf ~/.bundle/ ~/.gem/bundler/ ~/.gems/cache/bundler/
46
47 # Remove system-wide git repos and git checkouts
48 rm -rf $GEM_HOME/bundler/ $GEM_HOME/cache/bundler/
49
50 # Remove project-specific settings
51 rm -rf .bundle/
52
53 # Remove project-specific cached gems and repos
54 rm -rf vendor/cache/
55
56 # Remove the saved resolve of the Gemfile
57 rm -rf Gemfile.lock
58
59 # Uninstall the rubygems-bundler and open_gem gems
60 rvm gemset use global # if using rvm
61 gem uninstall rubygems-bundler open_gem
62
63 # Try to install one more time
64 bundle install
1 # Bug triage
2
3 Triaging is the work of processing tickets that have been opened by users. Common tasks include verifying bugs, categorizing tickets, and ensuring there's enough information to reproduce the bug for anyone who wants to try to fix it.
4
5 We've created an [issues guide](ISSUES.md) to walk users through the process of how to report an issue with the Bundler project. We also have a [troubleshooting guide](../TROUBLESHOOTING.md) to diagnose common problems.
6
7 Not every ticket will be a bug in Bundler's code, but open tickets usually mean that the there is something we could improve to help that user. Sometimes that means writing additional documentation or making error messages clearer.
8
9 ## Triaging existing issues
10
11 When you're looking at a ticket, here are the main questions to ask:
12
13 * Can I reproduce this bug myself?
14 * Are the steps to reproduce the bug clearly documented in the ticket?
15 * Which versions of Bundler (1.1.x, 1.2.x, git, etc.) manifest this bug?
16 * Which operating systems (OS X, Windows, Ubuntu, CentOS, etc.) manifest this bug?
17 * Which rubies (MRI, JRuby, Rubinius, etc.) and which versions (1.8.7, 1.9.3, etc.) have this bug?
18
19 If you can't reproduce the issue, chances are good that the bug has been fixed already (hurrah!). That's a good time to post to the ticket explaining what you did and how it worked.
20
21 If you can reproduce an issue, you're well on your way to fixing it. :)
22
23 ## Fixing your triaged bug
24
25 Everyone is welcome and encouraged to fix any open bug, improve an error message or add documentation. If you have a fix or an improvement to a ticket that you would like to contribute, we have a small guide to help:
26
27 1. Discuss the fix on the existing issue. Coordinating with everyone else saves duplicate work and serves as a great way to get suggestions and ideas if you need any.
28 2. Base your commits on the correct branch. Bugfixes for 1.x versions of Bundler should be based on the matching 1-x-stable branch.
29 3. Review the [pull request guide](../development/PULL_REQUESTS.md).
30 4. Commit the code with at least one test covering your changes to a named branch in your fork.
31 5. Put a line in the [CHANGELOG](../../CHANGELOG.md) summarizing your changes under the next release under the “Bugfixes” heading.
32 6. Send us a [pull request](https://help.github.com/articles/using-pull-requests) from your bugfix branch.
33
34 ## Duplicates!
35
36 Finally, the ticket may be a duplicate of another older ticket. If you notice a ticket is a duplicate, simply comment on the ticket noting the original ticket’s number. For example, you could say “This is a duplicate of issue #42, and can be closed”.
1 # Community
2
3 Community is an important part of all we do. If you’d like to be part of the Bundler community, you can jump right in and start helping make Bundler better for everyone who uses it.
4
5 It would be tremendously helpful to have more people answering questions about Bundler (and often simply about [Rubygems](https://github.com/rubygems/rubygems) or Ruby itself) in our [issue tracker](https://github.com/bundler/bundler/issues) or on [Stack Overflow](http://stackoverflow.com/questions/tagged/bundler).
6
7 Additional documentation and explanation is always helpful, too. If you have any suggestions for the Bundler website [bundler.io](http://bundler.io), we would absolutely love it if you opened an issue or pull request on the [bundler-site](https://github.com/bundler/bundler-site) repository.
8
9 Sharing your experiences and discoveries by writing them up is a valuable way to help others who have similar problems or experiences in the future. You can write a blog post, create an example and commit it to GitHub, take screenshots, or make videos.
10
11 Publishing examples of how Bundler is used helps everyone, and we’ve discovered that people already use it in ways that we never imagined when we were writing it. If you’re still not sure what to write about, there are also several projects doing interesting things based on Bundler. They could probably use publicity too.
12
13 Finally, all contributors to the Bundler project must agree to the contributor [code of conduct](http://bundler.io/conduct.html). By participating in this project you agree to abide by its terms.
1 # Getting help
2
3 If you have any questions after reading the documentation for contributing, please feel free to contact either [@indirect](https://github.com/indirect), [@segiddins](https://github.com/segiddins), or [@RochesterinNYC](https://github.com/RochesterinNYC). They are all happy to provide help working through your first bug fix or thinking through the problem you’re trying to resolve.
4
5 The best ways to get in touch are:
6
7 * [Bundler Slack](https://bundler.slack.com).
8 * Not a member of the Slack? Join the Bundler team slack [here](http://slack.bundler.io/)!
9 * [Bundler mailing list](http://groups.google.com/group/ruby-bundler)
10
11 You may also find our guide on [filing issues](ISSUES.md) to be helpful as well!
1 # How you can help: your first commits!
2
3 If you’re interested in contributing to Bundler, that’s awesome! We’d love your help.
4
5 If at any point you get stuck, here's how to [get in touch with the Bundler team for help](GETTING_HELP.md).
6
7 ## First contribution suggestions
8
9 We track [small bugs and features](https://github.com/bundler/bundler/labels/contribution%3A%20small) so that anyone who wants to help can start with something that's not too overwhelming.
10
11 Generally, great ways to get started helping out with Bundler are:
12
13 - using prerelease versions (run `gem install bundler --pre`)
14 - [reporting bugs you encounter or suggesting new features](https://github.com/bundler/bundler/issues/new)
15 - see our [issues guide](ISSUES.md) for help on filing issues
16 - see the [new features documentation](../development/NEW_FEATURES.md) for more
17 - adding to or editing [the Bundler documentation website](http://bundler.io) and [Bundler man pages](http://bundler.io/man/bundle.1.html)
18 - [checking issues for completeness](BUG_TRIAGE.md)
19 - closing issues that are not complete
20 - adding a failing test for reproducible [reported bugs](https://github.com/bundler/bundler/issues)
21 - reviewing [pull requests](https://github.com/bundler/bundler/pulls) and suggesting improvements
22 - improving existing code, including suggestions from [PullReview](https://www.pullreview.com/github/bundler/bundler/reviews/master) or [CodeClimate](https://codeclimate.com/github/bundler/bundler)
23 - writing code (no patch is too small! fix typos or bad whitespace)
24 - get started setting up your dev environment with [these instructions](../development/DEVELOPMENT_SETUP.md)
25 - backfilling [unit tests](https://github.com/bundler/bundler/tree/master/spec/bundler) for modules that lack [coverage](https://codeclimate.com/github/bundler/bundler/coverage)
26
27 If nothing on those lists looks good, [talk to us](http://slack.bundler.io/), and we'll figure out what you can help with. We can absolutely use your help, no matter what level of programming skill you have at the moment.
1 # Filing Issues: a guide
2
3 So! You're having problems with Bundler. This file is here to help. If you're running into an error, try reading the rest of this file for help. If you can't figure out how to solve your problem, there are also instructions on how to report a bug.
4
5 Before filing an issue, check our [troubleshooting guide](../TROUBLESHOOTING.md) for quick fixes to common issues.
6
7 ## Documentation
8
9 Instructions for common Bundler uses can be found on the [Bundler documentation site](http://bundler.io/).
10
11 Detailed information about each Bundler command, including help with common problems, can be found in the [Bundler man pages](http://bundler.io/man/bundle.1.html) or [Bundler Command Line Reference](http://bundler.io/v1.11/commands.html).
12
13 ## Reporting unresolved problems
14
15 Check our [troubleshooting common issues guide](../TROUBLESHOOTING.md) and see if your issues is resolved using the steps provided.
16
17 Hopefully the troubleshooting steps above resolved your problem! If things still aren't working the way you expect them to, please let us know so that we can diagnose and hopefully fix the problem you're having.
18
19 **The best way to report a bug is by providing a reproduction script.** See these examples:
20
21 * [Git environment variables causing install to fail.](https://gist.github.com/xaviershay/6207550)
22 * [Multiple gems in a repository cannot be updated independently.](https://gist.github.com/xaviershay/6295889)
23
24 A half working script with comments for the parts you were unable to automate is still appreciated.
25
26 If you are unable to do that, please include the following information in your report:
27
28 - What you're trying to accomplish
29 - The command you ran
30 - What you expected to happen
31 - What actually happened
32 - The exception backtrace(s), if any
33 - Everything output by running `bundle env`
34
35 If your version of Bundler does not have the `bundle env` command, then please include:
36
37 - Your `Gemfile`
38 - Your `Gemfile.lock`
39 - Your Bundler configuration settings (run `bundle config`)
40 - What version of bundler you are using (run `bundle -v`)
41 - What version of Ruby you are using (run `ruby -v`)
42 - What version of Rubygems you are using (run `gem -v`)
43 - Whether you are using RVM, and if so what version (run `rvm -v`)
44 - Whether you have the `rubygems-bundler` gem, which can break gem executables (run `gem list rubygems-bundler`)
45 - Whether you have the `open_gem` gem, which can cause rake activation conflicts (run `gem list open_gem`)
46
47 If you have either `rubygems-bundler` or `open_gem` installed, please try removing them and then following the troubleshooting steps above before opening a new ticket.
48
49 [Create a gist](https://gist.github.com) containing all of that information, then visit the [Bundler issue tracker](https://github.com/bundler/bundler/issues) and [create a ticket](https://github.com/bundler/bundler/issues/new) describing your problem and linking to your gist.
50
51 Thanks for reporting issues and helping make Bundler better!
1 # Contributing to Bundler
2
3 Welcome to Bundler! We are so happy that you're here. We know it can be daunting to joining a new open source project, so here's a quick overview of what you can expect from this documentation.
4
5 *Something missing?* Send us a [pull request](../development/PULL_REQUESTS.md)!
6
7 **Recommended first steps**
8
9 - Join us in the Bundler slack! Generate an invite [here](http://slack.bundler.io/)
10 - *If you're interested in helping with code:*
11 - Get a quick overview of our [development process](../development/README.md)
12 - [Setup your machine for development](../development/SETUP.md)
13 - Checkout [How you can help: your first contributions!](HOW_YOU_CAN_HELP.md) for a list of suggestions to get started
14 - *If you're interested in helping with documentation:*
15 - Read up on [how documentation works for Bundler](../documentation/README.md)
16 - Learn about our [documentation vision](../documentation/VISION.md)
17
18 You can start learning about Bundler by reading [the documentation](http://bundler.io). If you want, you can also read a (lengthy) explanation of [why Bundler exists and what it does](http://bundler.io/rationale.html).
19
20 ##[How you can help: your first contributions!](HOW_YOU_CAN_HELP.md)
21
22 A detailed overview of how to get started contributing to Bundler, including a long list of suggestions for your first project.
23
24 ##[Bug triage](BUG_TRIAGE.md)
25
26 Want to take a stab at processing issues? Start here.
27
28 ##[Getting help](GETTING_HELP.md)
29
30 How to get in touch with folks who can help when you're stuck. Don't worry! This happens to all of us. We're really nice, we promise.
31
32 ##[Filing issues](ISSUES.md)
33
34 We see a lot of issues in the Bundler repo! Use this guide to file informative, actionable issues.
35
36 ##[Community](COMMUNITY.md)
37
38 Learn more about our goals for the Bundler community and the ways you can help us build better together.
1 # Adding New Features
2
3 If you would like to add a new feature to Bundler, please follow these steps:
4
5 1. [Create an issue](https://github.com/bundler/bundler/issues/new) with the [`feature-request` label](https://github.com/bundler/bundler/labels/type:%20feature-request) to discuss your feature.
6 2. Base your commits on the master branch, since we follow [SemVer](http://semver.org) and don't add new features to old releases.
7 3. Commit the code and at least one test covering your changes to a feature branch in your fork.
8 4. Send us a [pull request](PULL_REQUESTS.md) from your feature branch.
9
10 If you don't hear back immediately, don’t get discouraged! We all have day jobs, but we respond to most tickets within a day or two.
1 # Submitting Pull Requests
2
3 Before you submit a pull request, please remember to do the following:
4
5 1. Check your code format and style
6 2. Run the test suite
7 3. Use a meaningful commit message without tags
8
9 ## Code formatting
10
11 Make sure the code formatting and styling adheres to the guidelines. We use RuboCop for this. Lack of formatting adherence will result in automatic Travis build failures.
12
13 $ bin/rubocop -a
14
15 ## Tests
16
17 Prior to submitting your PR, please run the test suite:
18
19 $ bin/rspec
20
21 If you are unable to run the entire test suite, please run the unit test suite and at least the integration specs related to the command or domain of Bundler that your code changes relate to.
22
23 Ex. For a pull request that changes something with `bundle update`, you might run:
24
25 $ bin/rspec spec/bundler
26 $ bin/rspec spec/commands/update_spec.rb
27
28 ## Commit messages
29
30 Please ensure that the commit messages included in the pull request __do not__ have the following:
31 - `@tag` GitHub user or team references (ex. `@indirect` or `@bundler/core`)
32 - `#id` references to issues or pull requests (ex. `#43` or `bundler/bundler-site#12`)
33
34 If you want to use these mechanisms, please instead include them in the pull request description. This prevents multiple notifications or references being created on commit rebases or pull request/branch force pushes.
35
36 Additionally, do not use `[ci skip]` or `[skip ci]` mechanisms in your pull request titles/descriptions or commit messages. Every potential commit and pull request should run through Bundler's CI system. This applies to all changes/commits (ex. even a change to just documentation or the removal of a comment).
37
38 ## CHANGELOG.md
39
40 Don't forget to add your changes into the CHANGELOG! If you're submitting documentation, note the changes under the "Documentation" heading.
1 # Development
2
3 So, you're ready to start contributing to Bundler! You've come to the right place. Here you'll find an overview of how to work on Bundler locally and a description of the process from code to release.
4
5 ##[Development setup](SETUP.md)
6
7 Guidelines for setting up your local development environment.
8
9 ##[Submitting pull requests](PULL_REQUESTS.md)
10
11 An overview of our preferred PR process, including how to run the test suite and what to expect when you submit code for review.
12
13 ##[Adding new features](NEW_FEATURES.md)
14
15 Guidelines for proposing and writing new features for Bundler.
16
17 ##[Releasing Bundler](RELEASING.md)
18
19 A broad-strokes overview of the release process adhered to by the Bundler core team.
1 # Releasing
2
3 _Release process documentation is in progress, see [PR 5252](https://github.com/bundler/bundler/pull/5252)._
4
5 ## Beta testing
6
7 Early releases require heavy testing, especially across various system setups. We :heart: testers, and are big fans of anyone who can run `gem install bundler --pre` and try out upcoming releases in their development and staging environments.
8
9 There may not always be prereleases or beta versions of Bundler. The Bundler team will tweet from the [@bundlerio account](http://twitter.com/bundlerio) when a prerelease or beta version becomes available. You are also always welcome to try checking out master and building a gem yourself if you want to try out the latest changes.
1 # Development setup
2
3 Bundler doesn't use a Gemfile to list development dependencies, because when we tried it we couldn't tell if we were awake or it was just another level of dreams. To work on Bundler, you'll probably want to do a couple of things.
4
5 1. Install `groff-base` and `graphviz` packages using your package manager, e.g for ubuntu
6
7 $ sudo apt-get install graphviz groff-base -y
8
9 and for OS X (with brew installed)
10
11 $ brew install graphviz homebrew/dupes/groff
12
13 2. Install Bundler's development dependencies
14
15 $ bin/rake spec:deps
16
17 3. Run the test suite, to make sure things are working
18
19 $ bin/rake spec
20
21 4. Set up a shell alias to run Bundler from your clone, e.g. a Bash alias:
22
23 $ alias dbundle='BUNDLE_TRAMPOLINE_DISABLE=1 ruby -I /path/to/bundler/lib /path/to/bundler/exe/bundle'
24
25 The `BUNDLE_TRAMPOLINE_DISABLE` environment variable ensures that the version of Bundler in `/path/to/bundler/lib` will be used. Without that environment setting, Bundler will automatically download, install, and run the version of Bundler listed in `Gemfile.lock`. With that set up, you can test changes you've made to Bundler by running `dbundle`, without interfering with the regular `bundle` command.
26
27 ## Debugging with `pry`
28
29 To dive into the code with Pry: `RUBYOPT=-rpry dbundle` to require pry and then run commands.
1 # Documentation
2
3 Code needs explanation, and sometimes those who know the code well have trouble explaining it to someone just getting into it. Because of that, we welcome documentation suggestions and patches from everyone, especially if they are brand new to using Bundler.
4
5 Currently, Bundler has two main sources of documentation:
6
7 1. built-in `help` (including usage information and man pages)
8 2. [Bundler documentation site](http://bundler.io)
9
10 If you have a suggestion or proposed change for [bundler.io](http://bundler.io), please open an issue or send a pull request to the [bundler-site](https://github.com/bundler/bundler-site) repository.
11
12 Not sure where to write documentation? In general, follow these guidelines:
13
14 * For an explanation of a specific Bundler command (ex: `bundle clean`): make changes to the man pages
15 * For longer explanations or usage guides (ex: "Using Bundler with Rails"): create new documentation within the [bundler-site](https://github.com/bundler/bundler-site) repository
16
17 If you are unsure where to begin, ping [@feministy](https://github.com/feministy) or [@indirect](https://github.com/indirect) in the Bundler Slack ([get an invite here](../contributing/GETTING_HELP.md)).
18
19 ## [Writing docs for man pages)](WRITING.md)
20
21 If you’d like to submit a patch to the man pages, you're in the right place! Details on editing and previewing changes to man pages can be found here.
22
23 ## [Documentation vision](VISION.md)
24
25 Just like Bundler, we have a grand plan (really, a wish list of sorts) for Bundler documentation. Preview our hopes and dreams for our documentation here.
26
27 ## Translations
28
29 We don't currently have any translations, but please reach out to us if you would like to help get this going.
1 # Documentation vision
2
3 Currently, documentation for using Bundler is spread across two places:
4
5 1. built-in `help` (including usage information and man pages)
6 2. [Bundler documentation site](http://bundler.io)
7
8 Additional documentation about using Bundler to publish gems can also be found on the [RubyGems guides](http://guides.rubygems.org/).
9
10 ## Goals
11
12 Bundler documentation should provide users with assistance:
13
14 1. Installing Bundler
15 2. Using Bundler to manage an application's dependencies
16 3. Using Bundler to create, package, and publish gems
17
18 Our goal is to provide three types of documentation:
19
20 * High level overviews that provide topical guidance
21 * Step-by-step tutorials
22 * Command-specific reference material for the CLI
23
24 Additionally, this documentation should be readily available in a logical place and easy to follow.
25
26 Someday, we'd like to create deep-dive reference material about the inner workings of Bundler. However, while this is part of our overall vision for Bundler documentation, it is not the focus of our current work.
1 # Writing docs for man pages
2
3 A primary source of help for Bundler users are the man pages: the output printed when you run `bundle help` (or `bundler help`). These pages can be a little tricky to format and preview, but are pretty straightforward once you get the hang of it.
4
5 _Note: `bundler` and `bundle` may be used interchangeably in the CLI. This guide uses `bundle` because it's cuter._
6
7 ## What goes in man pages?
8
9 We use man pages for Bundler commands used in the CLI (command line interface). They can vary in length from large (see `bundle install`) to very short (see `bundle clean`).
10
11 To see a list of commands available in the Bundler CLI, type:
12
13 $ bundle help
14
15 Our goal is to have a man page for every command.
16
17 Don't see a man page for a command? Make a new page and send us a PR! We also welcome edits to existing pages.
18
19 ## Creating a new man page
20
21 To create a new man page, simply create a new `.ronn` file in the `man/` directory.
22
23 For example: to create a man page for the command `bundle cookies` (not a real command, sadly), I would create a file `man/bundle-cookies.ronn` and add my documentation there.
24
25 ## Formatting
26
27 Our man pages use ronn formatting, a combination of Markdown and standard man page conventions. It can be a little weird getting used to it at first, especially if you've used Markdown a lot.
28
29 [The ronn guide formatting guide](https://rtomayko.github.io/ronn/ronn.7.html) provides a good overview of the common types of formatting.
30
31 In general, make your page look like the other pages: utilize sections like `##OPTIONS` and formatting like code blocks and definition lists where appropriate.
32
33 If you're not sure if the formatting looks right, that's ok! Make a pull request with what you've got and we'll take a peek.
34
35 ## Previewing
36
37 To preview your changes as they will print out for Bundler users, you'll need to run a series of commands:
38
39 ```
40 $ rake spec:deps
41 $ rake man:build
42 $ man man/bundle-cookies.1
43 ```
44
45 If you make more changes to `bundle-cookies.ronn`, you'll need to run the `rake man:build` again before previewing.
46
47 ## Testing
48
49 We have tests for our documentation! The most important test file to run before you make your pull request is the one for the `help` command and another for documentation quality.
50
51 ```
52 $ rspec ./spec/commands/help_spec.rb
53 $ rspec ./spec/quality_spec.rb
54 ```
1 #!/usr/bin/env ruby
2 # frozen_string_literal: true
3
4 # Exit cleanly from an early interrupt
5 Signal.trap("INT") do
6 Bundler.ui.debug("\n#{caller.join("\n")}") if defined?(Bundler)
7 exit 1
8 end
9
10 update = "update".start_with?(ARGV.first || " ") && ARGV.find {|a| a.start_with?("--bundler") }
11 update &&= update =~ /--bundler(?:=(.+))?/ && $1 || "> 0.a"
12 ENV["BUNDLER_VERSION"] = update if update
13 require "bundler/postit_trampoline"
14
15 require "bundler"
16 # Check if an older version of bundler is installed
17 $LOAD_PATH.each do |path|
18 next unless path =~ %r{/bundler-0\.(\d+)} && $1.to_i < 9
19 err = String.new
20 err << "Looks like you have a version of bundler that's older than 0.9.\n"
21 err << "Please remove your old versions.\n"
22 err << "An easy way to do this is by running `gem cleanup bundler`."
23 abort(err)
24 end
25
26 require "bundler/friendly_errors"
27 Bundler.with_friendly_errors do
28 require "bundler/cli"
29
30 # Allow any command to use --help flag to show help for that command
31 help_flags = %w(--help -h)
32 help_flag_used = ARGV.any? {|a| help_flags.include? a }
33 args = help_flag_used ? Bundler::CLI.reformatted_help_args(ARGV) : ARGV
34
35 Bundler::CLI.start(args, :debug => true)
36 end
1 #!/usr/bin/env ruby
2 # frozen_string_literal: true
3
4 Signal.trap("INT") { exit 1 }
5
6 require "bundler/errors"
7 require "bundler/ruby_version"
8 require "bundler/ruby_dsl"
9 require "bundler/shared_helpers"
10
11 module Bundler
12 class Dsl
13 include RubyDsl
14
15 attr_accessor :ruby_version
16
17 def initialize
18 @ruby_version = nil
19 end
20
21 def eval_gemfile(gemfile, contents = nil)
22 contents ||= File.open(gemfile, "rb", &:read)
23 instance_eval(contents, gemfile.to_s, 1)
24 rescue SyntaxError => e
25 bt = e.message.split("\n")[1..-1]
26 raise GemfileError, ["Gemfile syntax error:", *bt].join("\n")
27 rescue ScriptError, RegexpError, NameError, ArgumentError => e
28 e.backtrace[0] = "#{e.backtrace[0]}: #{e.message} (#{e.class})"
29 STDERR.puts e.backtrace.join("\n ")
30 raise GemfileError, "There was an error in your Gemfile," \
31 " and Bundler cannot continue."
32 end
33
34 def source(source, options = {})
35 end
36
37 def gem(name, *args)
38 end
39
40 def group(*args)
41 end
42 end
43 end
44
45 Bundler::SharedHelpers.major_deprecation("the bundle_ruby executable has been removed in favor of `bundle platform --ruby`")
46
47 dsl = Bundler::Dsl.new
48 begin
49 dsl.eval_gemfile(Bundler::SharedHelpers.default_gemfile)
50 ruby_version = dsl.ruby_version
51 if ruby_version
52 puts ruby_version
53 else
54 puts "No ruby version specified"
55 end
56 rescue Bundler::GemfileError => e
57 puts e.message
58 exit(-1)
59 end
1 #!/usr/bin/env ruby
2 # frozen_string_literal: true
3
4 load File.expand_path("../bundle", __FILE__)
1 # frozen_string_literal: true
2 # Capistrano task for Bundler.
3 #
4 # Add "require 'bundler/capistrano'" in your Capistrano deploy.rb, and
5 # Bundler will be activated after each new deployment.
6 require "bundler/deployment"
7 require "capistrano/version"
8
9 if defined?(Capistrano::Version) && Gem::Version.new(Capistrano::Version).release >= Gem::Version.new("3.0")
10 raise "For Capistrano 3.x integration, please use http://github.com/capistrano/bundler"
11 end
12
13 Capistrano::Configuration.instance(:must_exist).load do
14 before "deploy:finalize_update", "bundle:install"
15 Bundler::Deployment.define_task(self, :task, :except => { :no_release => true })
16 set :rake, lambda { "#{fetch(:bundle_cmd, "bundle")} exec rake" }
17 end
1 # frozen_string_literal: true
2 require "bundler/cli/common"
3
4 module Bundler
5 class CLI::Add
6 def initialize(options, gem_name)
7 @gem_name = gem_name
8 @options = options
9 @options[:group] = @options[:group].split(",").map(&:strip) if !@options[:group].nil? && !@options[:group].empty?
10 end
11
12 def run
13 version = @options[:version].nil? ? nil : @options[:version].split(",").map(&:strip)
14
15 unless version.nil?
16 version.each do |v|
17 raise InvalidOption, "Invalid gem requirement pattern '#{v}'" unless Gem::Requirement::PATTERN =~ v.to_s
18 end
19 end
20 dependency = Bundler::Dependency.new(@gem_name, version, @options)
21
22 Injector.inject([dependency], :conservative_versioning => @options[:version].nil?) # Perform conservative versioning only when version is not specified
23 Installer.install(Bundler.root, Bundler.definition)
24 end
25 end
26 end
1 # frozen_string_literal: true
2 require "bundler/cli/common"
3
4 module Bundler
5 class CLI::Binstubs
6 attr_reader :options, :gems
7 def initialize(options, gems)
8 @options = options
9 @gems = gems
10 end
11
12 def run
13 Bundler.definition.validate_runtime!
14 Bundler.settings[:bin] = options["path"] if options["path"]
15 Bundler.settings[:bin] = nil if options["path"] && options["path"].empty?
16 installer = Installer.new(Bundler.root, Bundler.definition)
17
18 if gems.empty?
19 Bundler.ui.error "`bundle binstubs` needs at least one gem to run."
20 exit 1
21 end
22
23 gems.each do |gem_name|
24 spec = Bundler.definition.specs.find {|s| s.name == gem_name }
25 unless spec
26 raise GemNotFound, Bundler::CLI::Common.gem_not_found_message(
27 gem_name, Bundler.definition.specs
28 )
29 end
30
31 if spec.name == "bundler"
32 Bundler.ui.warn "Sorry, Bundler can only be run via Rubygems."
33 elsif options[:standalone]
34 installer.generate_standalone_bundler_executable_stubs(spec)
35 else
36 installer.generate_bundler_executable_stubs(spec, :force => options[:force], :binstubs_cmd => true)
37 end
38 end
39 end
40 end
41 end
1 # frozen_string_literal: true
2 module Bundler
3 class CLI::Cache
4 attr_reader :options
5 def initialize(options)
6 @options = options
7 end
8
9 def run
10 Bundler.definition.validate_runtime!
11 Bundler.definition.resolve_with_cache!
12 setup_cache_all
13 Bundler.settings[:cache_all_platforms] = options["all-platforms"] if options.key?("all-platforms")
14 Bundler.load.cache
15 Bundler.settings[:no_prune] = true if options["no-prune"]
16 Bundler.load.lock
17 rescue GemNotFound => e
18 Bundler.ui.error(e.message)
19 Bundler.ui.warn "Run `bundle install` to install missing gems."
20 exit 1
21 end
22
23 private
24
25 def setup_cache_all
26 Bundler.settings[:cache_all] = options[:all] if options.key?("all")
27
28 if Bundler.definition.has_local_dependencies? && !Bundler.settings[:cache_all]
29 Bundler.ui.warn "Your Gemfile contains path and git dependencies. If you want " \
30 "to package them as well, please pass the --all flag. This will be the default " \
31 "on Bundler 2.0."
32 end
33 end
34 end
35 end
1 # frozen_string_literal: true
2 module Bundler
3 class CLI::Check
4 attr_reader :options
5
6 def initialize(options)
7 @options = options
8 end
9
10 def run
11 if options[:path]
12 Bundler.settings[:path] = File.expand_path(options[:path])
13 Bundler.settings[:disable_shared_gems] = true
14 end
15
16 begin
17 definition = Bundler.definition
18 definition.validate_runtime!
19 not_installed = definition.missing_specs
20 rescue GemNotFound, VersionConflict
21 Bundler.ui.error "Bundler can't satisfy your Gemfile's dependencies."
22 Bundler.ui.warn "Install missing gems with `bundle install`."
23 exit 1
24 end
25
26 if not_installed.any?
27 Bundler.ui.error "The following gems are missing"
28 not_installed.each {|s| Bundler.ui.error " * #{s.name} (#{s.version})" }
29 Bundler.ui.warn "Install missing gems with `bundle install`"
30 exit 1
31 elsif !Bundler.default_lockfile.file? && Bundler.settings[:frozen]
32 Bundler.ui.error "This bundle has been frozen, but there is no #{Bundler.default_lockfile.relative_path_from(SharedHelpers.pwd)} present"
33 exit 1
34 else
35 Bundler.load.lock(:preserve_unknown_sections => true) unless options[:"dry-run"]
36 Bundler.ui.info "The Gemfile's dependencies are satisfied"
37 end
38 end
39 end
40 end
1 # frozen_string_literal: true
2 module Bundler
3 class CLI::Clean
4 attr_reader :options
5
6 def initialize(options)
7 @options = options
8 end
9
10 def run
11 require_path_or_force unless options[:"dry-run"]
12 Bundler.load.clean(options[:"dry-run"])
13 end
14
15 protected
16
17 def require_path_or_force
18 if !Bundler.settings[:path] && !options[:force]
19 Bundler.ui.error "Cleaning all the gems on your system is dangerous! " \
20 "If you're sure you want to remove every system gem not in this " \
21 "bundle, run `bundle clean --force`."
22 exit 1
23 end
24 end
25 end
26 end
1 # frozen_string_literal: true
2 module Bundler
3 module CLI::Common
4 def self.output_post_install_messages(messages)
5 return if Bundler.settings["ignore_messages"]
6 messages.to_a.each do |name, msg|
7 print_post_install_message(name, msg) unless Bundler.settings["ignore_messages.#{name}"]
8 end
9 end
10
11 def self.print_post_install_message(name, msg)
12 Bundler.ui.confirm "Post-install message from #{name}:"
13 Bundler.ui.info msg
14 end
15
16 def self.output_without_groups_message
17 return unless Bundler.settings.without.any?
18 Bundler.ui.confirm without_groups_message
19 end
20
21 def self.without_groups_message
22 groups = Bundler.settings.without
23 group_list = [groups[0...-1].join(", "), groups[-1..-1]].
24 reject {|s| s.to_s.empty? }.join(" and ")
25 group_str = (groups.size == 1) ? "group" : "groups"
26 "Gems in the #{group_str} #{group_list} were not installed."
27 end
28
29 def self.select_spec(name, regex_match = nil)
30 specs = []
31 regexp = Regexp.new(name) if regex_match
32
33 Bundler.definition.specs.each do |spec|
34 return spec if spec.name == name
35 specs << spec if regexp && spec.name =~ regexp
36 end
37
38 case specs.count
39 when 0
40 raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies)
41 when 1
42 specs.first
43 else
44 ask_for_spec_from(specs)
45 end
46 rescue RegexpError
47 raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies)
48 end
49
50 def self.ask_for_spec_from(specs)
51 if !$stdout.tty? && ENV["BUNDLE_SPEC_RUN"].nil?
52 raise GemNotFound, gem_not_found_message(name, Bundler.definition.dependencies)
53 end
54
55 specs.each_with_index do |spec, index|
56 Bundler.ui.info "#{index.succ} : #{spec.name}", true
57 end
58 Bundler.ui.info "0 : - exit -", true
59
60 num = Bundler.ui.ask("> ").to_i
61 num > 0 ? specs[num - 1] : nil
62 end
63
64 def self.gem_not_found_message(missing_gem_name, alternatives)
65 require "bundler/similarity_detector"
66 message = "Could not find gem '#{missing_gem_name}'."
67 alternate_names = alternatives.map {|a| a.respond_to?(:name) ? a.name : a }
68 suggestions = SimilarityDetector.new(alternate_names).similar_word_list(missing_gem_name)
69 message += "\nDid you mean #{suggestions}?" if suggestions
70 message
71 end
72
73 def self.ensure_all_gems_in_lockfile!(names, locked_gems = Bundler.locked_gems)
74 locked_names = locked_gems.specs.map(&:name)
75 names.-(locked_names).each do |g|
76 raise GemNotFound, gem_not_found_message(g, locked_names)
77 end
78 end
79
80 def self.configure_gem_version_promoter(definition, options)
81 patch_level = patch_level_options(options)
82 raise InvalidOption, "Provide only one of the following options: #{patch_level.join(", ")}" unless patch_level.length <= 1
83 definition.gem_version_promoter.tap do |gvp|
84 gvp.level = patch_level.first || :major
85 gvp.strict = options[:strict] || options["update-strict"]
86 end
87 end
88
89 def self.patch_level_options(options)
90 [:major, :minor, :patch].select {|v| options.keys.include?(v.to_s) }
91 end
92 end
93 end
1 # frozen_string_literal: true
2 module Bundler
3 class CLI::Config
4 attr_reader :name, :options, :scope, :thor
5 attr_accessor :args
6
7 def initialize(options, args, thor)
8 @options = options
9 @args = args
10 @thor = thor
11 @name = peek = args.shift
12 @scope = "global"
13 return unless peek && peek.start_with?("--")
14 @name = args.shift
15 @scope = peek[2..-1]
16 end
17
18 def run
19 unless name
20 confirm_all
21 return
22 end
23
24 unless valid_scope?(scope)
25 Bundler.ui.error "Invalid scope --#{scope} given. Please use --local or --global."
26 exit 1
27 end
28
29 if scope == "delete"
30 Bundler.settings.set_local(name, nil)
31 Bundler.settings.set_global(name, nil)
32 return
33 end
34
35 if args.empty?
36 if options[:parseable]
37 if value = Bundler.settings[name]
38 Bundler.ui.info("#{name}=#{value}")
39 end
40 return
41 end
42
43 confirm(name)
44 return
45 end
46
47 Bundler.ui.info(message) if message
48 Bundler.settings.send("set_#{scope}", name, new_value)
49 end
50
51 private
52
53 def confirm_all
54 if @options[:parseable]
55 thor.with_padding do
56 Bundler.settings.all.each do |setting|
57 val = Bundler.settings[setting]
58 Bundler.ui.info "#{setting}=#{val}"
59 end
60 end
61 else
62 Bundler.ui.confirm "Settings are listed in order of priority. The top value will be used.\n"
63 Bundler.settings.all.each do |setting|
64 Bundler.ui.confirm "#{setting}"
65 show_pretty_values_for(setting)
66 Bundler.ui.confirm ""
67 end
68 end
69 end
70
71 def confirm(name)
72 Bundler.ui.confirm "Settings for `#{name}` in order of priority. The top value will be used"
73 show_pretty_values_for(name)
74 end
75
76 def new_value
77 pathname = Pathname.new(args.join(" "))
78 if name.start_with?("local.") && pathname.directory?
79 pathname.expand_path.to_s
80 else
81 args.join(" ")
82 end
83 end
84
85 def message
86 locations = Bundler.settings.locations(name)
87 if @options[:parseable]
88 "#{name}=#{new_value}" if new_value
89 elsif scope == "global"
90 if locations[:local]
91 "Your application has set #{name} to #{locations[:local].inspect}. " \
92 "This will override the global value you are currently setting"
93 elsif locations[:env]
94 "You have a bundler environment variable for #{name} set to " \
95 "#{locations[:env].inspect}. This will take precedence over the global value you are setting"
96 elsif locations[:global] && locations[:global] != args.join(" ")
97 "You are replacing the current global value of #{name}, which is currently " \
98 "#{locations[:global].inspect}"
99 end
100 elsif scope == "local" && locations[:local] != args.join(" ")
101 "You are replacing the current local value of #{name}, which is currently " \
102 "#{locations[:local].inspect}"
103 end
104 end
105
106 def show_pretty_values_for(setting)
107 thor.with_padding do
108 Bundler.settings.pretty_values_for(setting).each do |line|
109 Bundler.ui.info line
110 end
111 end
112 end
113
114 def valid_scope?(scope)
115 %w(delete local global).include?(scope)
116 end
117 end
118 end