diff --git a/.gitignore b/.gitignore index 8fd4d35..18700ab 100644 --- a/.gitignore +++ b/.gitignore @@ -2,6 +2,7 @@ /.yardoc /_yardoc/ /coverage/ +/log/ /doc/ /pkg/ /spec/reports/ @@ -10,4 +11,7 @@ *.so *.o *.a +*.swp mkmf.log +bummr-*.gem +.DS_Store diff --git a/Gemfile.lock b/Gemfile.lock index 60eea95..79d897c 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1,7 +1,7 @@ PATH remote: . specs: - bummr (1.1.0) + bummr (1.1.1a) rainbow thor diff --git a/README.md b/README.md index f2eb973..362e00d 100644 --- a/README.md +++ b/README.md @@ -99,6 +99,12 @@ Update gemname from 0.0.1 to 0.0.2 - Once the build passes, you can push your branch and create a pull-request! - You may wish to `tail -f log/bummr.log` in a separate terminal window so you can see which commits are being removed. +- Environment variables that adjust bummr behavior + - BUMMR_TEST = your app's testing suite command (default: `bundle exec rake`) + - BASE_BRANCH = your repo's primary branch (default: `main`) + - BUMMR_HEADLESS = skip interactive rebase after all updates are complete (default: `false`) + - BUMMR_GIT_COMMIT = the shell git commit command to be used (default: `git commit`) + ## License diff --git a/bummr.gemspec b/bummr.gemspec index 6a4f685..08e4a30 100644 --- a/bummr.gemspec +++ b/bummr.gemspec @@ -13,12 +13,14 @@ Gem::Specification.new do |spec| spec.homepage = "https://github.com/lpender/bummr" spec.license = "MIT" - spec.files = `git ls-files -z`.split("\x0") + spec.files = Dir["{lib,bin}/**/*"] + %w|LICENSE README.md| spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) } spec.test_files = spec.files.grep(%r{^(test|spec|features)/}) spec.require_paths = ["lib"] + # Toolkit for building powerful command-line interfaces spec.add_dependency "thor" + # Colorize printed text on ANSI terminals spec.add_dependency "rainbow" spec.add_development_dependency "rspec" diff --git a/lib/bummr/bisecter.rb b/lib/bummr/bisecter.rb index 394ce8f..af8f129 100644 --- a/lib/bummr/bisecter.rb +++ b/lib/bummr/bisecter.rb @@ -20,7 +20,7 @@ def bisect end if line == "bisect run success\n" - Bummr::Remover.instance.remove_commit(sha) + puts Bummr::Remover.instance.remove_commit(sha) end end end diff --git a/lib/bummr/check.rb b/lib/bummr/check.rb index 74ce1f7..c37030d 100644 --- a/lib/bummr/check.rb +++ b/lib/bummr/check.rb @@ -27,7 +27,7 @@ def check(fullcheck=true) private def check_base_branch - if `git rev-parse --abbrev-ref HEAD` == "#{BASE_BRANCH}\n" + if %x{git rev-parse --abbrev-ref HEAD} == "#{BASE_BRANCH}\n" message = "Bummr is not meant to be run on your base branch" puts message.color(:red) puts "Please checkout a branch with 'git checkout -b update-gems'" @@ -44,7 +44,7 @@ def check_log end def check_status - status = `git status` + status = %x{git status} if status.index 'are currently' message = "" @@ -55,15 +55,15 @@ def check_status message += "You are already bisecting. " end - message += "Make sure `git status` is clean" + message += "Make sure 'git status' is clean" puts message.color(:red) @errors.push message end end def check_diff - unless `git diff #{BASE_BRANCH}`.empty? - message = "Please make sure that `git diff #{BASE_BRANCH}` returns empty" + unless %x{git diff #{BASE_BRANCH}}.empty? + message = "Please make sure that 'git diff #{BASE_BRANCH}' returns empty" puts message.color(:red) @errors.push message end diff --git a/lib/bummr/cli.rb b/lib/bummr/cli.rb index f4a564d..a444fc2 100644 --- a/lib/bummr/cli.rb +++ b/lib/bummr/cli.rb @@ -8,10 +8,12 @@ class CLI < Thor include Bummr::Prompt include Bummr::Scm + # :nocov: internals are tested by spec/check_spec.rb desc "check", "Run automated checks to see if bummr can be run" def check(fullcheck=true) Bummr::Check.instance.check(fullcheck) end + # :nocov: end desc "update", "Update outdated gems, run tests, bisect if tests fail\n\n" + @@ -77,13 +79,16 @@ def bisect end end + # :nocov: internals are tested by spec/lib/remover_spec.rb desc "remove_commit", "Remove a commit from the history" def remove_commit(sha) - Bummr::Remover.instance.remove_commit(sha) + puts Bummr::Remover.instance.remove_commit(sha) end + # :nocov: end private + # :nocov: This is stubbed out during actual testing because its boilerplate information for the user def display_info puts "Bummr #{VERSION}" puts "To run Bummr, you must:" @@ -92,7 +97,7 @@ def display_info puts "- Have a 'log' directory, where we can place logs" puts "- Have your build configured to fail fast (recommended)" puts "- Have locked any Gem version that you don't wish to update in your Gemfile" - puts "- It is recommended that you lock your versions of `ruby` and `rails` in your `Gemfile`" + puts "- It is recommended that you lock your versions of 'ruby' and 'rails' in your 'Gemfile'" puts "\n" puts "Your test command is: " + "'#{TEST_COMMAND}'".color(:yellow) puts "\n" @@ -106,7 +111,8 @@ def print_received_options puts "--#{key.color(:yellow)}: #{value}" end - puts "\nRun `#{"bummr help update".color(:yellow)}` for more information.\n\n" + puts "\nRun '#{"bummr help update".color(:yellow)}' for more information.\n\n" end + # :nocov: end end end diff --git a/lib/bummr/git.rb b/lib/bummr/git.rb index de4a63b..6a832e8 100644 --- a/lib/bummr/git.rb +++ b/lib/bummr/git.rb @@ -20,8 +20,9 @@ def rebase_interactive(sha) system("git rebase -i #{BASE_BRANCH}") unless HEADLESS end + # print only the commit subject line def message(sha) - `git log --pretty=format:'%s' -n 1 #{sha}` + %x{git log --pretty=format:'%s' -n 1 #{sha}} end private diff --git a/lib/bummr/outdated.rb b/lib/bummr/outdated.rb index 11e02ba..46d14e1 100644 --- a/lib/bummr/outdated.rb +++ b/lib/bummr/outdated.rb @@ -17,7 +17,7 @@ def outdated_gems(options = {}) Open3.popen2("bundle outdated" + bundle_options) do |_std_in, std_out| while line = std_out.gets - puts line + puts line # TODO: remove this if possible (pointless for spec tests) gem = parse_gem_from(line) if gem && (options[:all_gems] || gemfile_contains(gem[:name])) @@ -43,8 +43,11 @@ def gemfile_contains(gem_name) /gem ['"]#{gem_name}['"]/.match gemfile end + # :nocov: no need to test whether linux "cat Gemfile" works def gemfile - @gemfile ||= `cat Gemfile` + @gemfile ||= %x{cat Gemfile} end + # :nocov: end + end end diff --git a/lib/bummr/remover.rb b/lib/bummr/remover.rb index d561c4b..7a2d0cb 100644 --- a/lib/bummr/remover.rb +++ b/lib/bummr/remover.rb @@ -10,17 +10,17 @@ def remove_commit(sha) log "Resetting..." system("git bisect reset") - message = "\nThe commit:\n\n `#{sha} #{git.message(sha)}`\n\n" + + message = "\nThe commit:\n\n '#{sha} #{git.message(sha)}'\n\n" + "Is breaking the build.\n\n" + "Please do one of the following: \n\n" + " 1. Update your code to work with the latest version of this gem.\n\n" + " 2. Perform the following steps to lock the gem version:\n\n" + - " - `git reset --hard main`\n" + + " - 'git reset --hard main'\n" + " - Lock the version of this Gem in your Gemfile.\n" + " - Commit the changes.\n" + - " - Run `bummr update` again.\n\n" + " - Run 'bummr update' again.\n\n" - puts message.color(:yellow) + message.color(:yellow) end end end diff --git a/lib/bummr/updater.rb b/lib/bummr/updater.rb index 82bca13..827f854 100644 --- a/lib/bummr/updater.rb +++ b/lib/bummr/updater.rb @@ -43,7 +43,7 @@ def update_gem(gem, index) end def updated_version_for(gem) - string = `bundle list --paths | grep "#{gem[:name]}"` + string = %x{bundle list --paths | grep "#{gem[:name]}"} string.match(/#{File::SEPARATOR}#{gem[:name]}-(.*)$/)[1] end end diff --git a/lib/bummr/version.rb b/lib/bummr/version.rb index 8c79693..20eccd7 100644 --- a/lib/bummr/version.rb +++ b/lib/bummr/version.rb @@ -1,3 +1,3 @@ module Bummr - VERSION = "1.1.0" + VERSION = "1.1.1a" end diff --git a/spec/black_box/bummr_update_spec.rb b/spec/black_box/bummr_update_spec.rb index 674c4ca..d18b161 100644 --- a/spec/black_box/bummr_update_spec.rb +++ b/spec/black_box/bummr_update_spec.rb @@ -2,6 +2,10 @@ require "jet_black" describe "bummr update command" do + before(:all) do + puts "\n<< black_box/bummr_update_spec >>\n" + end + let(:session) { JetBlack::Session.new(options: { clean_bundler_env: true }) } let(:bummr_gem_path) { File.expand_path("../../", __dir__) } diff --git a/spec/check_spec.rb b/spec/check_spec.rb index 2706f4f..4b209cc 100644 --- a/spec/check_spec.rb +++ b/spec/check_spec.rb @@ -1,6 +1,10 @@ require 'spec_helper' describe Bummr::Check do + before(:all) do + puts "\n<< Bummr::Check >>\n" + end + let(:check) { Bummr::Check.instance } before(:each) do @@ -81,7 +85,7 @@ check.check expect(check).to have_received(:puts) - .with("You are already bisecting. Make sure `git status` is clean".color(:red)) + .with("You are already bisecting. Make sure 'git status' is clean".color(:red)) expect(check).to have_received(:yes?) expect(check).to have_received(:exit).with(0) end @@ -98,7 +102,7 @@ check.check expect(check).to have_received(:puts) - .with("You are already rebasing. Make sure `git status` is clean".color(:red)) + .with("You are already rebasing. Make sure 'git status' is clean".color(:red)) expect(check).to have_received(:yes?) expect(check).to have_received(:exit).with(0) end @@ -116,7 +120,7 @@ check.check(true) expect(check).to have_received(:puts) - .with("Please make sure that `git diff main` returns empty".color(:red)) + .with("Please make sure that 'git diff main' returns empty".color(:red)) expect(check).to have_received(:yes?) expect(check).to have_received(:exit).with(0) end diff --git a/spec/lib/bisecter_spec.rb b/spec/lib/bisecter_spec.rb index 2cdcb5d..7289631 100644 --- a/spec/lib/bisecter_spec.rb +++ b/spec/lib/bisecter_spec.rb @@ -1,6 +1,10 @@ require 'spec_helper' describe Bummr::Bisecter do + before(:all) do + puts "\n<< Bummr::Bisecter >>\n" + end + let(:std_out_err_bad_commit) { output = String.new output += "mybadcommit is the first bad commit\n" diff --git a/spec/lib/cli_spec.rb b/spec/lib/cli_spec.rb index 2944564..497cb13 100644 --- a/spec/lib/cli_spec.rb +++ b/spec/lib/cli_spec.rb @@ -1,6 +1,10 @@ require 'spec_helper' describe Bummr::CLI do + before(:all) do + puts "\n<< Bummr::CLI >>\n" + end + # https://github.com/wireframe/gitx/blob/171da367072b0e82d5906d1e5b3f8ff38e5774e7/spec/thegarage/gitx/cli/release_command_spec.rb#L9 let(:args) { [] } let(:options) { {} } @@ -18,6 +22,7 @@ describe "#update" do context "when user rejects moving forward" do it "does not attempt to move forward" do + expect(cli).to receive(:display_info) # NOOP this function call expect(cli).to receive(:yes?).and_return(false) expect(cli).not_to receive(:check) diff --git a/spec/lib/git_spec.rb b/spec/lib/git_spec.rb index 321c8d1..a6b795d 100644 --- a/spec/lib/git_spec.rb +++ b/spec/lib/git_spec.rb @@ -1,6 +1,10 @@ require "spec_helper" describe Bummr::Git do + before(:all) do + puts "\n<< Bummr::Git >>\n" + end + describe "#add" do it "stages specified files with git" do git = stub_git diff --git a/spec/lib/log_spec.rb b/spec/lib/log_spec.rb index 2087dd8..7177421 100644 --- a/spec/lib/log_spec.rb +++ b/spec/lib/log_spec.rb @@ -1,16 +1,20 @@ require "spec_helper" describe Bummr::Log do + before(:all) do + puts "\n<< Bummr::Log >>\n" + end + let(:object) { Object.new } let(:message) { "test message" } before do - `mkdir -p log` + %x{mkdir -p log} object.extend(Bummr::Log) end after do - `rm log/bummr.log` + %x{rm log/bummr.log} end describe "#log" do @@ -23,9 +27,11 @@ end it "outputs the message to log/bummr.log" do + allow(object).to receive(:puts) # NOOP this function call + object.log message - result = `cat log/bummr.log` + result = %x{cat log/bummr.log} expect(result).to eq message + "\n" end diff --git a/spec/lib/outdated_spec.rb b/spec/lib/outdated_spec.rb index c25abf8..bc6673b 100644 --- a/spec/lib/outdated_spec.rb +++ b/spec/lib/outdated_spec.rb @@ -1,6 +1,10 @@ require 'spec_helper' describe Bummr::Outdated do + before(:all) do + puts "\n<< Bummr::Outdated >>\n" + end + # https://github.com/wireframe/gitx/blob/8e3cdc8b5d0c2082ed3daaf2fc054654b2e7a6c8/spec/gitx/executor_spec.rb#L9 let(:stdoutput_legacy) { output = String.new @@ -27,10 +31,15 @@ } describe "#outdated_gems" do + def mock_gemfile + allow_any_instance_of(described_class).to receive(:gemfile).and_return gemfile + allow_any_instance_of(described_class).to receive(:puts) # NOOP this function call + end + { bundler2: :stdoutput, bundler1: :stdoutput_legacy }.each_pair do |version, output| - it "Correctly identifies outdated gems with bundler #{version}" do - allow(Open3).to receive(:popen2).and_yield(nil, public_send(output)) - allow_any_instance_of(described_class).to receive(:gemfile).and_return gemfile + it "Correctly identifies outdated gems with bundler #{version}" do + allow(Open3).to receive(:popen2).and_yield(nil, public_send(output)) + mock_gemfile instance = Bummr::Outdated.instance result = instance.outdated_gems @@ -57,7 +66,7 @@ it "lists all outdated dependencies by omitting the strict option" do allow(Open3).to receive(:popen2).with("bundle outdated --parseable").and_yield(nil, stdoutput) - allow(Bummr::Outdated.instance).to receive(:gemfile).and_return gemfile + mock_gemfile results = Bummr::Outdated.instance.outdated_gems(all_gems: true) gem_names = results.map { |result| result[:name] } @@ -68,7 +77,7 @@ it "defaults to false" do expect(Open3).to receive(:popen2).with("bundle outdated --parseable --strict").and_yield(nil, stdoutput) - allow(Bummr::Outdated.instance).to receive(:gemfile).and_return gemfile + mock_gemfile results = Bummr::Outdated.instance.outdated_gems gem_names = results.map { |result| result[:name] } @@ -89,7 +98,7 @@ .with("bundle outdated --parseable --strict --group development") .and_yield(nil, stdoutput_from_development_group) - allow(Bummr::Outdated.instance).to receive(:gemfile).and_return gemfile + mock_gemfile results = Bummr::Outdated.instance.outdated_gems(group: :development) gem_names = results.map { |result| result[:name] } @@ -102,7 +111,7 @@ .with("bundle outdated --parseable --strict") .and_yield(nil, stdoutput) - allow(Bummr::Outdated.instance).to receive(:gemfile).and_return gemfile + mock_gemfile results = Bummr::Outdated.instance.outdated_gems gem_names = results.map { |result| result[:name] } @@ -123,7 +132,7 @@ .with("bundle outdated --parseable --strict spring") .and_yield(nil, stdoutput_from_spring_gem) - allow(Bummr::Outdated.instance).to receive(:gemfile).and_return gemfile + mock_gemfile results = Bummr::Outdated.instance.outdated_gems(gem: :spring) gem_names = results.map { |result| result[:name] } @@ -131,7 +140,7 @@ expect(gem_names).to match_array ['spring'] end end - end + end # end #outdated_gems describe "#parse_gem_from" do it 'line' do diff --git a/spec/lib/prompt_spec.rb b/spec/lib/prompt_spec.rb index f3fcaf7..6cca1e6 100644 --- a/spec/lib/prompt_spec.rb +++ b/spec/lib/prompt_spec.rb @@ -1,6 +1,10 @@ require "spec_helper" describe Bummr::Prompt do + before(:all) do + puts "\n<< Bummr::Prompt >>\n" + end + let(:parent_class) do Class.new do def yes?(message) diff --git a/spec/lib/remover_spec.rb b/spec/lib/remover_spec.rb index 9209863..443fb34 100644 --- a/spec/lib/remover_spec.rb +++ b/spec/lib/remover_spec.rb @@ -1,9 +1,13 @@ require "spec_helper" describe Bummr::Remover do + before(:all) do + puts "\n<< Bummr::Remover >>\n" + end + let(:remover) { Bummr::Remover.instance } let(:git) { Bummr::Git.instance } - let(:sha) { "testsha" } + let(:sha) { "HEAD~1" } before do allow(remover).to receive(:log) diff --git a/spec/lib/updater_spec.rb b/spec/lib/updater_spec.rb index 583521f..5f0dbbe 100644 --- a/spec/lib/updater_spec.rb +++ b/spec/lib/updater_spec.rb @@ -1,6 +1,10 @@ require "spec_helper" describe Bummr::Updater do + before(:all) do + puts "\n<< Bummr::Updater >>\n" + end + let(:outdated_gems) { [ { name: "myGem", installed: "0.3.2", newest: "0.3.5" }, @@ -19,6 +23,7 @@ describe "#update_gems" do it "calls update_gem on each gem" do allow(updater).to receive(:update_gem) + allow(updater).to receive(:puts) # NOOP this function call updater.update_gems @@ -29,11 +34,24 @@ end describe "#update_gem" do + # Ensure this directory exists to be added + before do + %x{mkdir -p vendor/cache} + end + after do + %x{rm -rf vendor/cache} + end + + def mock_log_commit_puts + allow(updater).to receive(:log) + allow(updater).to receive(:puts) # NOOP this function call + allow(git).to receive(:commit) + end + it "attempts to update the gem" do allow(updater).to receive(:system).with(update_cmd) allow(updater).to receive(:updated_version_for).with(gem).and_return installed - allow(updater).to receive(:log) - allow(git).to receive(:commit) + mock_log_commit_puts updater.update_gem(gem, 0) end @@ -42,8 +60,7 @@ it "logs that it's not updated to the latest" do allow(updater).to receive(:system).with(update_cmd) allow(updater).to receive(:updated_version_for).with(gem).and_return installed - allow(updater).to receive(:log) - allow(git).to receive(:commit) + mock_log_commit_puts updater.update_gem(gem, 0) @@ -53,8 +70,7 @@ it "doesn't commit anything" do allow(updater).to receive(:system).with(update_cmd) allow(updater).to receive(:updated_version_for).with(gem).and_return installed - allow(updater).to receive(:log) - allow(git).to receive(:commit) + mock_log_commit_puts updater.update_gem(gem, 0) @@ -73,8 +89,7 @@ not_latest_message = "#{gem[:name]} not updated from #{gem[:installed]} to latest: #{gem[:newest]}" allow(updater).to receive(:system) - allow(updater).to receive(:log) - allow(git).to receive(:commit) + mock_log_commit_puts updater.update_gem(gem, 0) @@ -84,10 +99,10 @@ it "commits" do commit_message = "Update #{gem[:name]} from #{gem[:installed]} to #{intermediate_version}" + allow(updater).to receive(:system) - allow(updater).to receive(:log) allow(git).to receive(:add) - allow(git).to receive(:commit) + mock_log_commit_puts updater.update_gem(gem, 0) @@ -106,10 +121,10 @@ it "commits" do commit_message = "Update #{gem[:name]} from #{gem[:installed]} to #{gem[:newest]}" + allow(updater).to receive(:system) - allow(updater).to receive(:log) allow(git).to receive(:add) - allow(git).to receive(:commit) + mock_log_commit_puts updater.update_gem(gem, 0) @@ -119,7 +134,7 @@ expect(git).to have_received(:commit).with(commit_message) end end - end + end # end #update_gem describe "#updated_version_for" do it "returns the correct version from bundle list" do diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 4035681..2f4c177 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,5 +1,11 @@ require "simplecov" -SimpleCov.start +SimpleCov.start do + # Exclude spec files from coverage + add_filter '/spec/' + + git_branch_name = %x{git rev-parse --abbrev-ref HEAD}.strip + SimpleCov.coverage_dir("coverage/#{git_branch_name}") +end require 'pry' require 'bummr'