shipit-engine 0.45.1 → 0.45.3
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 +4 -4
- data/app/controllers/shipit/api/stacks_controller.rb +6 -1
- data/app/controllers/shipit/api_clients_controller.rb +3 -1
- data/app/controllers/shipit/stacks_controller.rb +6 -1
- data/app/jobs/shipit/cache_deploy_spec_job.rb +13 -1
- data/app/jobs/shipit/create_on_github_job.rb +11 -0
- data/app/jobs/shipit/github_sync_job.rb +14 -0
- data/app/models/shipit/deploy_spec/file_system.rb +17 -11
- data/app/models/shipit/stack.rb +8 -2
- data/app/views/shipit/api_clients/show.html.erb +1 -0
- data/lib/shipit/version.rb +1 -1
- data/test/controllers/api/stacks_controller_test.rb +2 -2
- data/test/controllers/stacks_controller_test.rb +1 -1
- data/test/jobs/cache_deploy_spec_job_test.rb +57 -1
- data/test/jobs/github_sync_job_test.rb +44 -2
- data/test/jobs/perform_task_job_test.rb +3 -3
- data/test/jobs/shipit/create_on_github_job_test.rb +29 -0
- data/test/models/shipit/stack_test.rb +32 -0
- data/vendor/assets/javascripts/clusterize.js +15 -1
- metadata +4 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: afae76c5544a76b67f5b809fcd76784ba9a24cdbfe2a38d3b6ac646e618e535a
|
|
4
|
+
data.tar.gz: f7756ed9a71bfb8c9b138206ea830a8d0d972e7e5cd3284b2b7a880afdb7112b
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 45ad16450ce9f7f4cd94af2f109362b9da7fa74a02b54b017098f615c647711681c8b8f2ebc44b0bef6f8e5e03d0d415faf05191d377c6af8aab6e8cefe08b01
|
|
7
|
+
data.tar.gz: 881b0fb03c78cd01d7c25e8de9cf9421e74cb7abbd7855ecb8b7de5024364323b8ba531362c083d3019fa60dbd2075b34fd0fba2aa6e3141d10b7ce21ae6324d
|
|
@@ -69,7 +69,12 @@ module Shipit
|
|
|
69
69
|
def refresh
|
|
70
70
|
RefreshStatusesJob.perform_later(stack_id: stack.id)
|
|
71
71
|
RefreshCheckRunsJob.perform_later(stack_id: stack.id)
|
|
72
|
-
|
|
72
|
+
# force_spec_cache: explicit refreshes always recompute the cached deploy
|
|
73
|
+
# spec, even when the head hasn't moved: refreshing is how a stale or
|
|
74
|
+
# broken cached spec is fixed. Threading it through the sync job (rather
|
|
75
|
+
# than enqueuing CacheDeploySpecJob directly) guarantees the spec is
|
|
76
|
+
# computed from the post-sync head.
|
|
77
|
+
GithubSyncJob.perform_later(stack_id: stack.id, force_spec_cache: true)
|
|
73
78
|
render_resource(stack, status: :accepted)
|
|
74
79
|
end
|
|
75
80
|
|
|
@@ -43,7 +43,9 @@ module Shipit
|
|
|
43
43
|
end
|
|
44
44
|
|
|
45
45
|
def update_params
|
|
46
|
-
params.require(:api_client).permit(permissions: [])
|
|
46
|
+
permitted = params.require(:api_client).permit(permissions: [])
|
|
47
|
+
permitted[:permissions] = permitted[:permissions].reject(&:blank?)
|
|
48
|
+
permitted
|
|
47
49
|
end
|
|
48
50
|
end
|
|
49
51
|
end
|
|
@@ -94,7 +94,12 @@ module Shipit
|
|
|
94
94
|
def refresh
|
|
95
95
|
RefreshStatusesJob.perform_later(stack_id: @stack.id)
|
|
96
96
|
RefreshCheckRunsJob.perform_later(stack_id: @stack.id)
|
|
97
|
-
|
|
97
|
+
# force_spec_cache: explicit refreshes always recompute the cached deploy
|
|
98
|
+
# spec, even when the head hasn't moved: refreshing is how a stale or
|
|
99
|
+
# broken cached spec is fixed. Threading it through the sync job (rather
|
|
100
|
+
# than enqueuing CacheDeploySpecJob directly) guarantees the spec is
|
|
101
|
+
# computed from the post-sync head.
|
|
102
|
+
GithubSyncJob.perform_later(stack_id: @stack.id, force_spec_cache: true)
|
|
98
103
|
flash[:success] = 'Refresh scheduled'
|
|
99
104
|
redirect_to(request.referer.presence || stack_path(@stack))
|
|
100
105
|
end
|
|
@@ -7,13 +7,25 @@ module Shipit
|
|
|
7
7
|
|
|
8
8
|
queue_as :deploys
|
|
9
9
|
|
|
10
|
+
# Caps job execution AND sets the dedupe lock expiration to match.
|
|
11
|
+
# Without it the lock falls back to Unique::DEFAULT_TIMEOUT (10s), which is
|
|
12
|
+
# far shorter than the job's runtime, letting duplicate jobs for the same
|
|
13
|
+
# stack run concurrently once the lock expires mid-run.
|
|
14
|
+
self.timeout = 15.minutes.to_i
|
|
15
|
+
|
|
10
16
|
def perform(stack)
|
|
11
17
|
return if stack.inaccessible?
|
|
12
18
|
|
|
19
|
+
commit = stack.commits.reachable.last
|
|
13
20
|
commands = Commands.for(stack)
|
|
14
|
-
commands.with_temporary_working_directory(commit:
|
|
21
|
+
commands.with_temporary_working_directory(commit:, recursive: false) do |path|
|
|
15
22
|
stack.update!(cached_deploy_spec: DeploySpec::FileSystem.new(path, stack))
|
|
16
23
|
end
|
|
24
|
+
|
|
25
|
+
# A duplicate enqueued while this job held the dedupe lock was dropped;
|
|
26
|
+
# if the head moved under us, that dropped job's work is still
|
|
27
|
+
# outstanding, so hand it off rather than leaving the spec stale.
|
|
28
|
+
CacheDeploySpecJob.perform_later(stack) if stack.commits.reachable.last&.id != commit&.id
|
|
17
29
|
end
|
|
18
30
|
end
|
|
19
31
|
end
|
|
@@ -7,6 +7,17 @@ module Shipit
|
|
|
7
7
|
queue_as :default
|
|
8
8
|
on_duplicate :drop
|
|
9
9
|
|
|
10
|
+
# Transient Octokit::Unauthorized = GitHub installation-token propagation lag.
|
|
11
|
+
# attempts: 14 (~24h) outlasts the 50m token cache (GITHUB_TOKEN_RAILS_CACHE_LIFETIME).
|
|
12
|
+
# No token eviction here to avoid a remint storm across workers.
|
|
13
|
+
retry_on Octokit::Unauthorized, wait: :polynomially_longer, attempts: 14 do |job, exception|
|
|
14
|
+
record = job.arguments.first
|
|
15
|
+
Rails.logger.warn(
|
|
16
|
+
"[CreateOnGithubJob] Giving up on #{record.class.name} #{record.id} " \
|
|
17
|
+
"after GitHub authentication failures: #{exception.class} #{exception.message}"
|
|
18
|
+
)
|
|
19
|
+
end
|
|
20
|
+
|
|
10
21
|
# We observe that some objects regularly take longer than the default 10 seconds to create, e.g. deployments
|
|
11
22
|
self.timeout = 40
|
|
12
23
|
self.lock_timeout = 20
|
|
@@ -19,6 +19,8 @@ module Shipit
|
|
|
19
19
|
@stack = Stack.find(params[:stack_id])
|
|
20
20
|
expected_head_sha = params[:expected_head_sha]
|
|
21
21
|
retry_count = params[:retry_count] || 0
|
|
22
|
+
head_before_sync = spec_cache_target
|
|
23
|
+
appended_commits = []
|
|
22
24
|
|
|
23
25
|
handle_github_errors do
|
|
24
26
|
new_commits, shared_parent = fetch_missing_commits { stack.github_commits }
|
|
@@ -38,6 +40,11 @@ module Shipit
|
|
|
38
40
|
stack.lock_reverted_commits! if appended_commits.any?(&:revert?)
|
|
39
41
|
end
|
|
40
42
|
end
|
|
43
|
+
sync_changed_nothing = appended_commits.empty? &&
|
|
44
|
+
spec_cache_target == head_before_sync &&
|
|
45
|
+
stack.cached_deploy_spec.present?
|
|
46
|
+
return if sync_changed_nothing && !params[:force_spec_cache]
|
|
47
|
+
|
|
41
48
|
CacheDeploySpecJob.perform_later(stack)
|
|
42
49
|
end
|
|
43
50
|
|
|
@@ -63,6 +70,13 @@ module Shipit
|
|
|
63
70
|
|
|
64
71
|
protected
|
|
65
72
|
|
|
73
|
+
# The commit CacheDeploySpecJob would check out: the newest reachable one.
|
|
74
|
+
# If it didn't change during the sync (no appends, no detaches), the cached
|
|
75
|
+
# spec is still accurate and doesn't need to be recomputed.
|
|
76
|
+
def spec_cache_target
|
|
77
|
+
stack.commits.reachable.last&.sha
|
|
78
|
+
end
|
|
79
|
+
|
|
66
80
|
def handle_github_errors
|
|
67
81
|
yield
|
|
68
82
|
rescue Octokit::NotFound
|
|
@@ -106,24 +106,30 @@ module Shipit
|
|
|
106
106
|
build_config(config_file_path, config_obj)
|
|
107
107
|
end
|
|
108
108
|
|
|
109
|
+
YAML_EXTENSIONS = ["yml", "yaml"].freeze
|
|
110
|
+
|
|
109
111
|
def shipit_file_names_in_priority_order
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
112
|
+
YAML_EXTENSIONS.flat_map do |ext|
|
|
113
|
+
[
|
|
114
|
+
"#{app_name}.#{@env}.#{ext}",
|
|
115
|
+
".shipit/#{app_name}.#{@env}.#{ext}",
|
|
113
116
|
|
|
114
|
-
|
|
115
|
-
|
|
117
|
+
"#{app_name}.#{ext}",
|
|
118
|
+
".shipit/#{app_name}.#{ext}",
|
|
116
119
|
|
|
117
|
-
|
|
118
|
-
|
|
120
|
+
"shipit.#{@env}.#{ext}",
|
|
121
|
+
".shipit/#{@env}.#{ext}",
|
|
119
122
|
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
+
"shipit.#{ext}",
|
|
124
|
+
".shipit/shipit.#{ext}"
|
|
125
|
+
]
|
|
126
|
+
end.uniq
|
|
123
127
|
end
|
|
124
128
|
|
|
125
129
|
def bare_shipit_filenames
|
|
126
|
-
|
|
130
|
+
YAML_EXTENSIONS.flat_map do |ext|
|
|
131
|
+
["#{app_name}.#{ext}", "shipit.#{ext}", ".shipit/#{app_name}.#{ext}", ".shipit/shipit.#{ext}"]
|
|
132
|
+
end.uniq
|
|
127
133
|
end
|
|
128
134
|
|
|
129
135
|
def config_file_path
|
data/app/models/shipit/stack.rb
CHANGED
|
@@ -117,11 +117,17 @@ module Shipit
|
|
|
117
117
|
)
|
|
118
118
|
|
|
119
119
|
def self.refresh_deployed_revisions
|
|
120
|
-
|
|
120
|
+
# where.not avoids deserializing every stack's cached_deploy_spec each
|
|
121
|
+
# minute: a stack without a cached spec cannot have fetch steps.
|
|
122
|
+
not_archived
|
|
123
|
+
.where.not(cached_deploy_spec: nil)
|
|
124
|
+
.find_each
|
|
125
|
+
.select(&:supports_fetch_deployed_revision?)
|
|
126
|
+
.each(&:async_refresh_deployed_revision)
|
|
121
127
|
end
|
|
122
128
|
|
|
123
129
|
def self.schedule_continuous_delivery
|
|
124
|
-
where(continuous_deployment: true).find_each do |stack|
|
|
130
|
+
not_archived.where(continuous_deployment: true).find_each do |stack|
|
|
125
131
|
ContinuousDeliveryJob.perform_later(stack)
|
|
126
132
|
end
|
|
127
133
|
end
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
<section>
|
|
18
18
|
<%= form_for @api_client, url: api_client_path(@api_client) do |f| %>
|
|
19
19
|
<h3> Permissions </h3>
|
|
20
|
+
<%= hidden_field_tag 'api_client[permissions][]', '' %>
|
|
20
21
|
<ul class="deploy-checklist">
|
|
21
22
|
<% Shipit::ApiClient::PERMISSIONS.each do |permission| %>
|
|
22
23
|
<li class="deploy-checklist__item">
|
data/lib/shipit/version.rb
CHANGED
|
@@ -260,8 +260,8 @@ module Shipit
|
|
|
260
260
|
assert_json 'message', 'This operation requires the `write:stack` permission'
|
|
261
261
|
end
|
|
262
262
|
|
|
263
|
-
test "#refresh queues a GithubSyncJob" do
|
|
264
|
-
assert_enqueued_with(job: GithubSyncJob, args: [stack_id: @stack.id]) do
|
|
263
|
+
test "#refresh queues a GithubSyncJob with force_spec_cache" do
|
|
264
|
+
assert_enqueued_with(job: GithubSyncJob, args: [stack_id: @stack.id, force_spec_cache: true]) do
|
|
265
265
|
post :refresh, params: { id: @stack.to_param }
|
|
266
266
|
end
|
|
267
267
|
assert_response :accepted
|
|
@@ -204,7 +204,7 @@ module Shipit
|
|
|
204
204
|
|
|
205
205
|
assert_enqueued_with(job: RefreshStatusesJob, args: [stack_id: @stack.id]) do
|
|
206
206
|
assert_enqueued_with(job: RefreshCheckRunsJob, args: [stack_id: @stack.id]) do
|
|
207
|
-
assert_enqueued_with(job: GithubSyncJob, args: [stack_id: @stack.id]) do
|
|
207
|
+
assert_enqueued_with(job: GithubSyncJob, args: [stack_id: @stack.id, force_spec_cache: true]) do
|
|
208
208
|
post :refresh, params: { id: @stack.to_param }
|
|
209
209
|
end
|
|
210
210
|
end
|
|
@@ -14,11 +14,67 @@ module Shipit
|
|
|
14
14
|
@stack.update!(cached_deploy_spec: DeploySpec.new('review' => { 'checklist' => %w[foo bar] }))
|
|
15
15
|
|
|
16
16
|
dir = Pathname(Dir.tmpdir)
|
|
17
|
-
StackCommands.any_instance.expects(:with_temporary_working_directory)
|
|
17
|
+
StackCommands.any_instance.expects(:with_temporary_working_directory)
|
|
18
|
+
.with(commit: @last_commit, recursive: false).yields(dir)
|
|
18
19
|
|
|
19
20
|
assert_equal %w[foo bar], @stack.checklist
|
|
20
21
|
@job.perform(@stack)
|
|
21
22
|
assert_equal [], @stack.reload.checklist
|
|
22
23
|
end
|
|
24
|
+
|
|
25
|
+
test "the dedupe lock expiration covers the job runtime" do
|
|
26
|
+
assert_operator CacheDeploySpecJob.timeout, :>, BackgroundJob::Unique::DEFAULT_TIMEOUT
|
|
27
|
+
assert_equal 15.minutes.to_i, CacheDeploySpecJob.timeout
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
test "the redis lock is created with the job timeout as its expiration" do
|
|
31
|
+
mutex = mock
|
|
32
|
+
mutex.expects(:lock).yields
|
|
33
|
+
Redis::Lock.expects(:new)
|
|
34
|
+
.with(anything, anything, expiration: 15.minutes.to_i, timeout: 0)
|
|
35
|
+
.returns(mutex)
|
|
36
|
+
|
|
37
|
+
executed = false
|
|
38
|
+
CacheDeploySpecJob.new(@stack).acquire_lock { executed = true }
|
|
39
|
+
assert executed
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
test "#perform re-enqueues itself when the head moves during the run" do
|
|
43
|
+
moved_head = @stack.commits.reachable.first
|
|
44
|
+
reachable = mock
|
|
45
|
+
reachable.stubs(:last).returns(@last_commit, moved_head)
|
|
46
|
+
@stack.stubs(:commits).returns(stub(reachable:))
|
|
47
|
+
@stack.stubs(:update!) # side-effect callbacks are irrelevant to this test
|
|
48
|
+
|
|
49
|
+
StackCommands.any_instance.expects(:with_temporary_working_directory)
|
|
50
|
+
.with(commit: @last_commit, recursive: false).yields(Pathname(Dir.tmpdir))
|
|
51
|
+
|
|
52
|
+
assert_enqueued_with(job: CacheDeploySpecJob, args: [@stack]) do
|
|
53
|
+
@job.perform(@stack)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
test "#perform does not re-enqueue itself when the head is unchanged" do
|
|
58
|
+
StackCommands.any_instance.expects(:with_temporary_working_directory)
|
|
59
|
+
.with(commit: @last_commit, recursive: false).yields(Pathname(Dir.tmpdir))
|
|
60
|
+
|
|
61
|
+
assert_no_enqueued_jobs(only: CacheDeploySpecJob) do
|
|
62
|
+
@job.perform(@stack)
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
test "a duplicate job for the same stack is dropped while the lock is held" do
|
|
67
|
+
job = CacheDeploySpecJob.new(@stack)
|
|
68
|
+
duplicate = CacheDeploySpecJob.new(@stack)
|
|
69
|
+
duplicate_ran = false
|
|
70
|
+
|
|
71
|
+
job.acquire_lock do
|
|
72
|
+
duplicate.acquire_lock do
|
|
73
|
+
duplicate_ran = true
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
refute duplicate_ran, "duplicate should have been dropped, not executed"
|
|
78
|
+
end
|
|
23
79
|
end
|
|
24
80
|
end
|
|
@@ -16,10 +16,50 @@ module Shipit
|
|
|
16
16
|
@job.perform(stack_id: @stack.id)
|
|
17
17
|
end
|
|
18
18
|
|
|
19
|
-
test "#perform
|
|
19
|
+
test "#perform does not enqueue a CacheDeploySpecJob when the sync found nothing new" do
|
|
20
|
+
Stack.any_instance.stubs(:github_commits).returns(@github_commits)
|
|
21
|
+
@job.stubs(:fetch_missing_commits).yields.returns([[], nil])
|
|
22
|
+
|
|
23
|
+
assert_no_enqueued_jobs(only: CacheDeploySpecJob) do
|
|
24
|
+
@job.perform(stack_id: @stack.id)
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
test "#perform enqueues a CacheDeploySpecJob when the cached spec is missing" do
|
|
29
|
+
@stack.update!(cached_deploy_spec: nil)
|
|
30
|
+
Stack.any_instance.stubs(:github_commits).returns(@github_commits)
|
|
31
|
+
@job.stubs(:fetch_missing_commits).yields.returns([[], nil])
|
|
32
|
+
|
|
33
|
+
assert_enqueued_with(job: CacheDeploySpecJob, args: [@stack]) do
|
|
34
|
+
@job.perform(stack_id: @stack.id)
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
test "#perform enqueues a CacheDeploySpecJob when nothing changed but force_spec_cache is set" do
|
|
20
39
|
Stack.any_instance.stubs(:github_commits).returns(@github_commits)
|
|
21
40
|
@job.stubs(:fetch_missing_commits).yields.returns([[], nil])
|
|
22
41
|
|
|
42
|
+
assert_enqueued_with(job: CacheDeploySpecJob, args: [@stack]) do
|
|
43
|
+
@job.perform(stack_id: @stack.id, force_spec_cache: true)
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
test "#perform preserves force_spec_cache across eventual-consistency retries" do
|
|
48
|
+
expected_sha = "abcd1234"
|
|
49
|
+
Stack.any_instance.expects(:github_commits).returns(@github_commits)
|
|
50
|
+
@job.expects(:fetch_missing_commits).yields.returns([[], nil])
|
|
51
|
+
@job.expects(:commit_exists?).with(expected_sha).returns(false)
|
|
52
|
+
|
|
53
|
+
expected_args = { stack_id: @stack.id, expected_head_sha: expected_sha, force_spec_cache: true, retry_count: 1 }
|
|
54
|
+
assert_enqueued_with(job: GithubSyncJob, args: [expected_args]) do
|
|
55
|
+
@job.perform(stack_id: @stack.id, expected_head_sha: expected_sha, force_spec_cache: true)
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
test "#perform enqueues a CacheDeploySpecJob when commits are detached without new commits" do
|
|
60
|
+
Stack.any_instance.stubs(:github_commits).returns(@github_commits)
|
|
61
|
+
@job.stubs(:fetch_missing_commits).yields.returns([[], shipit_commits(:third)])
|
|
62
|
+
|
|
23
63
|
assert_enqueued_with(job: CacheDeploySpecJob, args: [@stack]) do
|
|
24
64
|
@job.perform(stack_id: @stack.id)
|
|
25
65
|
end
|
|
@@ -155,7 +195,9 @@ module Shipit
|
|
|
155
195
|
@job.expects(:fetch_missing_commits).yields.returns([[], nil])
|
|
156
196
|
@job.expects(:commit_exists?).with(expected_sha).returns(true)
|
|
157
197
|
|
|
158
|
-
|
|
198
|
+
# No retry is scheduled, and since the sync found nothing new,
|
|
199
|
+
# no spec re-cache is needed either.
|
|
200
|
+
assert_no_enqueued_jobs(only: [GithubSyncJob, CacheDeploySpecJob]) do
|
|
159
201
|
@job.perform(stack_id: @stack.id, expected_head_sha: expected_sha)
|
|
160
202
|
end
|
|
161
203
|
end
|
|
@@ -107,7 +107,7 @@ module Shipit
|
|
|
107
107
|
end
|
|
108
108
|
|
|
109
109
|
test "mark deploy as error an unexpected exception is raised" do
|
|
110
|
-
|
|
110
|
+
Shipit::TaskExecutionStrategy::Default.any_instance.expects(:capture!).at_least_once.raises(Command::Denied)
|
|
111
111
|
|
|
112
112
|
@job.perform(@deploy)
|
|
113
113
|
|
|
@@ -116,7 +116,7 @@ module Shipit
|
|
|
116
116
|
end
|
|
117
117
|
|
|
118
118
|
test "mark deploy as timedout if a command timeout" do
|
|
119
|
-
|
|
119
|
+
Shipit::TaskExecutionStrategy::Default.any_instance.expects(:capture!).at_least_once.raises(Command::TimedOut)
|
|
120
120
|
|
|
121
121
|
@job.perform(@deploy)
|
|
122
122
|
|
|
@@ -129,7 +129,7 @@ module Shipit
|
|
|
129
129
|
begin
|
|
130
130
|
Shipit.timeout_exit_codes = [70].freeze
|
|
131
131
|
|
|
132
|
-
|
|
132
|
+
Shipit::TaskExecutionStrategy::Default.any_instance.expects(:capture!).at_least_once.raises(Command::Failed.new('Blah', 70))
|
|
133
133
|
|
|
134
134
|
@job.perform(@deploy)
|
|
135
135
|
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'test_helper'
|
|
4
|
+
|
|
5
|
+
module Shipit
|
|
6
|
+
class CreateOnGithubJobTest < ActiveSupport::TestCase
|
|
7
|
+
setup do
|
|
8
|
+
@deployment = shipit_commit_deployments(:shipit_pending_fourth)
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
test "#perform retries on GitHub authentication errors" do
|
|
12
|
+
CommitDeployment.any_instance.stubs(:create_on_github!).raises(Octokit::Unauthorized)
|
|
13
|
+
|
|
14
|
+
assert_enqueued_with(job: CreateOnGithubJob) do
|
|
15
|
+
CreateOnGithubJob.perform_now(@deployment)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
test "#perform gives up without re-raising after exhausting authentication retries" do
|
|
20
|
+
CommitDeployment.any_instance.stubs(:create_on_github!).raises(Octokit::Unauthorized)
|
|
21
|
+
Rails.logger.stubs(:warn)
|
|
22
|
+
|
|
23
|
+
job = CreateOnGithubJob.new(@deployment)
|
|
24
|
+
job.exception_executions = { "[Octokit::Unauthorized]" => 13 }
|
|
25
|
+
|
|
26
|
+
assert_nothing_raised { job.perform_now }
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
@@ -11,6 +11,38 @@ module Shipit
|
|
|
11
11
|
GithubHook.any_instance.stubs(:teardown!)
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
+
test ".schedule_continuous_delivery skips archived stacks" do
|
|
15
|
+
archived = shipit_stacks(:archived_6hours_ago)
|
|
16
|
+
archived.update!(continuous_deployment: true)
|
|
17
|
+
@stack.update!(continuous_deployment: true)
|
|
18
|
+
|
|
19
|
+
Stack.schedule_continuous_delivery
|
|
20
|
+
|
|
21
|
+
enqueued_args = enqueued_jobs
|
|
22
|
+
.select { |job| job[:job] == ContinuousDeliveryJob }
|
|
23
|
+
.map { |job| job[:args].to_s }
|
|
24
|
+
assert enqueued_args.any? { |args| args.include?("Stack/#{@stack.id}") },
|
|
25
|
+
"expected a ContinuousDeliveryJob for the active stack"
|
|
26
|
+
refute enqueued_args.any? { |args| args.include?("Stack/#{archived.id}") },
|
|
27
|
+
"archived stacks must not trigger continuous delivery"
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
test ".refresh_deployed_revisions skips archived stacks" do
|
|
31
|
+
archived = shipit_stacks(:archived_6hours_ago)
|
|
32
|
+
archived.update!(cached_deploy_spec: DeploySpec.new('fetch' => ['echo 1']))
|
|
33
|
+
@stack.update!(cached_deploy_spec: DeploySpec.new('fetch' => ['echo 1']))
|
|
34
|
+
|
|
35
|
+
Stack.refresh_deployed_revisions
|
|
36
|
+
|
|
37
|
+
enqueued_args = enqueued_jobs
|
|
38
|
+
.select { |job| job[:job] == FetchDeployedRevisionJob }
|
|
39
|
+
.map { |job| job[:args].to_s }
|
|
40
|
+
assert enqueued_args.any? { |args| args.include?("Stack/#{@stack.id}") },
|
|
41
|
+
"expected a FetchDeployedRevisionJob for the active stack with fetch steps"
|
|
42
|
+
refute enqueued_args.any? { |args| args.include?("Stack/#{archived.id}") },
|
|
43
|
+
"archived stacks must not refresh deployed revisions"
|
|
44
|
+
end
|
|
45
|
+
|
|
14
46
|
test "branch defaults to default branch name" do
|
|
15
47
|
@stack.branch = ""
|
|
16
48
|
Shipit.github.api.expects(:repo).with("shopify/shipit-engine").returns(
|
|
@@ -251,7 +251,12 @@
|
|
|
251
251
|
var tag = document.createElement(this.options.tag),
|
|
252
252
|
clusterize_prefix = 'clusterize-';
|
|
253
253
|
tag.className = [clusterize_prefix + 'extra-row', clusterize_prefix + class_name].join(' ');
|
|
254
|
-
|
|
254
|
+
// CSP FIX: this element is serialized to markup via outerHTML and re-parsed by
|
|
255
|
+
// innerHTML below. Under a `style-src` policy without 'unsafe-inline', the browser
|
|
256
|
+
// refuses to apply a style ATTRIBUTE that came from parsed markup, so the spacer
|
|
257
|
+
// renders at height 0 and virtual scrolling collapses. Carry the height in a data
|
|
258
|
+
// attribute instead and apply it through CSSOM after insertion, which CSP allows.
|
|
259
|
+
height && tag.setAttribute('data-clusterize-height', height);
|
|
255
260
|
return tag.outerHTML;
|
|
256
261
|
},
|
|
257
262
|
// if necessary verify data changed and insert to DOM
|
|
@@ -279,6 +284,14 @@
|
|
|
279
284
|
}
|
|
280
285
|
},
|
|
281
286
|
// unfortunately ie <= 9 does not allow to use innerHTML for table elements, so make a workaround
|
|
287
|
+
// CSP FIX: apply spacer heights via CSSOM once the nodes are live in the document.
|
|
288
|
+
applyExtraRowHeights: function() {
|
|
289
|
+
var rows = this.content_elem.getElementsByClassName('clusterize-extra-row');
|
|
290
|
+
for(var i = 0; i < rows.length; i++) {
|
|
291
|
+
var h = rows[i].getAttribute('data-clusterize-height');
|
|
292
|
+
if(h) rows[i].style.height = h + 'px';
|
|
293
|
+
}
|
|
294
|
+
},
|
|
282
295
|
html: function(data) {
|
|
283
296
|
var content_elem = this.content_elem;
|
|
284
297
|
if(ie && ie <= 9 && this.options.tag == 'tr') {
|
|
@@ -294,6 +307,7 @@
|
|
|
294
307
|
} else {
|
|
295
308
|
content_elem.innerHTML = data;
|
|
296
309
|
}
|
|
310
|
+
this.applyExtraRowHeights();
|
|
297
311
|
},
|
|
298
312
|
getChildNodes: function(tag) {
|
|
299
313
|
var child_nodes = tag.children, nodes = [];
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: shipit-engine
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.45.
|
|
4
|
+
version: 0.45.3
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Jean Boussier
|
|
@@ -918,6 +918,7 @@ files:
|
|
|
918
918
|
- test/jobs/refresh_status_job_test.rb
|
|
919
919
|
- test/jobs/shipit/background_job_test.rb
|
|
920
920
|
- test/jobs/shipit/continuous_delivery_job_test.rb
|
|
921
|
+
- test/jobs/shipit/create_on_github_job_test.rb
|
|
921
922
|
- test/jobs/unique_job_test.rb
|
|
922
923
|
- test/jobs/update_github_last_deployed_ref_job_test.rb
|
|
923
924
|
- test/lib/shipit/deploy_commands_test.rb
|
|
@@ -1018,7 +1019,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
1018
1019
|
- !ruby/object:Gem::Version
|
|
1019
1020
|
version: '0'
|
|
1020
1021
|
requirements: []
|
|
1021
|
-
rubygems_version: 4.0.
|
|
1022
|
+
rubygems_version: 4.0.19
|
|
1022
1023
|
specification_version: 4
|
|
1023
1024
|
summary: Application deployment software
|
|
1024
1025
|
test_files:
|
|
@@ -1150,6 +1151,7 @@ test_files:
|
|
|
1150
1151
|
- test/jobs/refresh_status_job_test.rb
|
|
1151
1152
|
- test/jobs/shipit/background_job_test.rb
|
|
1152
1153
|
- test/jobs/shipit/continuous_delivery_job_test.rb
|
|
1154
|
+
- test/jobs/shipit/create_on_github_job_test.rb
|
|
1153
1155
|
- test/jobs/unique_job_test.rb
|
|
1154
1156
|
- test/jobs/update_github_last_deployed_ref_job_test.rb
|
|
1155
1157
|
- test/lib/shipit/deploy_commands_test.rb
|