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
|
@@ -1,5 +1,35 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
module Shipit
|
|
3
|
+
class NullRepository
|
|
4
|
+
def id
|
|
5
|
+
nil
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def stacks
|
|
9
|
+
Shipit::Stack.none
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def review_stacks
|
|
13
|
+
Shipit::ReviewStack.none
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def review_stacks_enabled
|
|
17
|
+
false
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def provisioning_behavior_allow_all?
|
|
21
|
+
false
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def provisioning_behavior_allow_with_label?
|
|
25
|
+
false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def provisioning_behavior_prevent_with_label?
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
3
33
|
class Repository < ApplicationRecord
|
|
4
34
|
OWNER_MAX_SIZE = 39
|
|
5
35
|
private_constant :OWNER_MAX_SIZE
|
|
@@ -8,12 +38,16 @@ module Shipit
|
|
|
8
38
|
private_constant :NAME_MAX_SIZE
|
|
9
39
|
|
|
10
40
|
validates :name, uniqueness: { scope: %i(owner), case_sensitive: false,
|
|
11
|
-
message: 'cannot be used more than once' }
|
|
41
|
+
message: 'cannot be used more than once', }
|
|
12
42
|
validates :owner, :name, presence: true, ascii_only: true
|
|
13
43
|
validates :owner, format: { with: /\A[a-z0-9_\-\.]+\z/ }, length: { maximum: OWNER_MAX_SIZE }
|
|
14
44
|
validates :name, format: { with: /\A[a-z0-9_\-\.]+\z/ }, length: { maximum: NAME_MAX_SIZE }
|
|
15
45
|
|
|
16
46
|
has_many :stacks, dependent: :destroy
|
|
47
|
+
has_many :review_stacks, dependent: :destroy
|
|
48
|
+
|
|
49
|
+
PROVISIONING_BEHAVIORS = %w(allow_all allow_with_label prevent_with_label).freeze
|
|
50
|
+
enum provisioning_behavior: PROVISIONING_BEHAVIORS.zip(PROVISIONING_BEHAVIORS).to_h, _prefix: :provisioning_behavior
|
|
17
51
|
|
|
18
52
|
def self.from_github_repo_name(github_repo_name)
|
|
19
53
|
repo_owner, repo_name = github_repo_name.downcase.split('/')
|
|
@@ -28,8 +62,12 @@ module Shipit
|
|
|
28
62
|
super(o&.downcase)
|
|
29
63
|
end
|
|
30
64
|
|
|
65
|
+
def github_repo_name
|
|
66
|
+
[owner, name].join('/')
|
|
67
|
+
end
|
|
68
|
+
|
|
31
69
|
def http_url
|
|
32
|
-
|
|
70
|
+
github_app.url(full_name)
|
|
33
71
|
end
|
|
34
72
|
|
|
35
73
|
def full_name
|
|
@@ -37,7 +75,29 @@ module Shipit
|
|
|
37
75
|
end
|
|
38
76
|
|
|
39
77
|
def git_url
|
|
40
|
-
"https://#{
|
|
78
|
+
"https://#{github_app.domain}/#{owner}/#{name}.git"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def schedule_for_destroy!
|
|
82
|
+
DestroyRepositoryJob.perform_later(self)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def to_param
|
|
86
|
+
github_repo_name
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self.from_param!(param)
|
|
90
|
+
repo_owner, repo_name = param.split('/')
|
|
91
|
+
where(
|
|
92
|
+
owner: repo_owner.downcase,
|
|
93
|
+
name: repo_name.downcase,
|
|
94
|
+
).first!
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
protected
|
|
98
|
+
|
|
99
|
+
def github_app
|
|
100
|
+
Shipit.github(organization: owner)
|
|
41
101
|
end
|
|
42
102
|
end
|
|
43
103
|
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shipit
|
|
4
|
+
class ReviewStack < Shipit::Stack
|
|
5
|
+
def self.clear_stale_caches
|
|
6
|
+
Shipit::ReviewStack.where(
|
|
7
|
+
"archived_since > :earliest AND archived_since < :latest",
|
|
8
|
+
earliest: 1.day.ago,
|
|
9
|
+
latest: 1.hour.ago
|
|
10
|
+
).find_each do |review_stack|
|
|
11
|
+
review_stack.clear_local_files
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.delete_old_deployment_directories
|
|
16
|
+
Shipit::Deploy.not_active.where(
|
|
17
|
+
"created_at > :earliest AND updated_at < :latest",
|
|
18
|
+
earliest: 1.day.ago,
|
|
19
|
+
latest: 1.hour.ago
|
|
20
|
+
).find_each do |deploy|
|
|
21
|
+
Shipit::Commands.for(deploy).clear_working_directory
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def update_latest_deployed_ref
|
|
26
|
+
# noop: last deployed ref is useless for review stacks
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
model_name.class_eval do
|
|
30
|
+
def route_key
|
|
31
|
+
"stacks"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def singular_route_key
|
|
35
|
+
"stack"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
has_one :pull_request, foreign_key: :stack_id
|
|
40
|
+
|
|
41
|
+
after_commit :emit_added_hooks, on: :create
|
|
42
|
+
after_commit :emit_updated_hooks, on: :update
|
|
43
|
+
after_commit :emit_removed_hooks, on: :destroy
|
|
44
|
+
|
|
45
|
+
state_machine :provision_status, initial: :deprovisioned do
|
|
46
|
+
state :provisioned
|
|
47
|
+
state :provisioning
|
|
48
|
+
state :deprovisioning
|
|
49
|
+
state :deprovisioned
|
|
50
|
+
|
|
51
|
+
event :provision do
|
|
52
|
+
transition deprovisioned: :provisioning
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
event :provision_success do
|
|
56
|
+
transition provisioning: :provisioned
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
event :provision_failure do
|
|
60
|
+
transition provisioning: :deprovisioned
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
event :deprovision do
|
|
64
|
+
transition provisioned: :deprovisioning
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
event :deprovision_success do
|
|
68
|
+
transition deprovisioning: :deprovisioned
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
event :deprovision_failure do
|
|
72
|
+
transition deprovisioning: :provisioned
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
after_transition deprovisioned: :provisioning do |stack, _|
|
|
76
|
+
stack.provisioner.up
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
after_transition provisioned: :deprovisioning do |stack, _|
|
|
80
|
+
stack.provisioner.down
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def env
|
|
85
|
+
return super unless pull_request.present?
|
|
86
|
+
|
|
87
|
+
super
|
|
88
|
+
.merge(
|
|
89
|
+
pull_request
|
|
90
|
+
.labels
|
|
91
|
+
.each_with_object({}) { |label_name, labels| labels[label_name.upcase] = "true" }
|
|
92
|
+
)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def provisioner
|
|
96
|
+
provisioner_class.new(self)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def provisioner_class
|
|
100
|
+
ProvisioningHandler.fetch(provisioning_handler_name)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def enqueue_for_provisioning
|
|
104
|
+
return if awaiting_provision
|
|
105
|
+
update!(awaiting_provision: true)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def remove_from_provisioning_queue
|
|
109
|
+
return unless awaiting_provision
|
|
110
|
+
update!(awaiting_provision: false)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def to_partial_path
|
|
114
|
+
"shipit/stacks/stack"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def emit_added_hooks
|
|
118
|
+
Hook.emit(:review_stack, self, action: :added, review_stack: self)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def emit_updated_hooks
|
|
122
|
+
changed = !(previous_changes.keys - %w(updated_at)).empty?
|
|
123
|
+
Hook.emit(:review_stack, self, action: :updated, review_stack: self) if changed
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def emit_removed_hooks
|
|
127
|
+
Hook.emit(:review_stack, self, action: :removed, review_stack: self)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shipit
|
|
4
|
+
class ReviewStackProvisioningQueue
|
|
5
|
+
def self.work
|
|
6
|
+
new.work
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.add(stack)
|
|
10
|
+
stack.enqueue_for_provisioning
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.queued_stacks
|
|
14
|
+
new.queued_stacks
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def work
|
|
18
|
+
queued_stacks.find_each(&method(:provision))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def queued_stacks
|
|
22
|
+
@queued_stacks ||= Shipit::ReviewStack
|
|
23
|
+
.with_provision_status(:deprovisioned)
|
|
24
|
+
.where(awaiting_provision: true)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def provision(stack)
|
|
30
|
+
if stack.provisioner.provision?
|
|
31
|
+
stack.provision
|
|
32
|
+
else
|
|
33
|
+
Rails.logger.info(
|
|
34
|
+
"Putting review ReviewStack<#{stack.id}> back into the provisioning queue - #provision? was falsey."
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -33,6 +33,10 @@ module Shipit
|
|
|
33
33
|
'deploys/deploy'
|
|
34
34
|
end
|
|
35
35
|
|
|
36
|
+
def report_complete!
|
|
37
|
+
complete!
|
|
38
|
+
end
|
|
39
|
+
|
|
36
40
|
private
|
|
37
41
|
|
|
38
42
|
def update_release_status
|
|
@@ -40,6 +44,7 @@ module Shipit
|
|
|
40
44
|
|
|
41
45
|
# When we rollback to a certain revision, assume that all later deploys were faulty
|
|
42
46
|
stack.deploys.newer_than(deploy.id).until(stack.last_completed_deploy.id).to_a.each do |deploy|
|
|
47
|
+
next if deploy.id == id
|
|
43
48
|
deploy.report_faulty!(description: "A rollback of #{stack.to_param} was triggered")
|
|
44
49
|
end
|
|
45
50
|
end
|
data/app/models/shipit/stack.rb
CHANGED
|
@@ -27,14 +27,14 @@ module Shipit
|
|
|
27
27
|
REQUIRED_HOOKS = %i(push status).freeze
|
|
28
28
|
|
|
29
29
|
has_many :commits, dependent: :destroy
|
|
30
|
-
has_many :
|
|
30
|
+
has_many :merge_requests, dependent: :destroy
|
|
31
31
|
has_many :tasks, dependent: :destroy
|
|
32
32
|
has_many :deploys
|
|
33
33
|
has_many :rollbacks
|
|
34
34
|
has_many :deploys_and_rollbacks,
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
35
|
+
-> { where(type: %w(Shipit::Deploy Shipit::Rollback)) },
|
|
36
|
+
class_name: 'Task',
|
|
37
|
+
inverse_of: :stack
|
|
38
38
|
has_many :github_hooks, dependent: :destroy, class_name: 'Shipit::GithubHook::Repo'
|
|
39
39
|
has_many :hooks, dependent: :destroy
|
|
40
40
|
has_many :api_clients, dependent: :destroy
|
|
@@ -44,6 +44,9 @@ module Shipit
|
|
|
44
44
|
|
|
45
45
|
scope :not_archived, -> { where(archived_since: nil) }
|
|
46
46
|
|
|
47
|
+
include DeferredTouch
|
|
48
|
+
deferred_touch repository: :updated_at
|
|
49
|
+
|
|
47
50
|
default_scope { preload(:repository) }
|
|
48
51
|
|
|
49
52
|
def env
|
|
@@ -80,19 +83,36 @@ module Shipit
|
|
|
80
83
|
after_commit :emit_merge_status_hooks, on: :update
|
|
81
84
|
after_commit :sync_github, on: :create
|
|
82
85
|
after_commit :schedule_merges_if_necessary, on: :update
|
|
86
|
+
after_commit :sync_github_if_necessary, on: :update
|
|
87
|
+
|
|
88
|
+
def sync_github_if_necessary
|
|
89
|
+
if (archived_since_previously_changed? && archived_since.nil?) || branch_previously_changed?
|
|
90
|
+
sync_github
|
|
91
|
+
end
|
|
92
|
+
end
|
|
83
93
|
|
|
84
94
|
validates :repository, uniqueness: {
|
|
85
95
|
scope: %i(environment), case_sensitive: false,
|
|
86
|
-
message: 'cannot be used more than once with this environment. Check archived stacks.'
|
|
96
|
+
message: 'cannot be used more than once with this environment. Check archived stacks.',
|
|
87
97
|
}
|
|
88
98
|
validates :environment, format: { with: /\A[a-z0-9\-_\:]+\z/ }, length: { maximum: ENVIRONMENT_MAX_SIZE }
|
|
89
99
|
validates :deploy_url, format: { with: URI.regexp(%w(http https ssh)) }, allow_blank: true
|
|
100
|
+
validates :branch, presence: true
|
|
90
101
|
|
|
91
102
|
validates :lock_reason, length: { maximum: 4096 }
|
|
92
103
|
|
|
93
104
|
serialize :cached_deploy_spec, DeploySpec
|
|
94
|
-
delegate
|
|
95
|
-
|
|
105
|
+
delegate(
|
|
106
|
+
:provisioning_handler_name,
|
|
107
|
+
:find_task_definition,
|
|
108
|
+
:release_status?,
|
|
109
|
+
:release_status_context,
|
|
110
|
+
:release_status_delay,
|
|
111
|
+
:supports_fetch_deployed_revision?,
|
|
112
|
+
:supports_rollback?,
|
|
113
|
+
to: :cached_deploy_spec,
|
|
114
|
+
allow_nil: true
|
|
115
|
+
)
|
|
96
116
|
|
|
97
117
|
def self.refresh_deployed_revisions
|
|
98
118
|
find_each.select(&:supports_fetch_deployed_revision?).each(&:async_refresh_deployed_revision)
|
|
@@ -139,6 +159,7 @@ module Shipit
|
|
|
139
159
|
env: filter_deploy_envs(env&.to_h || {}),
|
|
140
160
|
allow_concurrency: force,
|
|
141
161
|
ignored_safeties: force || !until_commit.deployable?,
|
|
162
|
+
max_retries: retries_on_deploy,
|
|
142
163
|
)
|
|
143
164
|
end
|
|
144
165
|
|
|
@@ -171,7 +192,7 @@ module Shipit
|
|
|
171
192
|
end
|
|
172
193
|
|
|
173
194
|
def continuous_delivery_delayed?
|
|
174
|
-
continuous_delivery_delayed_since? && continuous_deployment? && checks?
|
|
195
|
+
continuous_delivery_delayed_since? && continuous_deployment? && (checks? || deployment_checks?)
|
|
175
196
|
end
|
|
176
197
|
|
|
177
198
|
def continuous_delivery_delayed!
|
|
@@ -200,7 +221,7 @@ module Shipit
|
|
|
200
221
|
end
|
|
201
222
|
|
|
202
223
|
def schedule_merges
|
|
203
|
-
|
|
224
|
+
ProcessMergeRequestsJob.perform_later(self)
|
|
204
225
|
end
|
|
205
226
|
|
|
206
227
|
def next_commit_to_deploy
|
|
@@ -340,7 +361,7 @@ module Shipit
|
|
|
340
361
|
end
|
|
341
362
|
|
|
342
363
|
def deployable?
|
|
343
|
-
!locked? && !active_task?
|
|
364
|
+
!locked? && !active_task? && !awaiting_provision? && deployment_checks_passed?
|
|
344
365
|
end
|
|
345
366
|
|
|
346
367
|
def allows_merges?
|
|
@@ -348,7 +369,7 @@ module Shipit
|
|
|
348
369
|
end
|
|
349
370
|
|
|
350
371
|
def merge_method
|
|
351
|
-
cached_deploy_spec&.
|
|
372
|
+
cached_deploy_spec&.merge_request_merge_method || Shipit.default_merge_method
|
|
352
373
|
end
|
|
353
374
|
|
|
354
375
|
delegate :name=, to: :repository, prefix: :repo
|
|
@@ -359,42 +380,51 @@ module Shipit
|
|
|
359
380
|
delegate :git_url, to: :repository, prefix: :repo
|
|
360
381
|
|
|
361
382
|
def base_path
|
|
362
|
-
Rails.root.join('data', 'stacks', repo_owner, repo_name, environment)
|
|
383
|
+
@base_path ||= Rails.root.join('data', 'stacks', repo_owner, repo_name, environment)
|
|
363
384
|
end
|
|
364
385
|
|
|
365
386
|
def deploys_path
|
|
366
|
-
|
|
387
|
+
@deploys_path ||= base_path.join("deploys")
|
|
367
388
|
end
|
|
368
389
|
|
|
369
390
|
def git_path
|
|
370
|
-
|
|
391
|
+
@git_path ||= base_path.join("git")
|
|
371
392
|
end
|
|
372
393
|
|
|
373
394
|
def acquire_git_cache_lock(timeout: 15, &block)
|
|
374
|
-
Flock.new(git_path.to_s + '.lock')
|
|
395
|
+
@git_cache_lock ||= Flock.new(git_path.to_s + '.lock')
|
|
396
|
+
@git_cache_lock.lock(timeout: timeout, &block)
|
|
375
397
|
end
|
|
376
398
|
|
|
377
399
|
def clear_git_cache!
|
|
378
400
|
tmp_path = "#{git_path}-#{SecureRandom.hex}"
|
|
379
|
-
return unless
|
|
401
|
+
return unless git_path.exist?
|
|
380
402
|
acquire_git_cache_lock do
|
|
381
|
-
|
|
403
|
+
git_path.rename(tmp_path)
|
|
382
404
|
end
|
|
383
405
|
FileUtils.rm_rf(tmp_path)
|
|
384
406
|
end
|
|
385
407
|
|
|
386
408
|
def github_repo_name
|
|
387
|
-
|
|
409
|
+
repository.github_repo_name
|
|
388
410
|
end
|
|
389
411
|
|
|
390
412
|
def github_commits
|
|
391
413
|
handle_github_redirections do
|
|
392
|
-
|
|
414
|
+
github_api.commits(github_repo_name, sha: branch)
|
|
393
415
|
end
|
|
394
416
|
rescue Octokit::Conflict
|
|
395
417
|
[] # Repository is empty...
|
|
396
418
|
end
|
|
397
419
|
|
|
420
|
+
def github_api
|
|
421
|
+
github_app.api
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def github_app
|
|
425
|
+
Shipit.github(organization: repository.owner)
|
|
426
|
+
end
|
|
427
|
+
|
|
398
428
|
def handle_github_redirections
|
|
399
429
|
# https://developer.github.com/v3/#http-redirects
|
|
400
430
|
resource = yield
|
|
@@ -407,9 +437,9 @@ module Shipit
|
|
|
407
437
|
end
|
|
408
438
|
|
|
409
439
|
def refresh_repository!
|
|
410
|
-
resource =
|
|
440
|
+
resource = github_api.repo(github_repo_name)
|
|
411
441
|
if resource.try(:message) == 'Moved Permanently'
|
|
412
|
-
resource =
|
|
442
|
+
resource = github_api.get(resource.url)
|
|
413
443
|
end
|
|
414
444
|
repository.update!(owner: resource.owner.login, name: resource.name)
|
|
415
445
|
end
|
|
@@ -474,8 +504,9 @@ module Shipit
|
|
|
474
504
|
end
|
|
475
505
|
|
|
476
506
|
delegate :plugins, :task_definitions, :hidden_statuses, :required_statuses, :soft_failing_statuses,
|
|
477
|
-
|
|
478
|
-
|
|
507
|
+
:blocking_statuses, :deploy_variables, :filter_task_envs, :filter_deploy_envs,
|
|
508
|
+
:maximum_commits_per_deploy, :pause_between_deploys, :retries_on_deploy, :retries_on_rollback,
|
|
509
|
+
to: :cached_deploy_spec
|
|
479
510
|
|
|
480
511
|
def monitoring?
|
|
481
512
|
monitoring.present?
|
|
@@ -567,19 +598,31 @@ module Shipit
|
|
|
567
598
|
links_spec.transform_values { |url| context.interpolate(url) }
|
|
568
599
|
end
|
|
569
600
|
|
|
601
|
+
def clear_local_files
|
|
602
|
+
FileUtils.rm_rf(base_path.to_s)
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
def deployment_checks_passed?
|
|
606
|
+
return true unless deployment_checks?
|
|
607
|
+
|
|
608
|
+
Shipit.deployment_checks.call(self)
|
|
609
|
+
end
|
|
610
|
+
|
|
570
611
|
private
|
|
571
612
|
|
|
572
613
|
def clear_cache
|
|
573
614
|
remove_instance_variable(:@active_task) if defined?(@active_task)
|
|
574
615
|
end
|
|
575
616
|
|
|
576
|
-
def clear_local_files
|
|
577
|
-
FileUtils.rm_rf(base_path.to_s)
|
|
578
|
-
end
|
|
579
|
-
|
|
580
617
|
def update_defaults
|
|
581
618
|
self.environment = 'production' if environment.blank?
|
|
582
|
-
self.branch =
|
|
619
|
+
self.branch = default_branch_name if branch.blank?
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
def default_branch_name
|
|
623
|
+
Shipit.github.api.repo(github_repo_name).default_branch
|
|
624
|
+
rescue Octokit::NotFound, Octokit::InvalidRepository
|
|
625
|
+
nil
|
|
583
626
|
end
|
|
584
627
|
|
|
585
628
|
def set_locked_since
|
|
@@ -593,7 +636,7 @@ module Shipit
|
|
|
593
636
|
end
|
|
594
637
|
|
|
595
638
|
def schedule_merges_if_necessary
|
|
596
|
-
if
|
|
639
|
+
if lock_reason_previously_changed? && lock_reason.blank?
|
|
597
640
|
schedule_merges
|
|
598
641
|
end
|
|
599
642
|
end
|
|
@@ -630,7 +673,7 @@ module Shipit
|
|
|
630
673
|
end
|
|
631
674
|
|
|
632
675
|
def should_resume_continuous_delivery?(commit)
|
|
633
|
-
!deployable? ||
|
|
676
|
+
(deployment_checks_passed? && !deployable?) ||
|
|
634
677
|
deployed_too_recently? ||
|
|
635
678
|
commit.nil? ||
|
|
636
679
|
commit.deployed?
|
|
@@ -639,7 +682,12 @@ module Shipit
|
|
|
639
682
|
def should_delay_continuous_delivery?(commit)
|
|
640
683
|
commit.deploy_failed? ||
|
|
641
684
|
(checks? && !EphemeralCommitChecks.new(commit).run.success?) ||
|
|
685
|
+
!deployment_checks_passed? ||
|
|
642
686
|
commit.recently_pushed?
|
|
643
687
|
end
|
|
688
|
+
|
|
689
|
+
def deployment_checks?
|
|
690
|
+
Shipit.deployment_checks.present?
|
|
691
|
+
end
|
|
644
692
|
end
|
|
645
693
|
end
|