shipit-engine 0.37.0 → 0.39.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.
Files changed (60) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +8 -3
  3. data/app/controllers/shipit/api/base_controller.rb +2 -2
  4. data/app/controllers/shipit/api/deploys_controller.rb +5 -1
  5. data/app/controllers/shipit/api/stacks_controller.rb +25 -1
  6. data/app/helpers/shipit/api_clients_helper.rb +12 -0
  7. data/app/jobs/shipit/continuous_delivery_job.rb +4 -1
  8. data/app/models/shipit/api_client.rb +1 -1
  9. data/app/models/shipit/commit_deployment_status.rb +0 -1
  10. data/app/models/shipit/delivery.rb +1 -1
  11. data/app/models/shipit/deploy_spec/file_system.rb +14 -2
  12. data/app/models/shipit/hook.rb +1 -1
  13. data/app/models/shipit/pull_request.rb +1 -1
  14. data/app/models/shipit/stack.rb +21 -5
  15. data/app/models/shipit/task.rb +7 -3
  16. data/app/models/shipit/task_execution_strategy/default.rb +1 -1
  17. data/app/models/shipit/user.rb +2 -0
  18. data/app/views/shipit/_variables.html.erb +1 -1
  19. data/app/views/shipit/api_clients/show.html.erb +1 -1
  20. data/app/views/shipit/merge_status/failure.html.erb +1 -1
  21. data/app/views/shipit/missing_settings.html.erb +1 -1
  22. data/config/secrets.development.example.yml +1 -1
  23. data/config/secrets.development.shopify.yml +1 -1
  24. data/db/migrate/20230703181143_change_commit_deployment_statuses_github_id_to_big_int.rb +5 -0
  25. data/lib/shipit/engine.rb +1 -1
  26. data/lib/shipit/github_app.rb +0 -1
  27. data/lib/shipit/octokit_check_runs.rb +1 -3
  28. data/lib/shipit/octokit_iterator.rb +2 -0
  29. data/lib/shipit/stack_commands.rb +11 -1
  30. data/lib/shipit/task_commands.rb +1 -1
  31. data/lib/shipit/version.rb +1 -1
  32. data/lib/shipit.rb +1 -1
  33. data/test/controllers/api/base_controller_test.rb +1 -1
  34. data/test/controllers/api/ccmenu_controller_test.rb +1 -1
  35. data/test/controllers/api/commits_controller_test.rb +1 -1
  36. data/test/controllers/api/deploys_controller_test.rb +25 -1
  37. data/test/controllers/api/hooks_controller_test.rb +1 -1
  38. data/test/controllers/api/locks_controller_test.rb +1 -1
  39. data/test/controllers/api/merge_requests_controller_test.rb +1 -1
  40. data/test/controllers/api/outputs_controller_test.rb +1 -1
  41. data/test/controllers/api/release_statuses_controller_test.rb +1 -1
  42. data/test/controllers/api/rollback_controller_test.rb +1 -1
  43. data/test/controllers/api/stacks_controller_test.rb +52 -1
  44. data/test/controllers/api/tasks_controller_test.rb +1 -1
  45. data/test/controllers/stacks_controller_test.rb +1 -1
  46. data/test/controllers/tasks_controller_test.rb +8 -1
  47. data/test/dummy/config/application.rb +2 -1
  48. data/test/dummy/config/initializers/0_load_development_secrets.rb +2 -2
  49. data/test/dummy/config/secrets.development.json +3 -0
  50. data/test/dummy/config/secrets.test.json +21 -0
  51. data/test/dummy/db/schema.rb +2 -2
  52. data/test/helpers/api_helper.rb +13 -0
  53. data/test/models/commit_deployment_status_test.rb +0 -1
  54. data/test/models/merge_request_test.rb +4 -1
  55. data/test/models/shipit/{stacks_test.rb → stack_test.rb} +48 -5
  56. data/test/models/users_test.rb +8 -0
  57. data/test/test_helper.rb +2 -2
  58. data/test/unit/deploy_commands_test.rb +94 -6
  59. data/test/unit/github_app_test.rb +1 -1
  60. metadata +15 -9
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 174fee8bf3ed460fa137cbe666f639fec2218d0617b4860dcede08d38ed6d93d
4
- data.tar.gz: 739d8f122ead25b8f1053f954686e4ddd574bc17b544de9b69dce5af7635425c
3
+ metadata.gz: d14e4fec687523820d46bf58196894deb71b3acb79358059b743d33c31bf9305
4
+ data.tar.gz: e5d756e9bc4f452408f40d0a3f1f2d6f06cbeceb7544ae47d91b245acb1fc83b
5
5
  SHA512:
