heroku_hatchet 7.0.0 → 7.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 89dec86ebf0199547ebf527242257a88b26c2741b272aa73945b4c907b72f51a
4
- data.tar.gz: fe0bd8c520fc7102e13ad6f91da96b837158f0ba8eaa324c846e3acc92cb233f
3
+ metadata.gz: f8c7a94962a255edf58024ed43c7102fc7eb97e07a3d1127ccec6f1cb16c560b
4
+ data.tar.gz: 36c1999581499ba71e09c93376281bb57105be30d7c42637b1e38a29decdd602
5
5
  SHA512:
6
- metadata.gz: bad4717807a5cddb7b0cdd2750bdd1811b8b012e767d92173f364795eb1da3a8af41fddb28269d14c67ad8d2cfe7e7d4c7f9cefbbafd575172408787cca41142
7
- data.tar.gz: b2f7905e07091c4b66ad7b6ba4ac00b8e304e32f10c01a259723cb5e12e592160f9ca30cb66f5485c3bc59dffa26d99bbba070f73be161022d85e63c6afd4409
6
+ metadata.gz: bbc833ba77cc7ce963795cc90ec282489b35a235e5c161e85704b15d2cd430a1a426906d26bdee3f00045a637b56eb31b11778beb220b459c7e79d2d87f1306a
7
+ data.tar.gz: a7c48cc4ce7103313cdfa8dcd5a27d519ade4fa02d328b837f1cd6c0d4f02af377ec2df764235af0d66316b535ea145716ff0974c797ee32b243ad415472db86
@@ -1,5 +1,13 @@
1
1
  ## HEAD
2
2
 
