Skip to content

Commit

Permalink
Merge pull request #109 from jamesiarmes/build-mechanism-improvements
Browse files Browse the repository at this point in the history
Build mechanism improvements
  • Loading branch information
askreet committed Jul 8, 2016
2 parents 018e5b6 + d1cf2fb commit 3a54e86
Show file tree
Hide file tree
Showing 4 changed files with 172 additions and 4 deletions.
45 changes: 45 additions & 0 deletions lib/moonshot/build_mechanism/github_release.rb
Original file line number Diff line number Diff line change
Expand Up @@ -76,10 +76,40 @@ def confirm_or_fail(version)
end

def git_tag(tag, sha, annotation)
return if git_tag_exists(tag, sha)

cmd = "git tag -a #{tag} #{sha} --file=-"
sh_step(cmd, stdin: annotation)
end

# Determines if a valid git tag already exists.
#
# @param tag [String] Tag to check existence for.
# @param sha [String] SHA to verify the tag against.
#
# @return [Boolean] Whether or not the tag exists.
#
# @raise [RuntimeError] if the SHAs do not match.
def git_tag_exists(tag, sha)
exists = false
sh_step("git tag -l #{tag}") do |_, output|
exists = (output.strip == tag)
end

# If the tag does exist, make sure the existing SHA matches the SHA we're
# trying to build from.
if exists
sh_step("git rev-list -n 1 #{tag}") do |_, output|
raise "#{tag} already exists at a different SHA" \
if output.strip != sha
end

log.info("tag #{tag} already exists")
end

exists
end

def git_push_tag(remote, tag)
cmd = "git push #{remote} refs/tags/#{tag}:refs/tags/#{tag}"
sh_step(cmd) do
Expand All @@ -88,13 +118,28 @@ def git_push_tag(remote, tag)
end

def hub_create_release(semver, commitish, changelog_entry)
return if hub_release_exists(semver, commitish)

message = "#{semver}\n\n#{changelog_entry}"
cmd = "hub release create #{semver} --commitish=#{commitish}"
cmd << ' --prerelease' if semver.pre || semver.build
cmd << " --message=#{Shellwords.escape(message)}"
sh_step(cmd)
end

# Determines if a github release already exists.
#
# @param semver [String] Semantic version string for the release.
#
# @return [Boolean]
def hub_release_exists(semver)
sh_step("hub release show #{semver}")
log.info("release #{semver} already exists")
true
rescue RuntimeError
false
end

def validate_commit
cmd = "git show --stat #{@sha}"
sh_step(cmd, msg: "Validate commit #{@sha}.") do |_, out|
Expand Down
41 changes: 38 additions & 3 deletions lib/moonshot/build_mechanism/travis_deploy.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ class TravisDeploy
include Moonshot::DoctorHelper
include Moonshot::Shell

MAX_BUILD_FIND_ATTEMPTS = 10

attr_reader :output_file

def initialize(slug, pro: false)
Expand All @@ -33,13 +35,46 @@ def post_build_hook(_)
def find_build_and_job(version)
job_number = nil
ilog.start_threaded('Find Travis CI build') do |step|
sleep 2
build_out = sh_out("bundle exec travis show #{@cli_args} #{version}")
job_number = wait_for_build(version)

step.success("Travis CI ##{job_number.gsub(/\..*/, '')} running.")
end
job_number
end

# Looks for the travis build and attempts to retry if the build does not
# exist yet.
#
# @param verison [String] Build version to look for.
#
# @return [String] Job number for the travis build.
def wait_for_build(version)
job_number = nil
attempts = 0
loop do
# Give travis some time to start the build.
attempts += 1
sleep 10

# Attempt to find the build. Rescue and re-attempt if the build can not
# be found on travis yet.
begin
build_out = sh_out("bundle exec travis show #{@cli_args} #{version}")
rescue RuntimeError => e
next unless attempts >= MAX_BUILD_FIND_ATTEMPTS
raise e
end

