shipit-engine 0.32.0 → 0.35.1
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/README.md +13 -2
- data/app/assets/images/magic-solid.svg +1 -0
- data/app/assets/javascripts/shipit/repositories_search.js.coffee +60 -0
- data/app/assets/javascripts/shipit/{search.js.coffee → stack_search.js.coffee} +0 -0
- data/app/assets/stylesheets/_pages/_deploy.scss +2 -3
- data/app/assets/stylesheets/_pages/_repositories.scss +148 -0
- data/app/assets/stylesheets/_pages/_stacks.scss +19 -0
- data/app/assets/stylesheets/shipit.scss +1 -0
- data/app/controllers/shipit/api/ccmenu_controller.rb +1 -1
- data/app/controllers/shipit/api/deploys_controller.rb +2 -0
- data/app/controllers/shipit/api/{pull_requests_controller.rb → merge_requests_controller.rb} +8 -8
- data/app/controllers/shipit/api/rollbacks_controller.rb +2 -1
- data/app/controllers/shipit/api/stacks_controller.rb +15 -1
- data/app/controllers/shipit/deploys_controller.rb +1 -1
- data/app/controllers/shipit/merge_requests_controller.rb +31 -0
- data/app/controllers/shipit/merge_status_controller.rb +15 -15
- data/app/controllers/shipit/repositories_controller.rb +74 -0
- data/app/controllers/shipit/stacks_controller.rb +2 -2
- data/app/controllers/shipit/tasks_controller.rb +2 -2
- data/app/controllers/shipit/webhooks_controller.rb +23 -4
- data/app/helpers/shipit/chunks_helper.rb +2 -2
- data/app/helpers/shipit/github_url_helper.rb +8 -0
- data/app/helpers/shipit/shipit_helper.rb +0 -1
- data/app/helpers/shipit/stacks_helper.rb +4 -0
- data/app/jobs/shipit/create_on_github_job.rb +1 -0
- data/app/jobs/shipit/deliver_hook_job.rb +1 -1
- data/app/jobs/shipit/destroy_repository_job.rb +24 -0
- data/app/jobs/shipit/destroy_stack_job.rb +2 -2
- data/app/jobs/shipit/github_sync_job.rb +13 -9
- data/app/jobs/shipit/perform_task_job.rb +4 -98
- data/app/jobs/shipit/process_merge_requests_job.rb +32 -0
- data/app/jobs/shipit/refresh_merge_request_job.rb +11 -0
- data/app/jobs/shipit/update_github_last_deployed_ref_job.rb +1 -1
- data/app/models/shipit/anonymous_user.rb +10 -2
- data/app/models/shipit/check_run.rb +38 -2
- data/app/models/shipit/command_line_user.rb +4 -0
- data/app/models/shipit/commit.rb +31 -20
- data/app/models/shipit/commit_checks.rb +14 -13
- data/app/models/shipit/commit_deployment.rb +3 -3
- data/app/models/shipit/commit_deployment_status.rb +3 -3
- data/app/models/shipit/deploy.rb +17 -11
- data/app/models/shipit/deploy_spec/file_system.rb +11 -5
- data/app/models/shipit/deploy_spec/lerna_discovery.rb +12 -4
- data/app/models/shipit/deploy_spec.rb +16 -4
- data/app/models/shipit/duration.rb +2 -0
- data/app/models/shipit/hook.rb +28 -2
- data/app/models/shipit/merge_request.rb +304 -0
- data/app/models/shipit/provisioning_handler/base.rb +30 -0
- data/app/models/shipit/provisioning_handler/unregistered_provisioning_handler.rb +35 -0
- data/app/models/shipit/provisioning_handler.rb +32 -0
- data/app/models/shipit/pull_request.rb +26 -265
- data/app/models/shipit/pull_request_assignment.rb +10 -0
- data/app/models/shipit/release_status.rb +1 -1
- data/app/models/shipit/repository.rb +63 -3
- data/app/models/shipit/review_stack.rb +130 -0
- data/app/models/shipit/review_stack_provisioning_queue.rb +39 -0
- data/app/models/shipit/rollback.rb +5 -0
- data/app/models/shipit/stack.rb +78 -30
- data/app/models/shipit/status/group.rb +1 -1
- data/app/models/shipit/task.rb +62 -9
- data/app/models/shipit/task_execution_strategy/base.rb +20 -0
- data/app/models/shipit/task_execution_strategy/default.rb +109 -0
- data/app/models/shipit/team.rb +4 -2
- data/app/models/shipit/user.rb +10 -1
- data/app/models/shipit/webhooks/handlers/pull_request/assigned_handler.rb +74 -0
- data/app/models/shipit/webhooks/handlers/pull_request/closed_handler.rb +68 -0
- data/app/models/shipit/webhooks/handlers/pull_request/edited_handler.rb +74 -0
- data/app/models/shipit/webhooks/handlers/pull_request/label_capturing_handler.rb +127 -0
- data/app/models/shipit/webhooks/handlers/pull_request/labeled_handler.rb +106 -0
- data/app/models/shipit/webhooks/handlers/pull_request/opened_handler.rb +83 -0
- data/app/models/shipit/webhooks/handlers/pull_request/reopened_handler.rb +88 -0
- data/app/models/shipit/webhooks/handlers/pull_request/review_stack_adapter.rb +103 -0
- data/app/models/shipit/webhooks/handlers/pull_request/unlabeled_handler.rb +107 -0
- data/app/models/shipit/webhooks/handlers/push_handler.rb +4 -1
- data/app/models/shipit/webhooks.rb +10 -0
- data/app/serializers/shipit/deploy_serializer.rb +6 -0
- data/app/serializers/shipit/merge_request_serializer.rb +21 -0
- data/app/serializers/shipit/pull_request_serializer.rb +5 -8
- data/app/serializers/shipit/review_stack_serializer.rb +7 -0
- data/app/serializers/shipit/stack_serializer.rb +7 -6
- data/app/serializers/shipit/tail_task_serializer.rb +10 -2
- data/app/serializers/shipit/task_serializer.rb +1 -1
- data/app/validators/subset_validator.rb +1 -1
- data/app/views/layouts/merge_status.html.erb +1 -1
- data/app/views/shipit/merge_requests/_merge_request.html.erb +29 -0
- data/app/views/shipit/{pull_requests → merge_requests}/index.html.erb +2 -2
- data/app/views/shipit/merge_requests/merge_requests/_pull_request.html.erb +29 -0
- data/app/views/shipit/merge_requests/merge_requests/index.html.erb +20 -0
- data/app/views/shipit/merge_status/_merge_queue_button.html.erb +3 -3
- data/app/views/shipit/merge_status/backlogged.html.erb +1 -1
- data/app/views/shipit/merge_status/failure.html.erb +1 -1
- data/app/views/shipit/merge_status/locked.html.erb +1 -1
- data/app/views/shipit/merge_status/success.html.erb +2 -2
- data/app/views/shipit/repositories/_header.html.erb +19 -0
- data/app/views/shipit/repositories/index.html.erb +31 -0
- data/app/views/shipit/repositories/new.html.erb +23 -0
- data/app/views/shipit/repositories/settings.html.erb +53 -0
- data/app/views/shipit/repositories/show.html.erb +30 -0
- data/app/views/shipit/stacks/_banners.html.erb +15 -1
- data/app/views/shipit/stacks/_header.html.erb +5 -2
- data/app/views/shipit/stacks/_stack.html.erb +8 -0
- data/app/views/shipit/stacks/index.html.erb +2 -1
- data/app/views/shipit/stacks/new.html.erb +1 -1
- data/app/views/shipit/stacks/settings.html.erb +5 -5
- data/app/views/shipit/stacks/show.html.erb +1 -1
- data/app/views/shipit/tasks/_task_output.html.erb +1 -1
- data/config/routes.rb +15 -5
- data/config/secrets.development.example.yml +24 -0
- data/config/secrets.development.shopify.yml +20 -9
- data/db/migrate/20200706145406_add_review_stacks.rb +12 -0
- data/db/migrate/20200804144639_rename_pull_request_to_merge_request.rb +7 -0
- data/db/migrate/20200804161512_rename_commits_pull_request_id_to_merge_request_id.rb +5 -0
- data/db/migrate/20200813134712_recreate_shipit_pull_requests.rb +22 -0
- data/db/migrate/20200813194056_create_pull_request_assignments.rb +8 -0
- data/db/migrate/20201001125502_add_provision_pr_stacks_flag_to_repositories.rb +7 -0
- data/db/migrate/20201008145809_add_retry_attempt_to_tasks.rb +5 -0
- data/db/migrate/20201008152744_add_max_retries_to_tasks.rb +5 -0
- data/db/migrate/20210325194053_remove_stacks_branch_default.rb +5 -0
- data/db/migrate/20210504200438_add_github_updated_at_to_check_runs.rb +5 -0
- data/db/migrate/20210823075617_change_check_runs_github_updated_at_default.rb +5 -0
- data/lib/shipit/command.rb +7 -6
- data/lib/shipit/commands.rb +18 -5
- data/lib/shipit/engine.rb +2 -0
- data/lib/shipit/flock.rb +8 -1
- data/lib/shipit/github_app.rb +8 -6
- data/lib/shipit/octokit_iterator.rb +3 -3
- data/lib/shipit/review_stack_commands.rb +8 -0
- data/lib/shipit/simple_message_verifier.rb +2 -2
- data/lib/shipit/stack_commands.rb +36 -7
- data/lib/shipit/task_commands.rb +8 -1
- data/lib/shipit/version.rb +1 -1
- data/lib/shipit.rb +50 -16
- data/lib/snippets/publish-lerna-independent-packages +35 -34
- data/lib/snippets/publish-lerna-independent-packages-legacy +39 -0
- data/lib/tasks/cron.rake +11 -2
- data/test/controllers/api/ccmenu_controller_test.rb +1 -1
- data/test/controllers/api/deploys_controller_test.rb +17 -0
- data/test/controllers/api/{pull_requests_controller_test.rb → merge_requests_controller_test.rb} +12 -12
- data/test/controllers/api/outputs_controller_test.rb +1 -0
- data/test/controllers/api/rollback_controller_test.rb +1 -1
- data/test/controllers/api/stacks_controller_test.rb +42 -8
- data/test/controllers/{pull_requests_controller_test.rb → merge_requests_controller_test.rb} +6 -6
- data/test/controllers/repositories_controller_test.rb +71 -0
- data/test/controllers/stacks_controller_test.rb +9 -1
- data/test/controllers/tasks_controller_test.rb +14 -2
- data/test/controllers/webhooks_controller_test.rb +27 -12
- data/test/dummy/app/assets/config/manifest.js +3 -0
- data/test/dummy/config/application.rb +7 -2
- data/test/dummy/config/database.yml +9 -0
- data/test/dummy/config/environments/development.rb +1 -4
- data/test/dummy/config/environments/test.rb +0 -5
- data/test/dummy/config/secrets_double_github_app.yml +79 -0
- data/test/dummy/db/schema.rb +56 -17
- data/test/dummy/db/seeds.rb +2 -1
- data/test/fixtures/payloads/check_suite_master.json +4 -32
- data/test/fixtures/payloads/invalid_pull_request.json +117 -0
- data/test/fixtures/payloads/provision_disabled_pull_request.json +454 -0
- data/test/fixtures/payloads/pull_request_assigned.json +480 -0
- data/test/fixtures/payloads/pull_request_closed.json +454 -0
- data/test/fixtures/payloads/pull_request_labeled.json +461 -0
- data/test/fixtures/payloads/pull_request_opened.json +454 -0
- data/test/fixtures/payloads/pull_request_reopened.json +454 -0
- data/test/fixtures/payloads/pull_request_unlabeled.json +454 -0
- data/test/fixtures/payloads/pull_request_with_no_repo.json +454 -0
- data/test/fixtures/payloads/push_master.json +1 -1
- data/test/fixtures/payloads/push_not_master.json +1 -1
- data/test/fixtures/shipit/commits.yml +17 -4
- data/test/fixtures/shipit/hooks.yml +1 -0
- data/test/fixtures/shipit/merge_requests.yml +141 -0
- data/test/fixtures/shipit/pull_request_assignments.yml +3 -0
- data/test/fixtures/shipit/pull_requests.yml +10 -131
- data/test/fixtures/shipit/repositories.yml +1 -0
- data/test/fixtures/shipit/stacks.yml +145 -0
- data/test/fixtures/shipit/statuses.yml +9 -0
- data/test/fixtures/shipit/tasks.yml +4 -1
- data/test/fixtures/shipit/users.yml +7 -0
- data/test/helpers/json_helper.rb +5 -1
- data/test/helpers/payloads_helper.rb +4 -0
- data/test/jobs/chunk_rollup_job_test.rb +15 -1
- data/test/jobs/destroy_repository_job_test.rb +27 -0
- data/test/jobs/github_sync_job_test.rb +2 -1
- data/test/jobs/perform_task_job_test.rb +8 -8
- data/test/jobs/{merge_pull_requests_job_test.rb → process_merge_requests_job_test.rb} +18 -18
- data/test/lib/shipit/deploy_commands_test.rb +16 -0
- data/test/lib/shipit/task_commands_test.rb +17 -0
- data/test/models/commit_deployment_status_test.rb +3 -3
- data/test/models/commits_test.rb +24 -13
- data/test/models/deploy_spec_test.rb +64 -24
- data/test/models/deploys_test.rb +188 -14
- data/test/models/hook_test.rb +30 -1
- data/test/models/{pull_request_test.rb → merge_request_test.rb} +49 -34
- data/test/models/pull_request_assignment_test.rb +16 -0
- data/test/models/shipit/check_run_test.rb +124 -5
- data/test/models/shipit/provisioning_handler/base_test.rb +33 -0
- data/test/models/shipit/provisioning_handler/unregistered_provisioning_handler_test.rb +49 -0
- data/test/models/shipit/provisioning_handler_test.rb +64 -0
- data/test/models/shipit/pull_request_test.rb +52 -0
- data/test/models/shipit/repository_test.rb +5 -1
- data/test/models/shipit/review_stack_provision_status_test.rb +77 -0
- data/test/models/shipit/review_stack_provisioning_queue_test.rb +63 -0
- data/test/models/shipit/review_stack_test.rb +91 -0
- data/test/models/{stacks_test.rb → shipit/stacks_test.rb} +52 -8
- data/test/models/shipit/webhooks/handlers/pull_request/assigned_handler_test.rb +45 -0
- data/test/models/shipit/webhooks/handlers/pull_request/closed_handler_test.rb +192 -0
- data/test/models/shipit/webhooks/handlers/pull_request/edited_handler_test.rb +47 -0
- data/test/models/shipit/webhooks/handlers/pull_request/label_capturing_handler_test.rb +209 -0
- data/test/models/shipit/webhooks/handlers/pull_request/labeled_handler_test.rb +332 -0
- data/test/models/shipit/webhooks/handlers/pull_request/opened_handler_test.rb +238 -0
- data/test/models/shipit/webhooks/handlers/pull_request/reopened_handler_test.rb +282 -0
- data/test/models/shipit/webhooks/handlers/pull_request/review_stack_adapter_test.rb +107 -0
- data/test/models/shipit/webhooks/handlers/pull_request/unlabeled_handler_test.rb +324 -0
- data/test/models/shipit/{wehbooks → webhooks}/handlers_test.rb +0 -0
- data/test/models/tasks_test.rb +66 -3
- data/test/serializers/shipit/pull_request_serializer_test.rb +29 -0
- data/test/test_helper.rb +15 -0
- data/test/unit/anonymous_user_serializer_test.rb +1 -1
- data/test/unit/command_test.rb +8 -3
- data/test/unit/commit_serializer_test.rb +1 -1
- data/test/unit/deploy_commands_test.rb +73 -17
- data/test/unit/deploy_serializer_test.rb +1 -1
- data/test/unit/github_app_test.rb +2 -3
- data/test/unit/github_apps_test.rb +416 -0
- data/test/unit/github_url_helper_test.rb +5 -0
- data/test/unit/shipit_deployment_checks_test.rb +77 -0
- data/test/unit/shipit_task_execution_strategy_test.rb +47 -0
- data/test/unit/shipit_test.rb +14 -0
- data/test/unit/user_serializer_test.rb +1 -1
- metadata +306 -188
- data/app/controllers/shipit/pull_requests_controller.rb +0 -31
- data/app/jobs/shipit/merge_pull_requests_job.rb +0 -32
- data/app/jobs/shipit/refresh_pull_request_job.rb +0 -11
- data/app/views/shipit/pull_requests/_pull_request.html.erb +0 -29
- data/test/fixtures/shipit/output_chunks.yml +0 -47
- data/test/models/output_chunk_test.rb +0 -21
|
@@ -31,7 +31,7 @@ module Shipit
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
delegate :pending?, :success?, :error?, :failure?, :unknown?, :missing?, :state, :simple_state,
|
|
34
|
-
|
|
34
|
+
to: :significant_status
|
|
35
35
|
delegate :each, :size, :map, to: :statuses
|
|
36
36
|
delegate :required_statuses, to: :commit
|
|
37
37
|
|
data/app/models/shipit/task.rb
CHANGED
|
@@ -27,8 +27,6 @@ module Shipit
|
|
|
27
27
|
|
|
28
28
|
deferred_touch stack: :updated_at
|
|
29
29
|
|
|
30
|
-
has_many :chunks, -> { order(:id) }, class_name: 'OutputChunk', dependent: :delete_all, inverse_of: :task
|
|
31
|
-
|
|
32
30
|
serialize :definition, TaskDefinition
|
|
33
31
|
serialize :env, Hash
|
|
34
32
|
|
|
@@ -41,7 +39,7 @@ module Shipit
|
|
|
41
39
|
scope :last_seven_days, -> { where("created_at > ?", 7.days.ago) }
|
|
42
40
|
scope :previous_seven_days, -> { where(created_at: 14.days.ago..7.days.ago) }
|
|
43
41
|
|
|
44
|
-
scope :due_for_rollup, -> {
|
|
42
|
+
scope :due_for_rollup, -> { not_active.where(rolled_up: false).where('created_at <= ?', 1.hour.ago) }
|
|
45
43
|
|
|
46
44
|
after_save :record_status_change
|
|
47
45
|
after_create :prevent_concurrency, unless: :allow_concurrency?
|
|
@@ -79,6 +77,10 @@ module Shipit
|
|
|
79
77
|
task.async_refresh_deployed_revision
|
|
80
78
|
end
|
|
81
79
|
|
|
80
|
+
after_transition any => %i(aborted success failed error timedout) do |task|
|
|
81
|
+
task.schedule_rollup_chunks
|
|
82
|
+
end
|
|
83
|
+
|
|
82
84
|
after_transition any => :flapping do |task|
|
|
83
85
|
task.update!(confirmations: 0)
|
|
84
86
|
end
|
|
@@ -87,6 +89,10 @@ module Shipit
|
|
|
87
89
|
task.async_update_estimated_deploy_duration
|
|
88
90
|
end
|
|
89
91
|
|
|
92
|
+
after_transition any => %i(failed error timedout) do |task|
|
|
93
|
+
task.retry_if_necessary
|
|
94
|
+
end
|
|
95
|
+
|
|
90
96
|
event :run do
|
|
91
97
|
transition pending: :running
|
|
92
98
|
end
|
|
@@ -169,7 +175,7 @@ module Shipit
|
|
|
169
175
|
end
|
|
170
176
|
|
|
171
177
|
delegate :acquire_git_cache_lock, :async_refresh_deployed_revision, :async_update_estimated_deploy_duration,
|
|
172
|
-
|
|
178
|
+
to: :stack
|
|
173
179
|
|
|
174
180
|
delegate :checklist, to: :definition
|
|
175
181
|
|
|
@@ -197,16 +203,16 @@ module Shipit
|
|
|
197
203
|
|
|
198
204
|
def write(text)
|
|
199
205
|
log_output(text)
|
|
200
|
-
|
|
206
|
+
Shipit.redis.append(output_key, text)
|
|
201
207
|
end
|
|
202
208
|
|
|
203
209
|
def chunk_output
|
|
204
210
|
if rolled_up?
|
|
205
211
|
output
|
|
206
212
|
else
|
|
207
|
-
blob =
|
|
213
|
+
blob = Shipit.redis.get(output_key)
|
|
208
214
|
|
|
209
|
-
if blob.size > OUTPUT_SIZE_LIMIT
|
|
215
|
+
if blob && blob.size > OUTPUT_SIZE_LIMIT
|
|
210
216
|
Rails.logger.warn("Task #{id} output exceeds limit of #{HUMAN_READABLE_OUTPUT_LIMIT}, and will be truncated.")
|
|
211
217
|
blob = blob.last(OUTPUT_SIZE_LIMIT - OUTPUT_TRUNCATED_MESSAGE.size)
|
|
212
218
|
blob = OUTPUT_TRUNCATED_MESSAGE + blob
|
|
@@ -216,15 +222,30 @@ module Shipit
|
|
|
216
222
|
end
|
|
217
223
|
end
|
|
218
224
|
|
|
225
|
+
def chunk_output_size
|
|
226
|
+
return 0 if rolled_up?
|
|
227
|
+
|
|
228
|
+
Shipit.redis.strlen(output_key)
|
|
229
|
+
end
|
|
230
|
+
|
|
231
|
+
def tail_output(range_start)
|
|
232
|
+
Shipit.redis.getrange(output_key, range_start || 0, -1)
|
|
233
|
+
end
|
|
234
|
+
|
|
219
235
|
def schedule_rollup_chunks
|
|
220
236
|
ChunkRollupJob.perform_later(self)
|
|
221
237
|
end
|
|
222
238
|
|
|
223
239
|
def rollup_chunks
|
|
224
240
|
ActiveRecord::Base.transaction do
|
|
225
|
-
|
|
226
|
-
chunks
|
|
241
|
+
chunks = Shipit::OutputChunk.where(task: self).pluck(:text)
|
|
242
|
+
chunks << chunk_output
|
|
243
|
+
self.output = chunks.join("\n")
|
|
244
|
+
|
|
227
245
|
update_attribute(:rolled_up, true)
|
|
246
|
+
|
|
247
|
+
Shipit.redis.del(output_key)
|
|
248
|
+
Shipit::OutputChunk.where(task: self).delete_all
|
|
228
249
|
end
|
|
229
250
|
end
|
|
230
251
|
|
|
@@ -262,6 +283,10 @@ module Shipit
|
|
|
262
283
|
user || AnonymousUser.new
|
|
263
284
|
end
|
|
264
285
|
|
|
286
|
+
def author=(user)
|
|
287
|
+
super(user.presence)
|
|
288
|
+
end
|
|
289
|
+
|
|
265
290
|
def finished?
|
|
266
291
|
!pending? && !running? && !aborting?
|
|
267
292
|
end
|
|
@@ -382,12 +407,32 @@ module Shipit
|
|
|
382
407
|
.reject(&:alive?)
|
|
383
408
|
end
|
|
384
409
|
|
|
410
|
+
def retry_if_necessary
|
|
411
|
+
return unless retries_configured? && !stack.reload.locked?
|
|
412
|
+
|
|
413
|
+
if retry_attempt < max_retries
|
|
414
|
+
retry_task = duplicate_task
|
|
415
|
+
retry_task.retry_attempt = duplicate_task.retry_attempt + 1
|
|
416
|
+
retry_task.save!
|
|
417
|
+
|
|
418
|
+
retry_task.enqueue
|
|
419
|
+
end
|
|
420
|
+
end
|
|
421
|
+
|
|
422
|
+
def retries_configured?
|
|
423
|
+
!max_retries.nil? && max_retries > 0
|
|
424
|
+
end
|
|
425
|
+
|
|
385
426
|
private
|
|
386
427
|
|
|
387
428
|
def prevent_concurrency
|
|
388
429
|
raise ConcurrentTaskRunning if stack.tasks.active.exclusive.count > 1
|
|
389
430
|
end
|
|
390
431
|
|
|
432
|
+
def output_key
|
|
433
|
+
"#{status_key}:output"
|
|
434
|
+
end
|
|
435
|
+
|
|
391
436
|
def status_key
|
|
392
437
|
"shipit:task:#{id}"
|
|
393
438
|
end
|
|
@@ -405,5 +450,13 @@ module Shipit
|
|
|
405
450
|
def output_line_buffer
|
|
406
451
|
@output_line_buffer ||= LineBuffer.new
|
|
407
452
|
end
|
|
453
|
+
|
|
454
|
+
def duplicate_task
|
|
455
|
+
copy_task = dup
|
|
456
|
+
copy_task.status = 'pending'
|
|
457
|
+
copy_task.started_at = nil
|
|
458
|
+
copy_task.ended_at = nil
|
|
459
|
+
copy_task
|
|
460
|
+
end
|
|
408
461
|
end
|
|
409
462
|
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shipit
|
|
4
|
+
module TaskExecutionStrategy
|
|
5
|
+
class Base
|
|
6
|
+
def initialize(task)
|
|
7
|
+
self.task = task
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def execute
|
|
11
|
+
raise(
|
|
12
|
+
NotImplmentedError,
|
|
13
|
+
"subclasses of TaskExectuionStrategy::Base must implement the #execute method"
|
|
14
|
+
)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
attr_accessor :task
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shipit
|
|
4
|
+
module TaskExecutionStrategy
|
|
5
|
+
class Default < Base
|
|
6
|
+
def execute
|
|
7
|
+
@commands = Commands.for(@task)
|
|
8
|
+
unless @task.pending?
|
|
9
|
+
Rails.logger.error("Task ##{@task.id} already in `#{@task.status}` state. Aborting.")
|
|
10
|
+
return
|
|
11
|
+
end
|
|
12
|
+
run
|
|
13
|
+
ensure
|
|
14
|
+
@commands.clear_working_directory
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def run
|
|
18
|
+
@task.ping
|
|
19
|
+
@task.run!
|
|
20
|
+
checkout_repository
|
|
21
|
+
perform_task
|
|
22
|
+
@task.write("\nCompleted successfully\n")
|
|
23
|
+
@task.report_complete!
|
|
24
|
+
rescue Command::TimedOut => error
|
|
25
|
+
@task.write("\n#{error.message}\n")
|
|
26
|
+
@task.report_timeout!(error)
|
|
27
|
+
rescue Command::Error => error
|
|
28
|
+
@task.write("\n#{error.message}\n")
|
|
29
|
+
@task.report_failure!(error)
|
|
30
|
+
rescue StandardError => error
|
|
31
|
+
@task.report_error!(error)
|
|
32
|
+
rescue Exception => error
|
|
33
|
+
@task.report_error!(error)
|
|
34
|
+
raise
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def abort!(signal: 'TERM')
|
|
38
|
+
pid = @task.pid
|
|
39
|
+
if pid
|
|
40
|
+
@task.write("$ kill #{pid}\n")
|
|
41
|
+
Process.kill(signal, pid)
|
|
42
|
+
else
|
|
43
|
+
@task.write("Can't abort, no recorded pid, WTF?\n")
|
|
44
|
+
end
|
|
45
|
+
rescue SystemCallError => error
|
|
46
|
+
@task.write("kill: (#{pid}) - #{error.message}\n")
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def check_for_abort
|
|
50
|
+
@task.should_abort? do |times_killed|
|
|
51
|
+
if times_killed > 3
|
|
52
|
+
abort!(signal: 'KILL')
|
|
53
|
+
else
|
|
54
|
+
abort!
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def perform_task
|
|
60
|
+
capture_all!(@commands.install_dependencies)
|
|
61
|
+
capture_all!(@commands.perform)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def checkout_repository
|
|
65
|
+
unless @commands.fetched?(@task.until_commit).tap(&:run).success?
|
|
66
|
+
# acquire_git_cache_lock can take upto 15 seconds
|
|
67
|
+
# to process. Try to make sure that the job isn't
|
|
68
|
+
# marked dead while we attempt to acquire the lock.
|
|
69
|
+
@task.ping
|
|
70
|
+
@task.acquire_git_cache_lock do
|
|
71
|
+
@task.ping
|
|
72
|
+
unless @commands.fetched?(@task.until_commit).tap(&:run).success?
|
|
73
|
+
capture!(@commands.fetch)
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
77
|
+
capture_all!(@commands.clone)
|
|
78
|
+
capture!(@commands.checkout(@task.until_commit))
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def capture_all!(commands)
|
|
82
|
+
commands.map { |c| capture!(c) }
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def capture!(command)
|
|
86
|
+
started_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
87
|
+
command.start do
|
|
88
|
+
@task.ping
|
|
89
|
+
check_for_abort
|
|
90
|
+
end
|
|
91
|
+
@task.write("\n$ #{command}\npid: #{command.pid}\n")
|
|
92
|
+
@task.pid = command.pid
|
|
93
|
+
command.stream! do |line|
|
|
94
|
+
@task.write(line)
|
|
95
|
+
end
|
|
96
|
+
finished_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
97
|
+
@task.write("pid: #{command.pid} finished in: #{finished_at - started_at} seconds\n")
|
|
98
|
+
command.success?
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def capture(command)
|
|
102
|
+
capture!(command)
|
|
103
|
+
command.success?
|
|
104
|
+
rescue Command::Error
|
|
105
|
+
false
|
|
106
|
+
end
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
data/app/models/shipit/team.rb
CHANGED
|
@@ -26,7 +26,8 @@ module Shipit
|
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def find_team_on_github(organization, slug)
|
|
29
|
-
|
|
29
|
+
gh_api = Shipit.github(organization: organization).api
|
|
30
|
+
teams = Shipit::OctokitIterator.new(github_api: gh_api) { gh_api.org_teams(organization, per_page: 100) }
|
|
30
31
|
teams.find { |t| t.slug == slug }
|
|
31
32
|
rescue Octokit::NotFound
|
|
32
33
|
end
|
|
@@ -41,7 +42,8 @@ module Shipit
|
|
|
41
42
|
end
|
|
42
43
|
|
|
43
44
|
def refresh_members!
|
|
44
|
-
|
|
45
|
+
github_api = Shipit.github(organization: organization).api
|
|
46
|
+
github_members = Shipit::OctokitIterator.new(github_api.get(api_url).rels[:members])
|
|
45
47
|
members = github_members.map { |u| User.find_or_create_from_github(u) }
|
|
46
48
|
self.members = members
|
|
47
49
|
save!
|
data/app/models/shipit/user.rb
CHANGED
|
@@ -15,6 +15,8 @@ module Shipit
|
|
|
15
15
|
|
|
16
16
|
def self.find_or_create_by_login!(login)
|
|
17
17
|
find_or_create_by!(login: login) do |user|
|
|
18
|
+
# Users are global, any app can be used
|
|
19
|
+
# This will not work for users that only exist in an Enterprise install
|
|
18
20
|
user.github_user = Shipit.github.api.user(login)
|
|
19
21
|
end
|
|
20
22
|
end
|
|
@@ -24,7 +26,7 @@ module Shipit
|
|
|
24
26
|
end
|
|
25
27
|
|
|
26
28
|
def self.find_or_create_author_from_github_commit(github_commit)
|
|
27
|
-
if (match_info = github_commit.commit.message.match(/^#{
|
|
29
|
+
if (match_info = github_commit.commit.message.match(/^#{MergeRequest::MERGE_REQUEST_FIELD}: ([\w\-\.]+)$/))
|
|
28
30
|
begin
|
|
29
31
|
return find_or_create_by_login!(match_info[1])
|
|
30
32
|
rescue Octokit::NotFound
|
|
@@ -80,12 +82,19 @@ module Shipit
|
|
|
80
82
|
@authorized ||= Shipit.github_teams.empty? || teams.where(id: Shipit.github_teams.map(&:id)).exists?
|
|
81
83
|
end
|
|
82
84
|
|
|
85
|
+
def repositories_contributed_to
|
|
86
|
+
return [] unless id
|
|
87
|
+
Stack.where(id: stacks_contributed_to).distinct.pluck(:repository_id)
|
|
88
|
+
end
|
|
89
|
+
|
|
83
90
|
def stacks_contributed_to
|
|
84
91
|
return [] unless id
|
|
85
92
|
Commit.where('author_id = :id or committer_id = :id', id: id).distinct.pluck(:stack_id)
|
|
86
93
|
end
|
|
87
94
|
|
|
88
95
|
def refresh_from_github!
|
|
96
|
+
# Users are global, any app can be used
|
|
97
|
+
# This will not work for users that only exist in an Enterprise install
|
|
89
98
|
update!(github_user: Shipit.github.api.user(github_id))
|
|
90
99
|
rescue Octokit::NotFound
|
|
91
100
|
identify_renamed_user!
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shipit
|
|
4
|
+
module Webhooks
|
|
5
|
+
module Handlers
|
|
6
|
+
module PullRequest
|
|
7
|
+
class AssignedHandler < Shipit::Webhooks::Handlers::Handler
|
|
8
|
+
params do
|
|
9
|
+
requires :action, String
|
|
10
|
+
requires :number, Integer
|
|
11
|
+
requires :pull_request do
|
|
12
|
+
requires :id, Integer
|
|
13
|
+
requires :number, Integer
|
|
14
|
+
requires :url, String
|
|
15
|
+
requires :title, String
|
|
16
|
+
requires :state, String
|
|
17
|
+
requires :additions, Integer
|
|
18
|
+
requires :deletions, Integer
|
|
19
|
+
requires :head do
|
|
20
|
+
requires :sha, String
|
|
21
|
+
requires :ref, String
|
|
22
|
+
end
|
|
23
|
+
requires :user do
|
|
24
|
+
requires :login, String
|
|
25
|
+
end
|
|
26
|
+
requires :assignees, Array do
|
|
27
|
+
requires :login, String
|
|
28
|
+
end
|
|
29
|
+
requires :labels, Array do
|
|
30
|
+
requires :name, String
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
requires :repository do
|
|
34
|
+
requires :full_name, String
|
|
35
|
+
end
|
|
36
|
+
requires :sender do
|
|
37
|
+
requires :login, String
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def process
|
|
42
|
+
return unless respond_to_assignee_change?
|
|
43
|
+
|
|
44
|
+
pull_request.update(github_pull_request: params.pull_request) if pull_request.present?
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def respond_to_assignee_change?
|
|
50
|
+
%w[assigned unassigned].include?(params.action)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def pull_request
|
|
54
|
+
@pull_request ||= Shipit::PullRequest
|
|
55
|
+
.joins(:stack, stack: :repository)
|
|
56
|
+
.find_by(
|
|
57
|
+
number: params.number,
|
|
58
|
+
stacks: {
|
|
59
|
+
repositories:
|
|
60
|
+
{
|
|
61
|
+
id: repository.id,
|
|
62
|
+
},
|
|
63
|
+
}
|
|
64
|
+
)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def repository
|
|
68
|
+
Shipit::Repository.from_github_repo_name(params.repository.full_name) || Shipit::NullRepository.new
|
|
69
|
+
end
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shipit
|
|
4
|
+
module Webhooks
|
|
5
|
+
module Handlers
|
|
6
|
+
module PullRequest
|
|
7
|
+
class ClosedHandler < Shipit::Webhooks::Handlers::Handler
|
|
8
|
+
params do
|
|
9
|
+
requires :action, String
|
|
10
|
+
requires :number, Integer
|
|
11
|
+
requires :pull_request do
|
|
12
|
+
requires :id, Integer
|
|
13
|
+
requires :number, Integer
|
|
14
|
+
requires :url, String
|
|
15
|
+
requires :title, String
|
|
16
|
+
requires :state, String
|
|
17
|
+
requires :additions, Integer
|
|
18
|
+
requires :deletions, Integer
|
|
19
|
+
requires :head do
|
|
20
|
+
requires :sha, String
|
|
21
|
+
requires :ref, String
|
|
22
|
+
end
|
|
23
|
+
requires :user do
|
|
24
|
+
requires :login, String
|
|
25
|
+
end
|
|
26
|
+
requires :assignees, Array do
|
|
27
|
+
requires :login, String
|
|
28
|
+
end
|
|
29
|
+
requires :labels, Array do
|
|
30
|
+
requires :name, String
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
requires :repository do
|
|
34
|
+
requires :full_name, String
|
|
35
|
+
end
|
|
36
|
+
requires :sender do
|
|
37
|
+
requires :login, String
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def process
|
|
42
|
+
return unless respond_to_pull_request_closed?
|
|
43
|
+
|
|
44
|
+
review_stack.archive!
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def repository
|
|
50
|
+
@repository ||=
|
|
51
|
+
Shipit::Repository.from_github_repo_name(params.repository.full_name) ||
|
|
52
|
+
Shipit::NullRepository.new
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def review_stack
|
|
56
|
+
@review_stack ||=
|
|
57
|
+
Shipit::Webhooks::Handlers::PullRequest::ReviewStackAdapter
|
|
58
|
+
.new(params, scope: repository.review_stacks)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def respond_to_pull_request_closed?
|
|
62
|
+
params.action == "closed"
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|