bummr 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: e4e45c2c7ad39b56f06d1f4d1d9b92e81b9cfe99
4
+ data.tar.gz: 3926625ea98f21b174811801d4651fe57529714e
5
+ SHA512:
6
+ metadata.gz: 25f941aa5afaf12e341ca4418a456431e6fa7d1bbc1ad993d96fb848dc67a49bdbf26cff85c4e584037f5024cb4423f0cc5cfc9ccdf80cf61b7195e8f6fc7368
7
+ data.tar.gz: 55f6cb69285537ec993bbfd573c33ae1b550656f4a8b14b7e5906c7b967cfb09a47ad3d384e188e684c524061189538e465a1c404ebb731c5815a36ee88e682f
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+ *.bundle
11
+ *.so
12
+ *.o
13
+ *.a
14
+ mkmf.log
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 2.2.2
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in bummr.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Ryan Sonnek
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,95 @@
1
+ # Bummr
2
+
3
+ Updating Gems one by one is a Bummr: especially when one gem causes your build
4
+ to fail.
5
+
6
+ The *Bummr* gem allows you to automatically update all gems which pass your
7
+ build in separate commits, and logs the name and sha of each gem that fails.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ $ gem install bummr
13
+ ```
14
+
15
+ Add a file called `.bummr-build.sh` to the root of your git directory.
16
+
17
+ Here is a suggested `.bummr-build.sh` which will `bundle exec rake` 4 times:
18
+
19
+ `.bummr-build.sh`
20
+
21
+ ```bash
22
+ #!/bin/sh
23
+ MAX_TRIES=4
24
+ COUNT=0
25
+ EXIT=0
26
+
27
+ while [ $COUNT -lt $MAX_TRIES ] && [ $EXIT -eq 0 ]; do
28
+ git log --pretty=format:'%s' -n 1
29
+ echo "\nRunning test suite... $COUNT of $MAX_TRIES"
30
+ bundle exec rake
31
+ let EXIT=$?
32
+ let COUNT=COUNT+1
33
+ done
34
+
35
+ exit $EXIT
36
+ ```
37
+
38
+ Commit this file and merge it to master before running `bummr update`!
39
+
40
+ ## Usage:
41
+
42
+ - Create a new, clean branch off of master.
43
+ - Run `bummr update`
44
+
45
+ ##### `bummr update`
46
+
47
+ - Finds all your outdated gems
48
+ - Updates them each individually, using `bundle update --source #{gemname}`
49
+ - Commits each gem update separately, with a commit message like:
50
+
51
+ `gemname, {0.0.1 -> 0.0.2}`
52
+
53
+ - Runs `git rebase -i master` to allow you the chance to review and make changes.
54
+ - Runs `bummr test`
55
+
56
+ ##### `bummr test`
57
+
58
+ - Runs your build script (`.bummr-build.sh`).
59
+ - If there is a failure, runs `bummr bisect`.
60
+
61
+ ##### `bummr bisect`
62
+
63
+ - `git bisect`s against master.
64
+ - Finds the bad commit and attempts to remove it.
65
+ - Logs the bad commit in `log/bummr.log`.
66
+ - Runs `bummr test`
67
+
68
+ ## Notes
69
+
70
+ - Once the build passes, you can push your branch and create a pull-request!
71
+ - You may wish to `tail -f log/bummr.log` in a separate terminal window so you
72
+ can see which commits are being removed.
73
+ - Bummr may not be able to remove the bad commit due to a merge conflict, in
74
+ which case you will have to remove it manually, continue the rebase, and
75
+ run `bummr test` again.
76
+
77
+ ## Contributing
78
+
79
+ 1. Fork it ( https://github.com/lpender/bummr/fork )
80
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
81
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
82
+ 4. Push to the branch (`git push origin my-new-feature`)
83
+ 5. Create a new Pull Request
84
+
85
+ ## Wanted
86
+
87
+ Here are some things I'd love to add to Bummr:
88
+
89
+ - Test coverage.
90
+ - Configuration options (for test script path, name of master branch, etc)
91
+
92
+ ## Thank you!
93
+
94
+ Thanks to Ryan Sonnek for the [Bundler
95
+ Updater](https://github.com/wireframe/bundler-updater) gem.
data/Rakefile ADDED
@@ -0,0 +1,2 @@
1
+ require "bundler/gem_tasks"
2
+
data/bin/bummr ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/bummr/cli'
4
+ Bummr::CLI.start(ARGV)
data/bummr.gemspec ADDED
@@ -0,0 +1,28 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'bummr/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "bummr"
8
+ spec.version = Bummr::VERSION
9
+ spec.authors = ["Lee Pender"]
10
+ spec.email = ["lpender@gmail.com"]
11
+ spec.summary = %q{Helper script to intelligently update your Gemfile}
12
+ spec.description = %q{See Readme}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files -z`.split("\x0")
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.add_dependency 'thor'
22
+ spec.add_dependency 'colorize'
23
+
24
+ spec.add_development_dependency "bundler", "~> 1.7"
25
+ spec.add_development_dependency "rake", "~> 10.0"
26
+ spec.add_development_dependency 'rspec'
27
+ spec.add_development_dependency 'pry'
28
+ end
data/lib/bummr/cli.rb ADDED
@@ -0,0 +1,213 @@
1
+ require 'bundler'
2
+ require 'thor'
3
+ require 'open3'
4
+ require 'colorize'
5
+
6
+ module Bummr
7
+ class CLI < Thor
8
+ desc "check", "Run automated checks to see if bummr can be run"
9
+ def check(fullcheck=true)
10
+ errors = []
11
+
12
+ if `git rev-parse --abbrev-ref HEAD` == "master\n"
13
+ message = "Bummr is not meant to be run on master"
14
+ say message.red
15
+ say "Please checkout a branch with 'git checkout -b update-gems'"
16
+ errors.push message
17
+ end
18
+
19
+ unless File.file?(".bummr-build.sh") && File.executable?(".bummr-build.sh")
20
+ message = "You must have a file '.bummr-build.sh' which runs your build"
21
+ say message.red
22
+ errors.push message
23
+ end
24
+
25
+ unless File.directory? "log"
26
+ message = "There is no log directory or you are not in the root"
27
+ say message.red
28
+ errors.push message
29
+ end
30
+
31
+ if fullcheck == true
32
+ unless `git diff master`.empty?
33
+ message = "Please make sure that `git diff master` returns empty"
34
+ say message.red
35
+ errors.push message
36
+ end
37
+ end
38
+
39
+ if errors.any?
40
+ exit 0
41
+ else
42
+ puts "Ready to run bummr.".green
43
+ end
44
+ end
45
+
46
+ desc "update", "Update outdated gems, run tests, bisect if tests fail"
47
+ def update
48
+ say "To run Bummr, you must:"
49
+ say "- Be in the root path of a clean git branch off of master"
50
+ say "- Have no commits or local changes"
51
+ say "- Have a file, '.bummr-build.sh' on master that runs your build"
52
+ say "- Have a 'log' directory, where we can place logs"
53
+ say "- Have your build configured to fail fast (recommended)"
54
+ say "- Have locked any Gem version that you don't wish to update in your Gemfile"
55
+ say "- It is recommended that you lock your versions of `ruby` and `rails in your Gemfile`"
56
+
57
+ if yes? "Are you ready to use Bummr? (y/n)"
58
+ check
59
+ `bundle`
60
+
61
+ if outdated_gems_to_update.empty?
62
+ say "No outdated gems to update".green
63
+ else
64
+ say "Updating outdated gems:"
65
+ say outdated_gems_to_update.map { |g| "* #{g}" }.join("\n")
66
+
67
+ outdated_gems_to_update.each_with_index do |gem, index|
68
+ message = "#{gem[:name]}, {#{gem[:current_version]} -> #{gem[:spec_version]}}"
69
+ say "Updating #{message}, #{index+1} of #{outdated_gems_to_update.count}"
70
+
71
+ system("bundle update --source #{gem[:name]}")
72
+ system("git commit -am '#{message}'")
73
+ end
74
+
75
+ say "Choose which gems to update"
76
+ system("git rebase -i master")
77
+ end
78
+
79
+ test
80
+ else
81
+ say "Thank you!".green
82
+ end
83
+ end
84
+
85
+ desc "test", "Test for a successful build and bisect if necesssary"
86
+ def test
87
+ check(false)
88
+ say "Testing the build!".green
89
+
90
+ if system("./.bummr-build.sh") == false
91
+ `bundle`
92
+ bisect
93
+ else
94
+ say "Passed the build!".green
95
+ say "See log/bummr.log for details".yellow
96
+ system("cat log/bummr.log")
97
+ end
98
+ end
99
+
100
+ desc "bisect", "Find the bad commit, remove it, test again"
101
+ def bisect
102
+ check(false)
103
+ say "Bad commits found! Bisecting...".red
104
+ log "Bad commits found: #{Time.now}"
105
+
106
+ system("git bisect start head master")
107
+
108
+ Open3.popen2e("git bisect run ./.bummr-build.sh") do |std_in, std_out_err|
109
+ while line = std_out_err.gets
110
+ puts line
111
+
112
+ sha_regex = Regexp::new("(.*) is the first bad commit\n").match(line)
113
+ unless sha_regex.nil?
114
+ sha = sha_regex[1]
115
+ end
116
+
117
+ if line == "bisect run success\n"
118
+ remove_commit(sha)
119
+ end
120
+ end
121
+ end
122
+ end
123
+
124
+ private
125
+
126
+ def log(message)
127
+ system("touch log/bummr.log && echo '#{message}' >> log/bummr.log")
128
+ end
129
+
130
+ # see bundler/lib/bundler/cli/outdated.rb
131
+ def outdated_gems_to_update
132
+ @gems_to_update ||= begin
133
+ say 'Scanning for outdated gems...'
134
+ gems_to_update = []
135
+
136
+ all_gem_specs.each do |current_spec|
137
+ active_spec = bundle_spec(current_spec)
138
+ next if active_spec.nil?
139
+
140
+ if spec_outdated?(current_spec, active_spec)
141
+ spec_version = "#{active_spec.version}#{active_spec.git_version}"
142
+ current_version = "#{current_spec.version}#{current_spec.git_version}"
143
+
144
+ gem_to_update = { name: active_spec.name, spec_version: spec_version, current_version: current_version }
145
+
146
+ say "Adding #{gem_to_update[:name]} version: #{gem_to_update[:current_version]} to update list"
147
+
148
+ gems_to_update << gem_to_update
149
+ end
150
+ end
151
+
152
+ gems_to_update.sort_by do |gem|
153
+ gem[:name]
154
+ end
155
+ end
156
+ end
157
+
158
+ def remove_commit(sha)
159
+ commit_message = `git log --pretty=format:'%s' -n 1 #{sha}`
160
+ message = "Could not apply: #{commit_message}, #{sha}"
161
+
162
+ say message.red
163
+ log message
164
+
165
+ say "Resetting..."
166
+ system("git bisect reset")
167
+
168
+ say "Removing commit..."
169
+ if system("git rebase -X ours --onto #{sha}^ #{sha}")
170
+ say "Successfully removed bad commit...".green
171
+ say "Re-testing build...".green
172
+ test
173
+ else
174
+ say message.red
175
+ say "Could not automatically remove this commit!".red
176
+ say "Please resolve conflicts, then 'git rebase --continue'."
177
+ say "Run 'bummr test' again once the rebase is complete"
178
+ end
179
+ end
180
+
181
+ def spec_outdated?(current_spec, active_spec)
182
+ gem_outdated = Gem::Version.new(active_spec.version) > Gem::Version.new(current_spec.version)
183
+ git_outdated = current_spec.git_version != active_spec.git_version
184
+
185
+ gem_outdated || git_outdated
186
+ end
187
+
188
+ def bundle_spec(current_spec)
189
+ active_spec = bundle_definition.index[current_spec.name].sort_by { |b| b.version }
190
+ if !current_spec.version.prerelease? && !options[:pre] && active_spec.size > 1
191
+ active_spec = active_spec.delete_if { |b| b.respond_to?(:version) && b.version.prerelease? }
192
+ end
193
+ active_spec.last
194
+ end
195
+
196
+ def all_gem_specs
197
+ current_specs = Bundler.ui.silence { Bundler.load.specs }
198
+ current_dependencies = {}
199
+ Bundler.ui.silence { Bundler.load.dependencies.each { |dep| current_dependencies[dep.name] = dep } }
200
+ gemfile_specs, dependency_specs = current_specs.partition { |spec| current_dependencies.has_key? spec.name }
201
+ [gemfile_specs, dependency_specs].flatten.sort_by(&:name)
202
+ end
203
+
204
+ def bundle_definition
205
+ @definition ||= begin
206
+ Bundler.definition.validate_ruby!
207
+ definition = Bundler.definition(true)
208
+ definition.resolve_remotely!
209
+ definition
210
+ end
211
+ end
212
+ end
213
+ end
@@ -0,0 +1,3 @@
1
+ module Bummr
2
+ VERSION = "0.0.2"
3
+ end
data/lib/bummr.rb ADDED
@@ -0,0 +1,5 @@
1
+ require "bummr/version"
2
+
3
+ module Bummr
4
+ # Your code goes here...
5
+ end
metadata ADDED
@@ -0,0 +1,140 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: bummr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Lee Pender
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-05-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: thor
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: colorize
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.7'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.7'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '10.0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '10.0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pry
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: See Readme
98
+ email:
99
+ - lpender@gmail.com
100
+ executables:
101
+ - bummr
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - ".ruby-version"
107
+ - Gemfile
108
+ - LICENSE.txt
109
+ - README.md
110
+ - Rakefile
111
+ - bin/bummr
112
+ - bummr.gemspec
113
+ - lib/bummr.rb
114
+ - lib/bummr/cli.rb
115
+ - lib/bummr/version.rb
116
+ homepage: ''
117
+ licenses:
118
+ - MIT
119
+ metadata: {}
120
+ post_install_message:
121
+ rdoc_options: []
122
+ require_paths:
123
+ - lib
124
+ required_ruby_version: !ruby/object:Gem::Requirement
125
+ requirements:
126
+ - - ">="
127
+ - !ruby/object:Gem::Version
128
+ version: '0'
129
+ required_rubygems_version: !ruby/object:Gem::Requirement
130
+ requirements:
131
+ - - ">="
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ requirements: []
135
+ rubyforge_project:
136
+ rubygems_version: 2.4.5
137
+ signing_key:
138
+ specification_version: 4
139
+ summary: Helper script to intelligently update your Gemfile
140
+ test_files: []