unless (job_number = build_out.match(/^#(\d+\.\d+) .+BUILD=1.+/)[1])
next unless attempts >= MAX_BUILD_FIND_ATTEMPTS
raise "Build for #{version} not found.\n#{build_out}"
end
step.success("Travis CI ##{job_number.gsub(/\..*/, '')} running.")

# If we've reached this point then everything went smoothly and we can
# exit the loop.
break
end

job_number
end

Expand Down
50 changes: 49 additions & 1 deletion spec/moonshot/build_mechanism/github_release_spec.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
module Moonshot
module Moonshot # rubocop:disable ModuleLength
describe BuildMechanism::GithubRelease do
let(:tag) { '0.0.0-rspec' }
let(:build_mechanism) do
instance_double(BuildMechanism::Script).as_null_object
end
Expand Down Expand Up @@ -72,5 +73,52 @@ module Moonshot
end
end
end

describe '#git_tag_exists' do
let(:sha) { '1397919abb5b7c0908ab42eaac501d68a0ccb6db' }

it 'passes if the tag exists at the same sha' do
expect(subject).to receive(:sh_step).with("git tag -l #{tag}")
.and_yield(nil, tag)
expect(subject).to receive(:sh_step).with("git rev-list -n 1 #{tag}")
.and_yield(nil, sha)

expect(subject.send(:git_tag_exists, tag, sha)).to eq(true)
end

it 'fails if the tag does not exist' do
expect(subject).to receive(:sh_step).with("git tag -l #{tag}")
.and_yield(nil, '')
expect(subject).to_not receive(:sh_step)
.with("git rev-list -n 1 #{tag}")

expect(subject.send(:git_tag_exists, tag, sha)).to eq(false)
end

it 'errors if the tag exists at a different sha' do
expect(subject).to receive(:sh_step).with("git tag -l #{tag}")
.and_yield(nil, tag)
expect(subject).to receive(:sh_step).with("git rev-list -n 1 #{tag}")
.and_yield(nil, '72774c1855c044e917f322e9536a4e3f62697267')

expect { subject.send(:git_tag_exists, tag, sha) }.to \
raise_error(RuntimeError)
end
end

describe '#hub_release_exists' do
it 'passes if the github release exists' do
expect(subject).to receive(:sh_step).with("hub release show #{tag}")

expect(subject.send(:hub_release_exists, tag)).to eq(true)
end

it 'fails if the github release does not exist' do
expect(subject).to receive(:sh_step).with("hub release show #{tag}")
.and_raise

expect(subject.send(:hub_release_exists, tag)).to eq(false)
end
end
end
end
40 changes: 40 additions & 0 deletions spec/moonshot/build_mechanism/travis_deploy_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,5 +45,45 @@ module Moonshot
end
end
end

describe '#wait_for_build' do
let(:tag) { '0.0.0-rspec' }
let(:job_number) { '1401.3' }
let(:output) do
"Build #1401: Merge pull request #245 from respectest/updChange\n" \
"State: passed\nType: push\n" \
"Branch: 0.0.0-rspec\n" \
"Compare URL: https://github.com/acquia/moonshot/compare/0.0.0-rspec\n" \
"Duration: 5 min 50 sec\nStarted: 2016-06-30 16:05:34\n" \
"Finished: 2016-06-30 16:06:48\n\n" \
"#1401.1 passed: 1 min 13 sec rvm: 2.1.7, os: linux\n" \
"#1401.2 passed: 1 min 14 sec rvm: 2.2.3, os: linux\n" \
'#1401.3 passed: 3 min 23 sec rvm: 2.2.3, env: BUILD=1, ' \
'gemfile: .travis.build.Gemfile, os: linux '
end

it 'should only make one attempt if the job is found' do
expect(subject).to receive(:sleep).once
expect(subject).to receive(:sh_out).and_return(output)

expect(subject.send(:wait_for_build, tag)).to eq(job_number)
end

it 'should only make the max number of attempts before failing' do
expect(subject).to receive(:sleep).exactly(10).times
expect(subject).to receive(:sh_out).and_raise.exactly(10).times

expect { subject.send(:wait_for_build, tag) }.to \
raise_error(RuntimeError)
end

it 'should make attempts until the build is found' do
expect(subject).to receive(:sleep).exactly(3).times
expect(subject).to receive(:sh_out).and_raise.twice
expect(subject).to receive(:sh_out).and_return(output)

expect(subject.send(:wait_for_build, tag)).to eq(job_number)
end
end
end
end

0 comments on commit 3a54e86

Please sign in to comment.