3
+ ## 7.1.0
4
+
5
+ - Initializing an `App` can now take a `retries` key to overload the global hatchet env var (https://github.com/heroku/hatchet/pull/119)
6
+ - Calling `App#commit!` now adds an empty commit if there is no changes on disk (https://github.com/heroku/hatchet/pull/119)
7
+ - Bugfix: Failed release phase in deploys can now be re-run (https://github.com/heroku/hatchet/pull/119)
8
+ - Bugfix: Allow `hatchet lock` to be run against new projects (https://github.com/heroku/hatchet/pull/118)
9
+ - Bugfix: Allow `hatchet.lock` file to lock a repo to a different branch than what is specified as default for GitHub (https://github.com/heroku/hatchet/pull/118)
10
+
3
11
  ## 7.0.0
4
12
 
5
13
  - ActiveSupport's Object#blank? and Object#present? are no longer provided by default (https://github.com/heroku/hatchet/pull/107)
data/README.md CHANGED
@@ -531,6 +531,8 @@ WARNING: Enabling `run_multi` setting on an app will charge your Heroku account
531
531
  WARNING: Do not use `run_multi` if you're not using the `deploy` block syntax or manually call `teardown!` inside the text context [more info about how behavior does not work with the `after` block syntax in rspec](https://github.com/heroku/hatchet/issues/110).
532
532
  WARNING: To work, `run_multi` requires your application to have a `web` process associated with it.
533
533
 
534
+ - `retries` (Integer): When passed in, this value will be used insead of the global `HATCHET_RETRIES` set via environment variable. When `allow_failures: true` is set as well as a retries value, then the application will not retry pushing to Heroku.
535
+
534
536
  ### App methods:
535
537
 
536
538
  - `app.set_config()`: Updates the configuration on your app taking in a hash
@@ -67,7 +67,7 @@ class HatchetCLI < Thor
67
67
  desc "locks to specific git commits", "updates hatchet.lock"
68
68
  def lock
69
69
  lock_hash = {}
70
- lockfile_hash = load_lockfile
70
+ lockfile_hash = load_lockfile(create_if_does_not_exist: true)
71
71
  dirs.map do |directory, git_repo|
72
72
  Threaded.later do
73
73
  puts "== locking #{directory}"
@@ -118,10 +118,15 @@ class HatchetCLI < Thor
118
118
  end
119
119
 
120
120
  private
121
- def load_lockfile
121
+ def load_lockfile(create_if_does_not_exist: false)
122
122
  return YAML.safe_load(File.read('hatchet.lock')).to_h
123
123
  rescue Errno::ENOENT
124
- raise "No such file found `hatchet.lock` please run `$ bundle exec hatchet lock`"
124
+ if create_if_does_not_exist
125
+ FileUtils.touch('hatchet.lock')
126
+ {}
127
+ else
128
+ raise "No such file found `hatchet.lock` please run `$ bundle exec hatchet lock`"
129
+ end
125
130
  end
126
131
 
127
132
  def bad_repo?(url)
@@ -151,7 +156,7 @@ class HatchetCLI < Thor
151
156
  end
152
157
 
153
158
  def checkout_commit(directory, commit)
154
- cmd("cd #{directory} && git reset --hard #{commit}")
159
+ cmd("cd #{directory} && git fetch origin #{commit} && git checkout #{commit} && git checkout - && git reset --hard #{commit}")
155
160
  end
156
161
 
157
162
  def commit_at_directory(directory)
@@ -9,7 +9,7 @@ module Hatchet
9
9
  HATCHET_BUILDPACK_BRANCH = -> { ENV['HATCHET_BUILDPACK_BRANCH'] || ENV['HEROKU_TEST_RUN_BRANCH'] || Hatchet.git_branch }
10
10
  BUILDPACK_URL = "https://github.com/heroku/heroku-buildpack-ruby.git"
11
11
 
12
- attr_reader :name, :stack, :directory, :repo_name, :app_config, :buildpacks, :reaper
12
+ attr_reader :name, :stack, :directory, :repo_name, :app_config, :buildpacks, :reaper, :max_retries_count
13
13
 
14
14
  class FailedDeploy < StandardError; end
15
15
 
@@ -55,6 +55,7 @@ module Hatchet
55
55
  buildpack_url: nil,
56
56
  before_deploy: nil,
57
57
  run_multi: ENV["HATCHET_RUN_MULTI"],
58
+ retries: RETRIES,
58
59
  config: {}
59
60
  )
60
61
  @repo_name = repo_name
@@ -68,6 +69,7 @@ module Hatchet
68
69
  @buildpacks = Array(@buildpacks)
69
70
  @buildpacks.map! {|b| b == :default ? self.class.default_buildpack : b}
70
71
  @run_multi = run_multi
72
+ @max_retries_count = retries
71
73
 
72
74
  if run_multi && !ENV["HATCHET_EXPENSIVE_MODE"]
73
75
  raise "You're attempting to enable `run_multi: true` mode, but have not enabled `HATCHET_EXPENSIVE_MODE=1` env var to verify you understand the risks"
@@ -129,7 +131,7 @@ module Hatchet
129
131
  end
130
132
 
131
133
  def add_database(plan_name = 'heroku-postgresql:dev', match_val = "HEROKU_POSTGRESQL_[A-Z]+_URL")
132
- Hatchet::RETRIES.times.retry do
134
+ max_retries_count.times.retry do
133
135
  # heroku.post_addon(name, plan_name)
134
136
  api_rate_limit.call.addon.create(name, plan: plan_name )
135
137
  _, value = get_config.detect {|k, v| k.match(/#{match_val}/) }
@@ -316,7 +318,7 @@ module Hatchet
316
318
  end
317
319
 
318
320
  def commit!
319
- local_cmd_exec!('git add .; git commit -m next')
321
+ local_cmd_exec!('git add .; git commit --allow-empty -m next')
320
322
  end
321
323
 
322
324
  def push_without_retry!
@@ -386,12 +388,12 @@ module Hatchet
386
388
  end
387
389
 
388
390
  def push
389
- max_retries = @allow_failure ? 1 : RETRIES
390
- max_retries.times.retry do |attempt|
391
+ retry_count = allow_failure? ? 1 : max_retries_count
392
+ retry_count.times.retry do |attempt|
391
393
  begin
392
394
  @output = self.push_without_retry!
393
395
  rescue StandardError => error
394
- puts retry_error_message(error, attempt, max_retries)
396
+ puts retry_error_message(error, attempt) unless retry_count == 1
395
397
  raise error
396
398
  end
397
399
  end
@@ -400,10 +402,10 @@ module Hatchet
400
402
  alias :push_with_retry :push
401
403
  alias :push_with_retry! :push_with_retry
402
404
 
403
- def retry_error_message(error, attempt, max_retries)
405
+ def retry_error_message(error, attempt)
404
406
  attempt += 1
405
- return "" if attempt == max_retries
406
- msg = "\nRetrying failed Attempt ##{attempt}/#{max_retries} to push for '#{name}' due to error: \n"<<
407
+ return "" if attempt == max_retries_count
408
+ msg = "\nRetrying failed Attempt ##{attempt}/#{max_retries_count} to push for '#{name}' due to error: \n"<<
407
409
  "#{error.class} #{error.message}\n #{error.backtrace.join("\n ")}"
408
410
  return msg
409
411
  end
@@ -422,7 +424,7 @@ module Hatchet
422
424
 
423
425
  def run_ci(timeout: 300, &block)
424
426
  in_directory do
425
- Hatchet::RETRIES.times.retry do
427
+ max_retries_count.times.retry do
426
428
  result = create_pipeline
427
429
  @pipeline_id = result["id"]
428
430
  end
@@ -433,7 +435,7 @@ module Hatchet
433
435
  # that's why we create an app explictly (or maybe it already exists), and then associate it with with the pipeline
434
436
  # the app will be auto cleaned up later
435
437
  self.setup!
436
- Hatchet::RETRIES.times.retry do
438
+ max_retries_count.times.retry do
437
439
  couple_pipeline(@name, @pipeline_id)
438
440
  end
439
441
 
@@ -446,7 +448,7 @@ module Hatchet
446
448
  api_rate_limit: api_rate_limit
447
449
  )
448
450
 
449
- Hatchet::RETRIES.times.retry do
451
+ max_retries_count.times.retry do
450
452
  test_run.create_test_run
451
453
  end
452
454
  test_run.wait!(&block)
@@ -33,6 +33,7 @@ module Hatchet
33
33
 
34
34
  releases = platform_api.release.list(name)
35
35
  if releases.last["status"] == "failed"
36
+ commit! # An empty commit allows us to deploy again
36
37
  raise FailedReleaseError.new(self, "Buildpack: #{@buildpack.inspect}\nRepo: #{git_repo}", output: output)
37
38
  end
38
39
 
@@ -1,3 +1,3 @@
1
1
  module Hatchet
2
- VERSION = "7.0.0"
2
+ VERSION = "7.1.0"
3
3
  end
@@ -13,14 +13,29 @@ describe "AllowFailureGitTest" do
13
13
  }
14
14
 
15
15
  it "is marked as a failure if the release fails" do
16
+ app = Hatchet::GitApp.new("default_ruby", before_deploy: release_fail_proc, retries: 2)
17
+ def app.retry_error_message(*args); @test_attempts_count ||= 0; @test_attempts_count += 1; "" end
18
+ def app.test_attempts_count; @test_attempts_count ; end
19
+
16
20
  expect {
17
- Hatchet::GitApp.new("default_ruby", before_deploy: release_fail_proc).deploy {}
18
- }.to(raise_error(Hatchet::App::FailedReleaseError))
21
+ app.deploy {}
22
+ }.to raise_error { |error|
23
+ expect(error).to be_a(Hatchet::App::FailedReleaseError)
24
+ expect(error.message).to_not match("Everything up-to-date")
25
+ }
26
+
27
+ expect(app.test_attempts_count).to eq(2)
19
28
  end
20
29
 
21
30
  it "works when failure is allowed" do
22
- Hatchet::GitApp.new("default_ruby", before_deploy: release_fail_proc, allow_failure: true).deploy do |app|
23
- expect(app.output).to match("failing on release")
31
+ Hatchet::GitApp.new("default_ruby", before_deploy: release_fail_proc, allow_failure: true, retries: 3).tap do |app|
32
+ def app.retry_error_message(*args); @test_attempts_count ||= 0; @test_attempts_count += 1; "" end
33
+ def app.test_attempts_count; @test_attempts_count ; end
34
+
35
+ app.deploy do
36
+ expect(app.output).to match("failing on release")
37
+ expect(app.test_attempts_count).to eq(nil)
38
+ end
24
39
  end
25
40
  end
26
41
  end
@@ -28,3 +28,54 @@ describe "LockTest" do
28
28
  expect(branch).to eq("main")
29
29
  end
30
30
  end
31
+
32
+ describe "isolated lock tests" do
33
+ it "works when there's no hatchet.lock" do
34
+ Dir.mktmpdir do |dir|
35
+ dir = Pathname.new(dir)
36
+
37
+ dir.join("hatchet.json").open("w+") do |f|
38
+ f.puts %Q{{ "foo": ["sharpstone/lock_fail_main_default_is_master"] }}
39
+ end
40
+
41
+ output = `cd #{dir} && hatchet lock 2>&1`
42
+
43
+ raise "Expected cmd `hatchet lock` to succeed, but it did not: #{output}" unless $?.success?
44
+ expect(output).to include("locking")
45
+
46
+ lockfile_contents = dir.join('hatchet.lock').read
47
+ expect(lockfile_contents).to include("repos/foo/lock_fail_main_default_is_master")
48
+ end
49
+ end
50
+
51
+ it "works when a project is locked to main but the default branch is master" do
52
+ Dir.mktmpdir do |dir|
53
+ dir = Pathname.new(dir)
54
+
55
+ dir.join("hatchet.json").open("w+") do |f|
56
+ f.puts %Q{{ "foo": ["sharpstone/lock_fail_main_default_is_master"] }}
57
+ end
58
+
59
+ dir.join("hatchet.lock").open("w+") do |f|
60
+ f.puts <<~EOM
61
+ ---
62
+ - - "./repos/foo/lock_fail_main_default_is_master"
63
+ - main
64
+ EOM
65
+ end
66
+
67
+ output = `cd #{dir} && hatchet install 2>&1`
68
+
69
+ raise "Expected cmd `hatchet install` to succeed, but it did not:\n#{output}" unless $?.success?
70
+ expect(output).to include("Installing")
71
+
72
+ lockfile_contents = dir.join('hatchet.lock').read
73
+ contents = YAML.safe_load(lockfile_contents).to_h
74
+ expect(contents).to eq({"./repos/foo/lock_fail_main_default_is_master" => "main"})
75
+
76
+ contents.each do |repo_dir, commit_or_branch|
77
+ expect(`cd #{dir.join(repo_dir)} && git describe --contains --all HEAD`).to match("main")
78
+ end
79
+ end
80
+ end
81
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: heroku_hatchet
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0
4
+ version: 7.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Richard Schneeman
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-08-11 00:00:00.000000000 Z
11
+ date: 2020-08-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: platform-api