heroku_hatchet 7.0.0 → 7.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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