6
- metadata.gz: 7b3118fb7bc39e0c8cddad0444d34c39e935bcc192010dec3b27b2bddd9947a770573a959b13fe26661eb8874963b10cdb8ab2382d6eec811ebd8cd87322cc41
7
- data.tar.gz: cd173c7dc66f31a90e878ed9a2da9724132286c93f2a9c168a5593f81ffbfe3c6f25161095fafe7df1e9d7c2561339ca0c4051ae856c78d8698d382e8d65818c
6
+ metadata.gz: e4a7e88bdf8fe9c40fe6520054fad67a72af184524bb1a8f3a20c0bea07b858cf5d568b272ce0a95060c8bfa2c64b5cb1adec7487a877e23f37e6a8bf3f143ed
7
+ data.tar.gz: 6cab2f24a84a81251991dc20b23c4d9f966fa8b98f053b904b34227850efca196133ec2c395a5e0c8444b8c41d6672d1362058fd1c90e543e7b1c97d6f07732a
data/README.md CHANGED
@@ -25,8 +25,8 @@ This guide aims to help you [set up](#installation-and-setup), [use](#using-ship
25
25
  **II. USING SHIPIT**
26
26
 
27
27
  * [Adding stacks](#adding-stacks)
28
- * [Working on stacks](#working-on-stacks),
29
- * [Configuring stacks](#configuring-stacks).
28
+ * [Working on stacks](#working-on-stacks)
29
+ * [Configuring stacks](#configuring-stacks)
30
30
 
31
31
  **III. REFERENCE**
32
32
 
@@ -357,6 +357,11 @@ For example:
357
357
  fetch:
358
358
  curl --silent https://app.example.com/services/ping/version
359
359
  ```
360
+
361
+ **Note:** Currently, deployments in emergency mode are configured to occur concurrently via [the `build_deploy` method](https://github.com/Shopify/shipit-engine/blob/main/app/models/shipit/stack.rb),
362
+ whose `allow_concurrency` keyword argument defaults to `force`, where `force` is true when emergency mode is enabled.
363
+ If you'd like to separate these two from one another, override this method as desired in your service.
364
+
360
365
  <h3 id="kubernetes">Kubernetes</h3>
361
366
 
362
367
  **<code>kubernetes</code>** allows to specify a Kubernetes namespace and context to deploy to.
@@ -641,7 +646,7 @@ Your deploy scripts have access to the following environment variables:
641
646
  * `GITHUB_REPO_OWNER`: The GitHub username of the repository owner for the current deploy/task.
642
647
  * `EMAIL`: Email of the user that triggered the deploy/task (if available)
643
648
  * `ENVIRONMENT`: The stack environment (e.g `production` / `staging`)
644
- * `BRANCH`: The stack branch (e.g `master`)
649
+ * `BRANCH`: The stack branch (e.g `main`)
645
650
  * `LAST_DEPLOYED_SHA`: The git SHA of the last deployed commit
646
651
  * `DIFF_LINK`: URL to the diff on GitHub.
647
652
  * `TASK_ID`: ID of the task that is running
@@ -93,8 +93,8 @@ module Shipit
93
93
  render(status: :not_found, json: { status: '404', error: 'Not Found' })
94
94
  end
95
95
 
96
- def conflict(_error)
97
- render(status: :conflict, json: { status: '409', error: 'Conflict' })
96
+ def conflict(error)
97
+ render(status: :conflict, json: { status: '409', error: error.message })
98
98
  end
99
99
  end
100
100
  end
@@ -11,6 +11,7 @@ module Shipit
11
11
  params do
12
12
  requires :sha, String, length: { in: 6..40 }
13
13
  accepts :force, Boolean, default: false
14
+ accepts :allow_concurrency, Boolean
14
15
  accepts :require_ci, Boolean, default: false
15
16
  accepts :env, Hash, default: {}
16
17
  end
@@ -18,7 +19,10 @@ module Shipit
18
19
  commit = stack.commits.by_sha(params.sha) || param_error!(:sha, 'Unknown revision')
19
20
  param_error!(:force, "Can't deploy a locked stack") if !params.force && stack.locked?
20
21
  param_error!(:require_ci, "Commit is not deployable") if params.require_ci && !commit.deployable?
21
- deploy = stack.trigger_deploy(commit, current_user, env: params.env, force: params.force)
22
+
23
+ allow_concurrency = params.allow_concurrency.nil? ? params.force : params.allow_concurrency
24
+ deploy = stack.trigger_deploy(commit, current_user, env: params.env, force: params.force,
25
+ allow_concurrency: allow_concurrency)
22
26
  render_resource(deploy, status: :accepted)
23
27
  end
24
28
  end
@@ -46,9 +46,13 @@ module Shipit
46
46
  accepts :ignore_ci, Boolean
47
47
  accepts :merge_queue_enabled, Boolean
48
48
  accepts :continuous_deployment, Boolean
49
+ accepts :archived, Boolean
49
50
  end
50
51
  def update
51
- stack.update(params)
52
+ stack.update(update_params)
53
+
54
+ update_archived
55
+
52
56
  render_resource(stack)
53
57
  end
54
58
 
@@ -78,6 +82,26 @@ module Shipit
78
82
  @stack ||= stacks.from_param!(params[:id])
79
83
  end
80
84
 
85
+ def update_archived
86
+ if key?(:archived)
87
+ if params[:archived]
88
+ stack.archive!(nil)
89
+ elsif stack.archived?
90
+ stack.unarchive!
91
+ end
92
+ end
93
+ end
94
+
95
+ def key?(key)
96
+ params.to_h.key?(key)
97
+ end
98
+
99
+ def update_params
100
+ params.select do |key, _|
101
+ %i(environment branch deploy_url ignore_ci merge_queue_enabled continuous_deployment).include?(key)
102
+ end
103
+ end
104
+
81
105
  def repository
82
106
  @repository ||= Repository.find_or_create_by(owner: repo_owner, name: repo_name)
83
107
  end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+ module Shipit
3
+ module ApiClientsHelper
4
+ def api_client_token(api_client)
5
+ if api_client.created_at >= 5.minutes.ago && current_user == api_client.creator
6
+ api_client.authentication_token
7
+ else
8
+ "#{api_client.authentication_token[0..5]}************************"
9
+ end
10
+ end
11
+ end
12
+ end
@@ -8,7 +8,10 @@ module Shipit
8
8
 
9
9
  def perform(stack)
10
10
  return unless stack.continuous_deployment?
11
- return if stack.active_task?
11
+
12
+ # checks if there are any tasks running, including concurrent tasks
13
+ return if stack.occupied?
14
+
12
15
  stack.trigger_continuous_delivery
13
16
  end
14
17
  end
@@ -8,7 +8,7 @@ module Shipit
8
8
 
9
9
  validates :creator, :name, presence: true
10
10
 
11
- serialize :permissions, Shipit.serialized_column(:permissions, type: Array)
11
+ serialize :permissions, coder: Shipit.serialized_column(:permissions, type: Array)
12
12
  PERMISSIONS = %w(
13
13
  read:stack
14
14
  write:stack
@@ -48,7 +48,6 @@ module Shipit
48
48
  client.create_deployment_status(
49
49
  commit_deployment.api_url,
50
50
  status,
51
- accept: 'application/vnd.github.flash-preview+json',
52
51
  target_url: url_helpers.stack_deploy_url(stack, task),
53
52
  description: description.truncate(DESCRIPTION_CHARACTER_LIMIT_ON_GITHUB),
54
53
  environment_url: stack.deploy_url,
@@ -9,7 +9,7 @@ module Shipit
9
9
  validates :url, presence: true, url: { no_local: true, allow_blank: true }
10
10
  validates :content_type, presence: true
11
11
 
12
- serialize :response_headers, SafeJSON
12
+ serialize :response_headers, coder: SafeJSON
13
13
 
14
14
  after_commit :purge_old_deliveries, on: :create
15
15
 
@@ -101,11 +101,23 @@ module Shipit
101
101
  end
102
102
 
103
103
  def shipit_file_names_in_priority_order
104
- ["#{app_name}.#{@env}.yml", "#{app_name}.yml", "shipit.#{@env}.yml", "shipit.yml"].uniq
104
+ [
105
+ "#{app_name}.#{@env}.yml",
106
+ ".shipit/#{app_name}.#{@env}.yml",
107
+
108
+ "#{app_name}.yml",
109
+ ".shipit/#{app_name}.yml",
110
+
111
+ "shipit.#{@env}.yml",
112
+ ".shipit/#{@env}.yml",
113
+
114
+ "shipit.yml",
115
+ ".shipit/shipit.yml",
116
+ ].uniq
105
117
  end
106
118
 
107
119
  def bare_shipit_filenames
108
- ["#{app_name}.yml", "shipit.yml"].uniq
120
+ ["#{app_name}.yml", "shipit.yml", ".shipit/#{app_name}.yml", ".shipit/shipit.yml"].uniq
109
121
  end
110
122
 
111
123
  def config_file_path
@@ -87,7 +87,7 @@ module Shipit
87
87
  validates :content_type, presence: true, inclusion: { in: CONTENT_TYPES.keys }
88
88
  validates :events, presence: true, subset: { of: EVENTS }
89
89
 
90
- serialize :events, Shipit::CSVSerializer
90
+ serialize :events, coder: Shipit::CSVSerializer
91
91
 
92
92
  scope :global, -> { where(stack_id: nil) }
93
93
  scope :scoped_to, ->(stack) { where(stack_id: stack.id) }
@@ -11,7 +11,7 @@ module Shipit
11
11
  has_many :pull_request_assignments
12
12
  has_many :assignees, class_name: :User, through: :pull_request_assignments, source: :user
13
13
 
14
- serialize :labels, Shipit.serialized_column(:labels, type: Array)
14
+ serialize :labels, coder: Shipit.serialized_column(:labels, type: Array)
15
15
 
16
16
  after_create_commit :emit_create_hooks
17
17
  after_update_commit :emit_update_hooks
@@ -101,7 +101,7 @@ module Shipit
101
101
 
102
102
  validates :lock_reason, length: { maximum: 4096 }
103
103
 
104
- serialize :cached_deploy_spec, DeploySpec
104
+ serialize :cached_deploy_spec, coder: DeploySpec
105
105
  delegate(
106
106
  :provisioning_handler_name,
107
107
  :find_task_definition,
@@ -150,14 +150,14 @@ module Shipit
150
150
  task
151
151
  end
152
152
 
153
- def build_deploy(until_commit, user, env: nil, force: false)
153
+ def build_deploy(until_commit, user, env: nil, force: false, allow_concurrency: force)
154
154
  since_commit = last_deployed_commit.presence || commits.first
155
155
  deploys.build(
156
156
  user_id: user.id,
157
157
  until_commit: until_commit,
158
158
  since_commit: since_commit,
159
159
  env: filter_deploy_envs(env&.to_h || {}),
160
- allow_concurrency: force,
160
+ allow_concurrency: allow_concurrency,
161
161
  ignored_safeties: force || !until_commit.deployable?,
162
162
  max_retries: retries_on_deploy,
163
163
  )
@@ -226,8 +226,12 @@ module Shipit
226
226
 
227
227
  def next_commit_to_deploy
228
228
  commits_to_deploy = commits.order(id: :asc).newer_than(last_deployed_commit).reachable.preload(:statuses)
229
- commits_to_deploy = commits_to_deploy.limit(maximum_commits_per_deploy) if maximum_commits_per_deploy
230
- commits_to_deploy.to_a.reverse.find(&:deployable?)
229
+ if maximum_commits_per_deploy
230
+ commits_with_max_applied = commits_to_deploy.limit(maximum_commits_per_deploy)
231
+ deployable_commits(commits_with_max_applied) || deployable_commits(commits_to_deploy)
232
+ else
233
+ deployable_commits(commits_to_deploy)
234
+ end
231
235
  end
232
236
 
233
237
  def deployed_too_recently?
@@ -453,6 +457,14 @@ module Shipit
453
457
  @active_task ||= tasks.current
454
458
  end
455
459
 
460
+ def occupied?
461
+ !!occupied
462
+ end
463
+
464
+ def occupied
465
+ @occupied ||= tasks.active.last
466
+ end
467
+
456
468
  def locked?
457
469
  lock_reason.present?
458
470
  end
@@ -620,6 +632,10 @@ module Shipit
620
632
 
621
633
  private
622
634
 
635
+ def deployable_commits(commits)
636
+ commits.to_a.reverse.find(&:deployable?)
637
+ end
638
+
623
639
  def clear_cache
624
640
  remove_instance_variable(:@active_task) if defined?(@active_task)
625
641
  end
@@ -3,7 +3,11 @@ module Shipit
3
3
  class Task < Record
4
4
  include DeferredTouch
5
5
 
6
- ConcurrentTaskRunning = Class.new(StandardError)
6
+ class ConcurrentTaskRunning < StandardError
7
+ def message
8
+ "A task is already running."
9
+ end
10
+ end
7
11
 
8
12
  PRESENCE_CHECK_TIMEOUT = 30
9
13
  ACTIVE_STATUSES = %w(pending running aborting).freeze
@@ -54,8 +58,8 @@ module Shipit
54
58
  end
55
59
  end
56
60
 
57
- serialize :definition, TaskDefinition
58
- serialize :env, Shipit.serialized_column(:env, coder: EnvHash)
61
+ serialize :definition, coder: TaskDefinition
62
+ serialize :env, coder: Shipit.serialized_column(:env, coder: EnvHash)
59
63
 
60
64
  scope :success, -> { where(status: 'success') }
61
65
  scope :completed, -> { where(status: COMPLETED_STATUSES) }
@@ -70,7 +70,7 @@ module Shipit
70
70
  @task.acquire_git_cache_lock do
71
71
  @task.ping
72
72
  unless @commands.fetched?(@task.until_commit).tap(&:run).success?
73
- capture!(@commands.fetch)
73
+ capture!(@commands.fetch_commit(@task.until_commit))
74
74
  end
75
75
  end
76
76
  end
@@ -95,6 +95,8 @@ module Shipit
95
95
  update!(github_user: Shipit.github.api.user(github_id))
96
96
  rescue Octokit::NotFound
97
97
  identify_renamed_user!
98
+ rescue Octokit::Forbidden
99
+ Rails.logger.info("User #{name}, github_id #{github_id} has forbidden access to their GitHub, likely deleted.")
98
100
  end
99
101
 
100
102
  def github_user=(github_user)
@@ -9,7 +9,7 @@
9
9
  <% if variable.select %>
10
10
  <%= field.select variable.name, options_for_select([["Please select...", { disabled: "disabled" }]] + variable.select, variable.default || "Please select...") %>
11
11
  <% else %>
12
- <%= field.text_field variable.name, value: variable.default %>
12
+ <%= field.text_field variable.name, value: params[variable.name].presence || variable.default %>
13
13
  <% end %>
14
14
  <%= field.label variable.name, variable.title || variable.name %>
15
15
  </p>
@@ -10,7 +10,7 @@
10
10
  <section>
11
11
  <h3>Authentication token:</h3>
12
12
  <code style="background-color: yellow">
13
- <b><%= @api_client.authentication_token %></b>
13
+ <b><%= api_client_token(@api_client) %></b>
14
14
  </code>
15
15
  </section>
16
16
 
@@ -15,7 +15,7 @@
15
15
  </h4>
16
16
  <span class="status-meta">
17
17
  <%= link_to @stack.to_param, stack_url(@stack), target: '_blank', rel: 'noopener' %>
18
- <strong>master branch is failing!</strong>
18
+ <strong>main branch is failing!</strong>
19
19
  </span>
20
20
  <%= render 'commit_count_warning' if display_commit_count_warning?(params[:commits].to_i) %>
21
21
  </div>
@@ -22,7 +22,7 @@
22
22
 
23
23
  <p id="github_app">
24
24
  Config:
25
- <% if Rails.application.secrets.github.present? %>
25
+ <% if Rails.application.credentials.github.present? %>
26
26
  Success!
27
27
  <% else %>
28
28
  <span class="missing">
@@ -1,7 +1,7 @@
1
1
  host: 'localhost:3000'
2
2
  redis_url: 'redis://127.0.0.1:6379/0'
3
3
 
4
- # For creating an app see: https://github.com/Shopify/shipit-engine/blob/master/docs/setup.md#creating-the-github-app
4
+ # For creating an app see: https://github.com/Shopify/shipit-engine/blob/main/docs/setup.md#creating-the-github-app
5
5
  # Can be obtained there: https://github.com/settings/apps
6
6
  # Set the "Authorization callback URL" as `<host>/github/auth/github/callback`
7
7
 
@@ -1,7 +1,7 @@
1
1
  host: 'shipit-engine.myshopify.io'
2
2
  redis_url: 'redis://shipit-engine.railgun:6379'
3
3
 
4
- # For creating an app see: https://github.com/Shopify/shipit-engine/blob/master/docs/setup.md#creating-the-github-app
4
+ # For creating an app see: https://github.com/Shopify/shipit-engine/blob/main/docs/setup.md#creating-the-github-app
5
5
 
6
6
  github:
7
7
  somegithuborg:
@@ -0,0 +1,5 @@
1
+ class ChangeCommitDeploymentStatusesGithubIdToBigInt < ActiveRecord::Migration[7.0]
2
+ def change
3
+ change_column :commit_deployment_statuses, :github_id, :bigint
4
+ end
5
+ end
data/lib/shipit/engine.rb CHANGED
@@ -21,7 +21,7 @@ module Shipit
21
21
  Shipit::Engine.routes.default_url_options[:host] = Shipit.host
22
22
  Pubsubstub.redis_url = Shipit.redis_url.to_s
23
23
 
24
- Rails.application.secrets.deep_symbolize_keys!
24
+ Rails.application.credentials.deep_symbolize_keys!
25
25
 
26
26
  app.config.assets.paths << Emoji.images_path
27
27
  app.config.assets.precompile += %w(
@@ -103,7 +103,6 @@ module Shipit
103
103
  ) do
104
104
  response = new_client(bearer_token: authentication_payload).create_app_installation_access_token(
105
105
  installation_id,
106
- accept: 'application/vnd.github.machine-man-preview+json',
107
106
  )
108
107
  token = Token.from_github(response)
109
108
  raise AuthenticationFailed if token.blank?
@@ -1,9 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  module OctokitCheckRuns
3
3
  def check_runs(repo, sha, options = {})
4
- paginate("#{Octokit::Repository.path(repo)}/commits/#{sha}/check-runs", options.reverse_merge(
5
- accept: 'application/vnd.github.antiope-preview+json',
6
- ))
4
+ paginate("#{Octokit::Repository.path(repo)}/commits/#{sha}/check-runs", options)
7
5
  end
8
6
  end
9
7
 
@@ -16,6 +16,8 @@ module Shipit
16
16
  response = @response
17
17
 
18
18
  loop do
19
+ return unless response.present?
20
+
19
21
  response.data.each(&block)
20
22
  return unless response.rels[:next]
21
23
  response = response.rels[:next].get
@@ -13,6 +13,16 @@ module Shipit
13
13
  super.merge(@stack.env)
14
14
  end
15
15
 
16
+ def fetch_commit(commit)
17
+ create_directories
18
+ if valid_git_repository?(@stack.git_path)
19
+ git('fetch', 'origin', '--quiet', '--tags', commit.sha, env: env, chdir: @stack.git_path)
20
+ else
21
+ @stack.clear_git_cache!
22
+ git_clone(@stack.repo_git_url, @stack.git_path, branch: @stack.branch, env: env, chdir: @stack.deploys_path)
23
+ end
24
+ end
25
+
16
26
  def fetch
17
27
  create_directories
18
28
  if valid_git_repository?(@stack.git_path)
@@ -96,7 +106,7 @@ module Shipit
96
106
  .success?
97
107
  end
98
108
 
99
- def git_clone(url, path, branch: 'master', **kwargs)
109
+ def git_clone(url, path, branch: 'main', **kwargs)
100
110
  git('clone', '--quiet', *modern_git_args, '--recursive', '--branch', branch, url, path, **kwargs)
101
111
  end
102
112
 
@@ -2,7 +2,7 @@
2
2
  # rubocop:disable Lint/MissingSuper
3
3
  module Shipit
4
4
  class TaskCommands < Commands
5
- delegate :fetch, :fetched?, to: :stack_commands
5
+ delegate :fetch_commit, :fetch, :fetched?, to: :stack_commands
6
6
 
7
7
  def initialize(task)
8
8
  @task = task
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Shipit
3
- VERSION = '0.37.0'
3
+ VERSION = '0.39.0'
4
4
  end
data/lib/shipit.rb CHANGED
@@ -291,7 +291,7 @@ module Shipit
291
291
  end
292
292
 
293
293
  def secrets
294
- Rails.application.secrets
294
+ Rails.application.credentials
295
295
  end
296
296
  end
297
297
 
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class BaseControllerTest < ActionController::TestCase
6
+ class BaseControllerTest < ApiControllerTestCase
7
7
  test "authentication is required" do
8
8
  get :index
9
9
  assert_response :unauthorized
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class CCMenuControllerTest < ActionController::TestCase
6
+ class CCMenuControllerTest < ApiControllerTestCase
7
7
  setup do
8
8
  authenticate!
9
9
  @stack = shipit_stacks(:shipit)
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class CommitsControllerTest < ActionController::TestCase
6
+ class CommitsControllerTest < ApiControllerTestCase
7
7
  setup do
8
8
  @stack = shipit_stacks(:shipit)
9
9
  authenticate!
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class DeploysControllerTest < ActionController::TestCase
6
+ class DeploysControllerTest < ApiControllerTestCase
7
7
  setup do
8
8
  authenticate!
9
9
  @user = shipit_users(:walrus)
@@ -81,6 +81,7 @@ module Shipit
81
81
  end
82
82
 
83
83
  assert_response :conflict
84
+ assert_json 'error', 'A task is already running.'
84
85
  end
85
86
 
86
87
  test "#create refuses to deploy unsuccessful commits if the require_ci flag is passed" do
@@ -119,6 +120,29 @@ module Shipit
119
120
  assert_response :accepted
120
121
  assert_json 'status', 'pending'
121
122
  end
123
+
124
+ test "#create uses allow_concurrency param when provided" do
125
+ @stack.update!(lock_reason: 'Something broken')
126
+
127
+ assert_difference -> { @stack.deploys.count }, 1 do
128
+ post :create, params: { stack_id: @stack.to_param, sha: @commit.sha, force: 'true', allow_concurrency: 'false' }
129
+ end
130
+ assert_response :accepted
131
+ assert_json 'status', 'pending'
132
+ refute @stack.deploys.last.allow_concurrency
133
+ end
134
+
135
+ test "#create defaults allow_concurrency to force param when not provided" do
136
+ @stack.update!(lock_reason: 'Something broken')
137
+ expected_force = true
138
+
139
+ assert_difference -> { @stack.deploys.count }, 1 do
140
+ post :create, params: { stack_id: @stack.to_param, sha: @commit.sha, force: expected_force }
141
+ end
142
+ assert_response :accepted
143
+ assert_json 'status', 'pending'
144
+ assert_equal expected_force, @stack.deploys.last.allow_concurrency
145
+ end
122
146
  end
123
147
  end
124
148
  end
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class HooksControllerTest < ActionController::TestCase
6
+ class HooksControllerTest < ApiControllerTestCase
7
7
  setup do
8
8
  authenticate!
9
9
  @stack = shipit_stacks(:shipit)
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class LocksControllerTest < ActionController::TestCase
6
+ class LocksControllerTest < ApiControllerTestCase
7
7
  setup do
8
8
  authenticate!
9
9
  @stack = shipit_stacks(:shipit)
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class MergeRequestsControllerTest < ActionController::TestCase
6
+ class MergeRequestsControllerTest < ApiControllerTestCase
7
7
  setup do
8
8
  @stack = shipit_stacks(:shipit)
9
9
  @merge_request = shipit_merge_requests(:shipit_pending)
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class OutputsControllerTest < ActionController::TestCase
6
+ class OutputsControllerTest < ApiControllerTestCase
7
7
  setup do
8
8
  @stack = shipit_stacks(:shipit)
9
9
  authenticate!
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class ReleaseStatusesControllerTest < ActionController::TestCase
6
+ class ReleaseStatusesControllerTest < ApiControllerTestCase
7
7
  setup do
8
8
  authenticate!
9
9
  @stack = shipit_stacks(:shipit_canaries)
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class RollbacksControllerTest < ActionController::TestCase
6
+ class RollbacksControllerTest < ApiControllerTestCase
7
7
  setup do
8
8
  authenticate!
9
9
  @user = shipit_users(:walrus)
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class StacksControllerTest < ActionController::TestCase
6
+ class StacksControllerTest < ApiControllerTestCase
7
7
  setup do
8
8
  authenticate!
9
9
  @stack = shipit_stacks(:shipit)
@@ -114,6 +114,57 @@ module Shipit
114
114
  refute @stack.continuous_deployment
115
115
  end
116
116
 
117
+ test "#update does not perform archive when key is not provided" do
118
+ refute_predicate @stack, :archived?
119
+ refute_predicate @stack, :locked?
120
+
121
+ patch :update, params: { id: @stack.to_param }
122
+
123
+ @stack.reload
124
+ refute_predicate @stack, :archived?
125
+ refute_predicate @stack, :locked?
126
+ end
127
+
128
+ test "#update does not perform unarchive when key is not provided" do
129
+ @stack.archive!(shipit_users(:walrus))
130
+ assert_predicate @stack, :locked?
131
+ assert_predicate @stack, :archived?
132
+
133
+ patch :update, params: { id: @stack.to_param }
134
+
135
+ @stack.reload
136
+ assert_predicate @stack, :locked?
137
+ assert_predicate @stack, :archived?
138
+ end
139
+
140
+ test "#update allows to archive the stack" do
141
+ refute_predicate @stack, :archived?
142
+ refute_predicate @stack, :locked?
143
+
144
+ patch :update, params: { id: @stack.to_param, archived: true }
145
+
146
+ @stack.reload
147
+ assert_predicate @stack, :locked?
148
+ assert_predicate @stack, :archived?
149
+ assert_instance_of AnonymousUser, @stack.lock_author
150
+ assert_equal "Archived", @stack.lock_reason
151
+ end
152
+
153
+ test "#update allows to unarchive the stack" do
154
+ @stack.archive!(shipit_users(:walrus))
155
+ assert_predicate @stack, :locked?
156
+ assert_predicate @stack, :archived?
157
+
158
+ patch :update, params: { id: @stack.to_param, archived: false }
159
+
160
+ @stack.reload
161
+ refute_predicate @stack, :archived?
162
+ refute_predicate @stack, :locked?
163
+ assert_nil @stack.locked_since
164
+ assert_nil @stack.lock_reason
165
+ assert_instance_of AnonymousUser, @stack.lock_author
166
+ end
167
+
117
168
  test "#index returns a list of stacks" do
118
169
  stack = Stack.last
119
170
  get :index
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class TasksControllerTest < ActionController::TestCase
6
+ class TasksControllerTest < ApiControllerTestCase
7
7
  setup do
8
8
  @stack = shipit_stacks(:shipit)
9
9
  @user = shipit_users(:walrus)
@@ -10,7 +10,7 @@ module Shipit
10
10
  end
11
11
 
12
12
  test "validates that Shipit.github is present" do
13
- Rails.application.secrets.stubs(:github).returns(nil)
13
+ Rails.application.credentials.stubs(:github).returns(nil)
14
14
  get :index
15
15
  assert_select "#github_app .missing"
16
16
  assert_select ".missing", count: 1
@@ -11,9 +11,16 @@ module Shipit
11
11
  session[:user_id] = shipit_users(:walrus).id
12
12
  end
13
13
 
14
- test "tasks defined in the shipit.yml can be displayed" do
14
+ test "tasks defined in the shipit.yml can be displayed with default variable values" do
15
15
  get :new, params: { stack_id: @stack, definition_id: @definition.id }
16
16
  assert_response :ok
17
+ assert_select 'input[name="task[env][FOO]"][value="1"]'
18
+ end
19
+
20
+ test "it is possible to provide a default value override for a task" do
21
+ get :new, params: { stack_id: @stack, definition_id: @definition.id, FOO: '42' }
22
+ assert_response :ok
23
+ assert_select 'input[name="task[env][FOO]"][value="42"]'
17
24
  end
18
25
 
19
26
  test "tasks defined in the shipit.yml can't be triggered if the stack is being deployed" do
@@ -17,6 +17,7 @@ end
17
17
 
18
18
  module Shipit
19
19
  class Application < Rails::Application
20
- config.load_defaults 7.0
20
+ config.load_defaults 7.1
21
+ config.active_record.encryption.support_sha1_for_non_deterministic_encryption = true
21
22
  end
22
23
  end
@@ -2,8 +2,8 @@ local_secrets = Shipit::Engine.root.join('config/secrets.development.yml')
2
2
  if local_secrets.exist?
3
3
  secrets = YAML.load(local_secrets.read).deep_symbolize_keys
4
4
  if Rails.env.development?
5
- Rails.application.secrets.deep_merge!(secrets)
5
+ Rails.application.credentials.deep_merge!(secrets)
6
6
  elsif Rails.env.test?
7
- Rails.application.secrets.merge!(redis_url: secrets[:redis_url])
7
+ Rails.application.credentials.merge!(redis_url: secrets[:redis_url])
8
8
  end
9
9
  end
@@ -0,0 +1,3 @@
1
+ {
2
+ "secret_key_base": "s3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3t"
3
+ }
@@ -0,0 +1,21 @@
1
+ {
2
+ "host": "shipit.com",
3
+ "secret_key_base": "s3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3t",
4
+ "github_api": {
5
+ "token": "t0k3n"
6
+ },
7
+ "github": {
8
+ "domain": null,
9
+ "app_id": 42,
10
+ "installation_id": 43,
11
+ "bot_login": "shipit[bot]",
12
+ "webhook_secret": null,
13
+ "private_key": "-----BEGIN RSA PRIVATE KEY-----\nMIIEpAIBAAKCAQEA7iUQC2uUq/gtQg0gxtyaccuicYgmq1LUr1mOWbmwM1Cv63+S\n73qo8h87FX+YyclY5fZF6SMXIys02JOkImGgbnvEOLcHnImCYrWs03msOzEIO/pG\nM0YedAPtQ2MEiLIu4y8htosVxeqfEOPiq9kQgFxNKyETzjdIA9q1md8sofuJUmPv\nibacW1PecuAMnn+P8qf0XIDp7uh6noB751KvhCaCNTAPtVE9NZ18OmNG9GOyX/pu\npQHIrPgTpTG6KlAe3r6LWvemzwsMtuRGU+K+KhK9dFIlSE+v9rA32KScO8efOh6s\nGu3rWorV4iDu14U62rzEfdzzc63YL94sUbZxbwIDAQABAoIBADLJ8r8MxZtbhYN1\nu0zOFZ45WL6v09dsBfITvnlCUeLPzYUDIzoxxcBFittN6C744x3ARS6wjimw+EdM\nTZALlCSb/sA9wMDQzt7wchhz9Zh2H5RzDu+2f54sjDh38KqancdT8PO2fAFGxX/b\nqicOVyeZB9gv6MJtJc20olBbuXAeBNfcDABF9oxF+0i+Ssg7B4VXiqgcjtGbr/Og\nqRll7AqyTArVx2xEcVfZxeZ4zGnigzcJq4te7yYpxzwk+RxblkPh54Yt4WxZ+8DI\nRsn3r6ajlpwzpwvsJFU2Txq7xBTzGQMFmy/Pnjk83kP2cogxB2+tRyjITGqTwD8b\ngg9PFCkCgYEA+7u8A0l0Cz6p0SI6c7ftVePVRiIhpawWN7og/wEmI6zUjm/3rA+R\nhrhaVKuOD8QF/HdDsqTck5gjGAjTmJz6r33/cl1Tz+pr62znsrB4r0yMKvQbKN81\nWGaWOsi2+ZXqLNv5h5wpUF0MTKlXHeKnwP5kuEvGwVn6WURFCh6PhLMCgYEA8i5e\nJjulJVGyd5HuoY3xyO7E6DjidsqRnVRq+hYpORjnHvTmSwe4+tH4ha2p9Kv2Y6k3\nC1NYY/fSMQoYCCRaYyJleI+la/9tsZqAmtms4ZB8KhFmPHf9fW75i6G0xKWyZ8K+\nE2Ft/UaEiM282593cguV6+Kt5uExnyPxLLK4FlUCgYEAwRJ/JGI8/7bjFkTTYheq\nj5q75BufhOrU6471acAe2XPgXxLfefdC3Xodxh0CS3NESBvNL4Ikr4sbN37lk4Kq\n/th7iOKtuqUIeru/hZy2I3VpeDRbdGCmEJQ2GwYA2LKztg5Nd0Y9paaIHXAwIfrK\nQUqcQ4HTAk8ZpUeoUBeaaeMCgYANLmbjb9WiPVsYVPIHCwHA7PX8qbPxwT7BsGmO\nKQyfVfKmZa/vH4F67Vi4deZNMdrcO8aKMEQcVM2065a5QrlEsgeR00eupB1lUEJ1\nqylUsZeAdqf43JMIc7TTW77KATa/nQLZbTEeWus1wvTngztuEqFbUGAks9cOkVc8\nFpIcbQKBgQDVIL8gPLmn0f+4oLF8MBC+oxtKpz14X5iJ1saGFkzW5I+nIEskpS0S\nqtirnTCnJFGdCrFwctnxiuiCmyGwpBYdjIfHyvYAHnqAtMnESzCUyeSFZiquVW5W\nMvbMmDPoV27XOHU9kIq6NXtfrkpufiyo6/VEYWozXalxKLNuqLYfPQ==\n-----END RSA PRIVATE KEY-----\n",
14
+ "oauth": {
15
+ "id": "Iv1.bf2c2c45b449bfd9",
16
+ "secret": "ef694cd6e45223075d78d138ef014049052665f1",
17
+ "teams": null
18
+ }
19
+ },
20
+ "redis_url": "redis://127.0.0.1:6379/7"
21
+ }
@@ -10,7 +10,7 @@
10
10
  #
11
11
  # It's strongly recommended that you check this file into your version control system.
12
12
 
13
- ActiveRecord::Schema.define(version: 2021_11_03_154121) do
13
+ ActiveRecord::Schema.define(version: 2023_07_03_181143) do
14
14
 
15
15
  create_table "api_clients", force: :cascade do |t|
16
16
  t.text "permissions", limit: 65535
@@ -42,7 +42,7 @@ ActiveRecord::Schema.define(version: 2021_11_03_154121) do
42
42
  create_table "commit_deployment_statuses", force: :cascade do |t|
43
43
  t.integer "commit_deployment_id"
44
44
  t.string "status"
45
- t.integer "github_id"
45
+ t.bigint "github_id"
46
46
  t.string "api_url"
47
47
  t.datetime "created_at", null: false
48
48
  t.datetime "updated_at", null: false
@@ -8,3 +8,16 @@ module ApiHelper
8
8
  request.headers['Authorization'] = "Basic #{Base64.encode64(client.authentication_token)}"
9
9
  end
10
10
  end
11
+
12
+ module Shipit
13
+ class ApiControllerTestCase < ActionController::TestCase
14
+ private
15
+
16
+ def process(_action, **kwargs)
17
+ if kwargs[:method] != "GET"
18
+ kwargs[:as] ||= :json
19
+ end
20
+ super
21
+ end
22
+ end
23
+ end
@@ -15,7 +15,6 @@ module Shipit
15
15
  @author.github_api.class.any_instance.expects(:create_deployment_status).with(
16
16
  @deployment.api_url,
17
17
  'in_progress',
18
- accept: "application/vnd.github.flash-preview+json",
19
18
  target_url: "http://shipit.com/shopify/shipit-engine/production/deploys/#{@task.id}",
20
19
  description: "walrus triggered the deploy of shopify/shipit-engine/production to #{@deployment.short_sha}",
21
20
  environment_url: "https://shipit.shopify.com",
@@ -243,7 +243,10 @@ module Shipit
243
243
  end
244
244
 
245
245
  test "status transitions emit hooks" do
246
- job = assert_enqueued_with(job: EmitEventJob) do
246
+ expected_args = ->(job_args) do
247
+ job_args.first[:event] == 'merge'
248
+ end
249
+ job = assert_enqueued_with(job: EmitEventJob, args: expected_args) do
247
250
  @pr.reject!('merge_conflict')
248
251
  end
249
252
  params = job.arguments.first
@@ -3,7 +3,7 @@ require 'test_helper'
3
3
  require 'securerandom'
4
4
 
5
5
  module Shipit
6
- class StacksTest < ActiveSupport::TestCase
6
+ class StackTest < ActiveSupport::TestCase
7
7
  def setup
8
8
  @stack = shipit_stacks(:shipit)
9
9
  @expected_base_path = Rails.root.join('data', 'stacks', @stack.to_param).to_s
@@ -278,6 +278,36 @@ module Shipit
278
278
  end
279
279
  end
280
280
 
281
+ test "#active_task? is false if stack has a concurrent deploy in active state" do
282
+ @stack.trigger_deploy(shipit_commits(:third), AnonymousUser.new, force: true)
283
+ refute @stack.active_task?
284
+ end
285
+
286
+ test "#occupied? is false if stack has no deploy in either pending or running state" do
287
+ @stack.deploys.active.destroy_all
288
+ refute @stack.occupied?
289
+ end
290
+
291
+ test "#occupied? is false if stack has no deploy at all" do
292
+ @stack.deploys.destroy_all
293
+ refute @stack.occupied?
294
+ end
295
+
296
+ test "occupied? is true if stack has a concurrent deploy in active state" do
297
+ @stack.trigger_deploy(shipit_commits(:third), AnonymousUser.new, force: true)
298
+ assert @stack.occupied?
299
+ end
300
+
301
+ test "occupied? is true if stack has a deploy in pending state" do
302
+ @stack.trigger_deploy(shipit_commits(:third), AnonymousUser.new)
303
+ assert @stack.occupied?
304
+ end
305
+
306
+ test "#occupied? is true if a rollback is ongoing" do
307
+ shipit_deploys(:shipit_complete).trigger_rollback(AnonymousUser.new)
308
+ assert @stack.occupied?
309
+ end
310
+
281
311
  test "#deployable? returns true if the stack is not locked, not awaiting provision, and is not deploying" do
282
312
  @stack.deploys.destroy_all
283
313
  @stack.update!(lock_reason: nil, awaiting_provision: false)
@@ -674,12 +704,12 @@ module Shipit
674
704
  assert_equal shipit_commits(:fifth), @stack.next_commit_to_deploy
675
705
  end
676
706
 
677
- test "#next_commit_to_deploy respects the deploy.max_commits directive" do
707
+ test "#next_commit_to_deploy respects the deploy.max_commits directive given the commit is deployable" do
678
708
  @stack.tasks.destroy_all
679
709
 
680
- fifth_commit = shipit_commits(:third)
681
- fifth_commit.statuses.create!(stack_id: @stack.id, state: 'success', context: 'ci/travis')
682
- assert_predicate fifth_commit, :deployable?
710
+ third_commit = shipit_commits(:third)
711
+ third_commit.statuses.create!(stack_id: @stack.id, state: 'success', context: 'ci/travis')
712
+ assert_predicate third_commit, :deployable?
683
713
 
684
714
  assert_equal shipit_commits(:third), @stack.next_commit_to_deploy
685
715
 
@@ -687,6 +717,19 @@ module Shipit
687
717
  assert_equal shipit_commits(:third), @stack.next_commit_to_deploy
688
718
  end
689
719
 
720
+ test "#next_commit_to_deploy deploys the first deployable commit when deploy.max_commits directive fails to find a deployable commit" do
721
+ @stack.tasks.destroy_all
722
+
723
+ third_commit = shipit_commits(:third)
724
+ third_commit.statuses.create!(stack_id: @stack.id, state: 'success', context: 'ci/travis')
725
+ assert_predicate third_commit, :deployable?
726
+
727
+ assert_equal shipit_commits(:third), @stack.next_commit_to_deploy
728
+
729
+ @stack.expects(:maximum_commits_per_deploy).returns(1).at_least_once
730
+ assert_equal shipit_commits(:third), @stack.next_commit_to_deploy
731
+ end
732
+
690
733
  test "setting #lock_reason also sets #locked_since" do
691
734
  assert_predicate @stack.locked_since, :nil?
692
735
 
@@ -203,6 +203,14 @@ module Shipit
203
203
  assert_equal 'george@cyclim.se', user.email
204
204
  end
205
205
 
206
+ test "#refresh_from_github! logs deleted users" do
207
+ Shipit.github.api.expects(:user).with(@user.github_id).raises(Octokit::Forbidden)
208
+
209
+ Rails.logger.expects(:info).with("User #{@user.name}, github_id #{@user.github_id} has forbidden access to their GitHub, likely deleted.")
210
+
211
+ @user.refresh_from_github!
212
+ end
213
+
206
214
  test "#github_api uses the user's access token" do
207
215
  assert_equal @user.github_access_token, @user.github_api.access_token
208
216
  end
data/test/test_helper.rb CHANGED
@@ -23,7 +23,7 @@ require 'spy/integration'
23
23
 
24
24
  # Load fixtures from the engine
25
25
  if ActiveSupport::TestCase.respond_to?(:fixture_path=)
26
- ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
26
+ ActiveSupport::TestCase.fixture_paths << File.expand_path("../fixtures", __FILE__)
27
27
  ActiveSupport::TestCase.fixtures(:all)
28
28
  end
29
29
 
@@ -71,7 +71,7 @@ module ActiveSupport
71
71
  end
72
72
  end
73
73
 
74
- ActiveRecord::Migration.check_pending!
74
+ ActiveRecord::Migration.check_all_pending!
75
75
 
76
76
  # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
77
77
  #
@@ -21,6 +21,100 @@ module Shipit
21
21
  StackCommands.stubs(git_version: Gem::Version.new('1.8.4.3'))
22
22
  end
23
23
 
24
+ test "#fetch_commit calls git fetch if repository cache already exist" do
25
+ @stack.git_path.stubs(:exist?).returns(true)
26
+ @stack.git_path.stubs(:empty?).returns(false)
27
+
28
+ command = @commands.fetch_commit(@deploy.until_commit)
29
+
30
+ assert_equal %W(git fetch origin --quiet --tags #{@deploy.until_commit.sha}), command.args
31
+ end
32
+
33
+ test "#fetch_commit calls git fetch in git_path directory if repository cache already exist" do
34
+ @stack.git_path.stubs(:exist?).returns(true)
35
+ @stack.git_path.stubs(:empty?).returns(false)
36
+
37
+ command = @commands.fetch_commit(@deploy.until_commit)
38
+
39
+ assert_equal @stack.git_path.to_s, command.chdir
40
+ end
41
+
42
+ test "#fetch_commit calls git clone if repository cache do not exist" do
43
+ @stack.git_path.stubs(:exist?).returns(false)
44
+
45
+ command = @commands.fetch_commit(@deploy.until_commit)
46
+
47
+ expected = %W(git clone --quiet --single-branch --recursive --branch master #{@stack.repo_git_url} #{@stack.git_path})
48
+ assert_equal expected, command.args.map(&:to_s)
49
+ end
50
+
51
+ test "#fetch_commit calls git clone if repository cache is empty" do
52
+ @stack.git_path.stubs(:exist?).returns(true)
53
+ @stack.git_path.stubs(:empty?).returns(true)
54
+
55
+ command = @commands.fetch_commit(@deploy.until_commit)
56
+
57
+ expected = %W(git clone --quiet --single-branch --recursive --branch master #{@stack.repo_git_url} #{@stack.git_path})
58
+ assert_equal expected, command.args
59
+ end
60
+
61
+ test "#fetch_commit calls git clone if repository cache corrupt" do
62
+ @stack.git_path.stubs(:exist?).returns(true)
63
+ @stack.git_path.stubs(:empty?).returns(false)
64
+ StackCommands.any_instance.expects(:git_cmd_succeeds?)
65
+ .with(@stack.git_path)
66
+ .returns(false)
67
+
68
+ command = @commands.fetch_commit(@deploy.until_commit)
69
+
70
+ expected = %W(git clone --quiet --single-branch --recursive --branch master #{@stack.repo_git_url} #{@stack.git_path})
71
+ assert_equal expected, command.args
72
+ end
73
+
74
+ test "#fetch_commit clears a corrupted git stash before cloning" do
75
+ @stack.expects(:clear_git_cache!)
76
+ @stack.git_path.stubs(:exist?).returns(true)
77
+ @stack.git_path.stubs(:empty?).returns(false)
78
+ StackCommands.any_instance.expects(:git_cmd_succeeds?)
79
+ .with(@stack.git_path)
80
+ .returns(false)
81
+
82
+ command = @commands.fetch_commit(@deploy.until_commit)
83
+
84
+ expected = %W(git clone --quiet --single-branch --recursive --branch master #{@stack.repo_git_url} #{@stack.git_path})
85
+ assert_equal expected, command.args
86
+ end
87
+
88
+ test "#fetch_commit does not use --single-branch if git is outdated" do
89
+ @stack.git_path.stubs(:exist?).returns(false)
90
+ StackCommands.stubs(git_version: Gem::Version.new('1.7.2.30'))
91
+
92
+ command = @commands.fetch_commit(@deploy.until_commit)
93
+
94
+ expected = %W(git clone --quiet --recursive --branch master #{@stack.repo_git_url} #{@stack.git_path})
95
+ assert_equal expected, command.args.map(&:to_s)
96
+ end
97
+
98
+ test "#fetch_commit calls git fetch in base_path directory if repository cache do not exist" do
99
+ @stack.git_path.stubs(:exist?).returns(false)
100
+
101
+ command = @commands.fetch_commit(@deploy.until_commit)
102
+
103
+ assert_equal @stack.deploys_path.to_s, command.chdir
104
+ end
105
+
106
+ test "#fetch_commit merges Shipit.env in ENVIRONMENT" do
107
+ Shipit.stubs(:env).returns("SPECIFIC_CONFIG" => 5)
108
+ command = @commands.fetch_commit(@deploy.until_commit)
109
+ assert_equal '5', command.env["SPECIFIC_CONFIG"]
110
+ end
111
+
112
+ test "#env uses the correct Github token for a stack" do
113
+ Shipit.github(organization: 'shopify').stubs(:token).returns('aS3cr3Tt0kEn')
114
+ command = @commands.fetch_commit(@deploy.until_commit)
115
+ assert_equal 'aS3cr3Tt0kEn', command.env["GITHUB_TOKEN"]
116
+ end
117
+
24
118
  test "#fetch calls git fetch if repository cache already exist" do
25
119
  @stack.git_path.stubs(:exist?).returns(true)
26
120
  @stack.git_path.stubs(:empty?).returns(false)
@@ -109,12 +203,6 @@ module Shipit
109
203
  assert_equal '5', command.env["SPECIFIC_CONFIG"]
110
204
  end
111
205
 
112
- test "#env uses the correct Github token for a stack" do
113
- Shipit.github(organization: 'shopify').stubs(:token).returns('aS3cr3Tt0kEn')
114
- command = @commands.fetch
115
- assert_equal 'aS3cr3Tt0kEn', command.env["GITHUB_TOKEN"]
116
- end
117
-
118
206
  test "#clone clones the repository cache into the working directory" do
119
207
  commands = @commands.clone
120
208
  assert_equal 2, commands.size
@@ -202,7 +202,7 @@ module Shipit
202
202
  end
203
203
 
204
204
  def default_config
205
- Rails.application.secrets.github.deep_dup
205
+ Rails.application.credentials.github.deep_dup
206
206
  end
207
207
  end
208
208
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: shipit-engine
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.37.0
4
+ version: 0.39.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jean Boussier
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-08-10 00:00:00.000000000 Z
11
+ date: 2024-04-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: active_model_serializers
@@ -156,14 +156,14 @@ dependencies:
156
156
  requirements:
157
157
  - - "~>"
158
158
  - !ruby/object:Gem::Version
159
- version: '4.20'
159
+ version: 5.6.0
160
160
  type: :runtime
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
164
  - - "~>"
165
165
  - !ruby/object:Gem::Version
166
- version: '4.20'
166
+ version: 5.6.0
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: omniauth-github
169
169
  requirement: !ruby/object:Gem::Requirement
@@ -198,14 +198,14 @@ dependencies:
198
198
  requirements:
199
199
  - - "~>"
200
200
  - !ruby/object:Gem::Version
201
- version: 7.0.0
201
+ version: 7.1.1
202
202
  type: :runtime
203
203
  prerelease: false
204
204
  version_requirements: !ruby/object:Gem::Requirement
205
205
  requirements:
206
206
  - - "~>"
207
207
  - !ruby/object:Gem::Version
208
- version: 7.0.0
208
+ version: 7.1.1
209
209
  - !ruby/object:Gem::Dependency
210
210
  name: rails-timeago
211
211
  requirement: !ruby/object:Gem::Requirement
@@ -507,6 +507,7 @@ files:
507
507
  - app/controllers/shipit/status_controller.rb
508
508
  - app/controllers/shipit/tasks_controller.rb
509
509
  - app/controllers/shipit/webhooks_controller.rb
510
+ - app/helpers/shipit/api_clients_helper.rb
510
511
  - app/helpers/shipit/chunks_helper.rb
511
512
  - app/helpers/shipit/deploys_helper.rb
512
513
  - app/helpers/shipit/github_url_helper.rb
@@ -771,6 +772,7 @@ files:
771
772
  - db/migrate/20210504200438_add_github_updated_at_to_check_runs.rb
772
773
  - db/migrate/20210823075617_change_check_runs_github_updated_at_default.rb
773
774
  - db/migrate/20211103154121_increase_github_team_slug_size.rb
775
+ - db/migrate/20230703181143_change_commit_deployment_statuses_github_id_to_big_int.rb
774
776
  - lib/shipit-engine.rb
775
777
  - lib/shipit.rb
776
778
  - lib/shipit/cast_value.rb
@@ -876,6 +878,8 @@ files:
876
878
  - test/dummy/config/initializers/wrap_parameters.rb
877
879
  - test/dummy/config/locales/en.yml
878
880
  - test/dummy/config/routes.rb
881
+ - test/dummy/config/secrets.development.json
882
+ - test/dummy/config/secrets.test.json
879
883
  - test/dummy/config/secrets.yml
880
884
  - test/dummy/config/secrets_double_github_app.yml
881
885
  - test/dummy/db/schema.rb
@@ -972,7 +976,7 @@ files:
972
976
  - test/models/shipit/review_stack_provision_status_test.rb
973
977
  - test/models/shipit/review_stack_provisioning_queue_test.rb
974
978
  - test/models/shipit/review_stack_test.rb
975
- - test/models/shipit/stacks_test.rb
979
+ - test/models/shipit/stack_test.rb
976
980
  - test/models/shipit/webhooks/handlers/pull_request/assigned_handler_test.rb
977
981
  - test/models/shipit/webhooks/handlers/pull_request/closed_handler_test.rb
978
982
  - test/models/shipit/webhooks/handlers/pull_request/edited_handler_test.rb
@@ -1039,7 +1043,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1039
1043
  - !ruby/object:Gem::Version
1040
1044
  version: '0'
1041
1045
  requirements: []
1042
- rubygems_version: 3.3.3
1046
+ rubygems_version: 3.5.7
1043
1047
  signing_key:
1044
1048
  specification_version: 4
1045
1049
  summary: Application deployment software
@@ -1102,6 +1106,8 @@ test_files:
1102
1106
  - test/dummy/config/initializers/wrap_parameters.rb
1103
1107
  - test/dummy/config/locales/en.yml
1104
1108
  - test/dummy/config/routes.rb
1109
+ - test/dummy/config/secrets.development.json
1110
+ - test/dummy/config/secrets.test.json
1105
1111
  - test/dummy/config/secrets.yml
1106
1112
  - test/dummy/config/secrets_double_github_app.yml
1107
1113
  - test/dummy/config.ru
@@ -1199,7 +1205,7 @@ test_files:
1199
1205
  - test/models/shipit/review_stack_provision_status_test.rb
1200
1206
  - test/models/shipit/review_stack_provisioning_queue_test.rb
1201
1207
  - test/models/shipit/review_stack_test.rb
1202
- - test/models/shipit/stacks_test.rb
1208
+ - test/models/shipit/stack_test.rb
1203
1209
  - test/models/shipit/webhooks/handlers/pull_request/assigned_handler_test.rb
1204
1210
  - test/models/shipit/webhooks/handlers/pull_request/closed_handler_test.rb
1205
1211
  - test/models/shipit/webhooks/handlers/pull_request/edited_handler_test.rb