shipit-engine 0.32.0 → 0.33.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- 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/_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/{pull_requests_controller.rb → merge_requests_controller.rb} +8 -8
- data/app/controllers/shipit/api/stacks_controller.rb +14 -1
- data/app/controllers/shipit/deploys_controller.rb +2 -2
- 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/tasks_controller.rb +4 -4
- data/app/helpers/shipit/chunks_helper.rb +2 -2
- data/app/helpers/shipit/github_url_helper.rb +8 -0
- data/app/helpers/shipit/stacks_helper.rb +4 -0
- data/app/jobs/shipit/create_on_github_job.rb +1 -0
- data/app/jobs/shipit/destroy_repository_job.rb +24 -0
- data/app/jobs/shipit/destroy_stack_job.rb +2 -2
- 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/models/shipit/anonymous_user.rb +4 -0
- data/app/models/shipit/check_run.rb +2 -2
- data/app/models/shipit/command_line_user.rb +4 -0
- data/app/models/shipit/commit.rb +11 -11
- data/app/models/shipit/commit_checks.rb +1 -0
- data/app/models/shipit/deploy.rb +1 -0
- data/app/models/shipit/deploy_spec.rb +16 -4
- data/app/models/shipit/deploy_spec/file_system.rb +11 -5
- data/app/models/shipit/hook.rb +2 -0
- data/app/models/shipit/merge_request.rb +302 -0
- data/app/models/shipit/provisioning_handler.rb +32 -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/pull_request.rb +25 -264
- data/app/models/shipit/pull_request_assignment.rb +10 -0
- data/app/models/shipit/repository.rb +54 -0
- data/app/models/shipit/review_stack.rb +116 -0
- data/app/models/shipit/review_stack_provisioning_queue.rb +39 -0
- data/app/models/shipit/stack.rb +22 -8
- data/app/models/shipit/task.rb +56 -7
- data/app/models/shipit/task_execution_strategy/base.rb +20 -0
- data/app/models/shipit/task_execution_strategy/default.rb +110 -0
- data/app/models/shipit/user.rb +6 -1
- data/app/models/shipit/webhooks.rb +10 -0
- 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/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/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 +13 -0
- 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/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/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/lib/shipit.rb +11 -1
- data/lib/shipit/github_app.rb +1 -1
- data/lib/shipit/review_stack_commands.rb +8 -0
- data/lib/shipit/stack_commands.rb +6 -1
- data/lib/shipit/task_commands.rb +1 -0
- data/lib/shipit/version.rb +1 -1
- data/lib/tasks/cron.rake +11 -2
- 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 +21 -1
- 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 +1 -1
- data/test/dummy/config/application.rb +6 -1
- data/test/dummy/config/environments/development.rb +0 -3
- data/test/dummy/config/environments/test.rb +0 -5
- data/test/dummy/db/schema.rb +52 -14
- data/test/dummy/db/seeds.rb +1 -1
- data/test/fixtures/payloads/check_suite_master.json +2 -2
- 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/shipit/commits.yml +15 -2
- 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 +3 -0
- data/test/fixtures/shipit/users.yml +7 -0
- 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/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/commits_test.rb +22 -13
- data/test/models/deploy_spec_test.rb +57 -24
- data/test/models/deploys_test.rb +148 -14
- data/test/models/{pull_request_test.rb → merge_request_test.rb} +30 -30
- data/test/models/pull_request_assignment_test.rb +16 -0
- 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 +59 -0
- data/test/models/{stacks_test.rb → shipit/stacks_test.rb} +10 -4
- 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 +83 -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 +44 -3
- data/test/serializers/shipit/pull_request_serializer_test.rb +29 -0
- data/test/unit/command_test.rb +3 -3
- data/test/unit/github_url_helper_test.rb +5 -0
- data/test/unit/shipit_task_execution_strategy_test.rb +47 -0
- metadata +260 -154
- 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
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shipit
|
|
4
|
+
module ProvisioningHandler
|
|
5
|
+
class Base
|
|
6
|
+
def initialize(stack)
|
|
7
|
+
@stack = stack
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def up
|
|
11
|
+
# Intentionally a noop
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def down
|
|
15
|
+
# Intentionally a noop
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# An (optional) guard to prevent provisioning. Intended to be
|
|
19
|
+
# use to set logic to determine if enough actual resources exist
|
|
20
|
+
# to complete the provisioning request.
|
|
21
|
+
def provision?
|
|
22
|
+
true
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
attr_accessor :stack
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shipit
|
|
4
|
+
module ProvisioningHandler
|
|
5
|
+
class UnregisteredProvisioningHandler < Shipit::ProvisioningHandler::Base
|
|
6
|
+
def up
|
|
7
|
+
lock_and_prevent_transition
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def down
|
|
11
|
+
lock_and_prevent_transition
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
private
|
|
15
|
+
|
|
16
|
+
def lock_and_prevent_transition
|
|
17
|
+
stack.lock(
|
|
18
|
+
"Failed to find a provisioning handler named '#{stack.provisioning_handler_name}' in the " \
|
|
19
|
+
"ProvisioningHandler registry. Have you registered it via Provisioning::Handler.register?",
|
|
20
|
+
Shipit::AnonymousUser.new
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
# Prevent transition of the ReviewStack 'provision_status'
|
|
24
|
+
# state machine. This signals to the state_machines gem that
|
|
25
|
+
# the transition should be canceled.
|
|
26
|
+
#
|
|
27
|
+
# References:
|
|
28
|
+
#
|
|
29
|
+
# - https://github.com/state-machines/state_machines/blob/309668998449ca6c348de809f34660d822bc626e/lib/state_machines/callback.rb#L81-L89
|
|
30
|
+
# - https://github.com/state-machines/state_machines/blob/309668998449ca6c348de809f34660d822bc626e/lib/state_machines/transition_collection.rb#L63
|
|
31
|
+
throw(:halt)
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
@@ -1,299 +1,60 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
|
+
|
|
2
3
|
module Shipit
|
|
3
|
-
class PullRequest <
|
|
4
|
+
class PullRequest < Record
|
|
4
5
|
include DeferredTouch
|
|
5
6
|
|
|
6
|
-
MERGE_REQUEST_FIELD = 'Merge-Requested-By'
|
|
7
|
-
|
|
8
|
-
WAITING_STATUSES = %w(fetching pending).freeze
|
|
9
|
-
QUEUED_STATUSES = %w(pending revalidating).freeze
|
|
10
|
-
REJECTION_REASONS = %w(ci_missing ci_failing merge_conflict requires_rebase).freeze
|
|
11
|
-
InvalidTransition = Class.new(StandardError)
|
|
12
|
-
NotReady = Class.new(StandardError)
|
|
13
|
-
|
|
14
|
-
class StatusChecker < Status::Group
|
|
15
|
-
def initialize(commit, statuses, deploy_spec)
|
|
16
|
-
@deploy_spec = deploy_spec
|
|
17
|
-
super(commit, statuses)
|
|
18
|
-
end
|
|
19
|
-
|
|
20
|
-
private
|
|
21
|
-
|
|
22
|
-
attr_reader :deploy_spec
|
|
23
|
-
|
|
24
|
-
def reject_hidden(statuses)
|
|
25
|
-
statuses.reject { |s| ignored_statuses.include?(s.context) }
|
|
26
|
-
end
|
|
27
|
-
|
|
28
|
-
def reject_allowed_to_fail(statuses)
|
|
29
|
-
statuses.reject { |s| ignored_statuses.include?(s.context) }
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
def ignored_statuses
|
|
33
|
-
deploy_spec&.pull_request_ignored_statuses || []
|
|
34
|
-
end
|
|
35
|
-
|
|
36
|
-
def required_statuses
|
|
37
|
-
deploy_spec&.pull_request_required_statuses || []
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
|
-
|
|
41
7
|
belongs_to :stack
|
|
8
|
+
belongs_to :user
|
|
42
9
|
belongs_to :head, class_name: 'Shipit::Commit', optional: true
|
|
43
|
-
belongs_to :base_commit, class_name: 'Shipit::Commit', optional: true
|
|
44
|
-
belongs_to :merge_requested_by, class_name: 'Shipit::User', optional: true
|
|
45
|
-
has_one :merge_commit, class_name: 'Shipit::Commit'
|
|
46
|
-
|
|
47
|
-
deferred_touch stack: :updated_at
|
|
48
|
-
|
|
49
|
-
validates :number, presence: true, uniqueness: { scope: :stack_id }
|
|
50
|
-
|
|
51
|
-
scope :waiting, -> { where(merge_status: WAITING_STATUSES) }
|
|
52
|
-
scope :pending, -> { where(merge_status: 'pending') }
|
|
53
|
-
scope :to_be_merged, -> { pending.order(merge_requested_at: :asc) }
|
|
54
|
-
scope :queued, -> { where(merge_status: QUEUED_STATUSES).order(merge_requested_at: :asc) }
|
|
55
|
-
|
|
56
|
-
after_save :record_merge_status_change
|
|
57
|
-
after_commit :emit_hooks
|
|
58
|
-
|
|
59
|
-
state_machine :merge_status, initial: :fetching do
|
|
60
|
-
state :fetching
|
|
61
|
-
state :pending
|
|
62
|
-
state :rejected
|
|
63
|
-
state :canceled
|
|
64
|
-
state :merged
|
|
65
|
-
state :revalidating
|
|
66
10
|
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
event :reject do
|
|
72
|
-
transition pending: :rejected
|
|
73
|
-
end
|
|
11
|
+
has_many :pull_request_assignments
|
|
12
|
+
has_many :assignees, class_name: :User, through: :pull_request_assignments, source: :user
|
|
74
13
|
|
|
75
|
-
|
|
76
|
-
transition pending: :revalidating
|
|
77
|
-
end
|
|
78
|
-
|
|
79
|
-
event :cancel do
|
|
80
|
-
transition any => :canceled
|
|
81
|
-
end
|
|
14
|
+
serialize :labels, Array
|
|
82
15
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
event :retry do
|
|
88
|
-
transition %i(rejected canceled revalidating) => :pending
|
|
89
|
-
end
|
|
90
|
-
|
|
91
|
-
before_transition rejected: any do |pr|
|
|
92
|
-
pr.rejection_reason = nil
|
|
93
|
-
end
|
|
16
|
+
after_create_commit :emit_create_hooks
|
|
17
|
+
after_update_commit :emit_update_hooks
|
|
18
|
+
after_destroy_commit :emit_destroy_hooks
|
|
94
19
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
before_transition any => :pending do |pr|
|
|
100
|
-
pr.revalidated_at = Time.now.utc
|
|
101
|
-
end
|
|
102
|
-
|
|
103
|
-
before_transition %i(pending) => :merged do |pr|
|
|
104
|
-
Stack.increment_counter(:undeployed_commits_count, pr.stack_id)
|
|
105
|
-
end
|
|
20
|
+
def emit_destroy_hooks
|
|
21
|
+
emit_hooks(:destroyed)
|
|
106
22
|
end
|
|
107
23
|
|
|
108
|
-
def
|
|
109
|
-
|
|
24
|
+
def emit_create_hooks
|
|
25
|
+
emit_hooks(:created)
|
|
110
26
|
end
|
|
111
27
|
|
|
112
|
-
def
|
|
113
|
-
|
|
114
|
-
when /\A#?(\d+)\z/
|
|
115
|
-
$1.to_i
|
|
116
|
-
when %r{\Ahttps://#{Regexp.escape(Shipit.github.domain)}/([^/]+)/([^/]+)/pull/(\d+)}
|
|
117
|
-
return unless $1.downcase == stack.repo_owner.downcase
|
|
118
|
-
return unless $2.downcase == stack.repo_name.downcase
|
|
119
|
-
$3.to_i
|
|
120
|
-
end
|
|
28
|
+
def emit_update_hooks
|
|
29
|
+
emit_hooks(:updated)
|
|
121
30
|
end
|
|
122
31
|
|
|
123
|
-
def
|
|
124
|
-
|
|
125
|
-
pull_request = begin
|
|
126
|
-
create_with(
|
|
127
|
-
merge_requested_at: now,
|
|
128
|
-
merge_requested_by: user.presence,
|
|
129
|
-
).find_or_create_by!(
|
|
130
|
-
stack: stack,
|
|
131
|
-
number: number,
|
|
132
|
-
)
|
|
133
|
-
rescue ActiveRecord::RecordNotUnique
|
|
134
|
-
retry
|
|
135
|
-
end
|
|
136
|
-
pull_request.update!(merge_requested_by: user.presence)
|
|
137
|
-
pull_request.retry! if pull_request.rejected? || pull_request.canceled? || pull_request.revalidating?
|
|
138
|
-
pull_request.schedule_refresh!
|
|
139
|
-
pull_request
|
|
140
|
-
end
|
|
141
|
-
|
|
142
|
-
def reject!(reason)
|
|
143
|
-
unless REJECTION_REASONS.include?(reason)
|
|
144
|
-
raise ArgumentError, "invalid reason: #{reason.inspect}, must be one of: #{REJECTION_REASONS.inspect}"
|
|
145
|
-
end
|
|
146
|
-
self.rejection_reason = reason.presence
|
|
147
|
-
super()
|
|
148
|
-
true
|
|
149
|
-
end
|
|
150
|
-
|
|
151
|
-
def reject_unless_mergeable!
|
|
152
|
-
return reject!('merge_conflict') if merge_conflict?
|
|
153
|
-
return reject!('ci_missing') if any_status_checks_missing?
|
|
154
|
-
return reject!('ci_failing') if any_status_checks_failed?
|
|
155
|
-
return reject!('requires_rebase') if stale?
|
|
156
|
-
false
|
|
157
|
-
end
|
|
158
|
-
|
|
159
|
-
def merge!
|
|
160
|
-
raise InvalidTransition unless pending?
|
|
161
|
-
|
|
162
|
-
raise NotReady if not_mergeable_yet?
|
|
163
|
-
|
|
164
|
-
Shipit.github.api.merge_pull_request(
|
|
165
|
-
stack.github_repo_name,
|
|
166
|
-
number,
|
|
167
|
-
merge_message,
|
|
168
|
-
sha: head.sha,
|
|
169
|
-
commit_message: 'Merged by Shipit',
|
|
170
|
-
merge_method: stack.merge_method,
|
|
171
|
-
)
|
|
172
|
-
begin
|
|
173
|
-
if Shipit.github.api.pull_requests(stack.github_repo_name, base: branch).empty?
|
|
174
|
-
Shipit.github.api.delete_branch(stack.github_repo_name, branch)
|
|
175
|
-
end
|
|
176
|
-
rescue Octokit::UnprocessableEntity
|
|
177
|
-
# branch was already deleted somehow
|
|
178
|
-
end
|
|
179
|
-
complete!
|
|
180
|
-
true
|
|
181
|
-
rescue Octokit::MethodNotAllowed # merge conflict
|
|
182
|
-
reject!('merge_conflict')
|
|
183
|
-
false
|
|
184
|
-
rescue Octokit::Conflict # shas didn't match, PR was updated.
|
|
185
|
-
raise NotReady
|
|
186
|
-
end
|
|
187
|
-
|
|
188
|
-
def all_status_checks_passed?
|
|
189
|
-
return false unless head
|
|
190
|
-
StatusChecker.new(head, head.statuses_and_check_runs, stack.cached_deploy_spec).success?
|
|
191
|
-
end
|
|
192
|
-
|
|
193
|
-
def any_status_checks_failed?
|
|
194
|
-
status = StatusChecker.new(head, head.statuses_and_check_runs, stack.cached_deploy_spec)
|
|
195
|
-
status.failure? || status.error?
|
|
196
|
-
end
|
|
197
|
-
|
|
198
|
-
def any_status_checks_missing?
|
|
199
|
-
StatusChecker.new(head, head.statuses_and_check_runs, stack.cached_deploy_spec).missing?
|
|
200
|
-
end
|
|
201
|
-
|
|
202
|
-
def waiting?
|
|
203
|
-
WAITING_STATUSES.include?(merge_status)
|
|
204
|
-
end
|
|
205
|
-
|
|
206
|
-
def need_revalidation?
|
|
207
|
-
timeout = stack.cached_deploy_spec&.revalidate_pull_requests_after
|
|
208
|
-
return false unless timeout
|
|
209
|
-
(revalidated_at + timeout).past?
|
|
210
|
-
end
|
|
211
|
-
|
|
212
|
-
def merge_conflict?
|
|
213
|
-
mergeable == false
|
|
214
|
-
end
|
|
215
|
-
|
|
216
|
-
def not_mergeable_yet?
|
|
217
|
-
mergeable.nil?
|
|
218
|
-
end
|
|
219
|
-
|
|
220
|
-
def schedule_refresh!
|
|
221
|
-
RefreshPullRequestJob.perform_later(self)
|
|
222
|
-
end
|
|
223
|
-
|
|
224
|
-
def closed?
|
|
225
|
-
state == "closed"
|
|
226
|
-
end
|
|
227
|
-
|
|
228
|
-
def merged_upstream?
|
|
229
|
-
closed? && merged_at
|
|
230
|
-
end
|
|
231
|
-
|
|
232
|
-
def refresh!
|
|
233
|
-
update!(github_pull_request: Shipit.github.api.pull_request(stack.github_repo_name, number))
|
|
234
|
-
head.refresh_statuses!
|
|
235
|
-
fetched! if fetching?
|
|
236
|
-
@comparison = nil
|
|
32
|
+
def emit_hooks(reason)
|
|
33
|
+
Hook.emit('pull_request', stack, action: reason, pull_request: self, stack: stack)
|
|
237
34
|
end
|
|
238
35
|
|
|
239
36
|
def github_pull_request=(github_pull_request)
|
|
240
37
|
self.github_id = github_pull_request.id
|
|
38
|
+
self.number = github_pull_request.number
|
|
241
39
|
self.api_url = github_pull_request.url
|
|
242
40
|
self.title = github_pull_request.title
|
|
243
41
|
self.state = github_pull_request.state
|
|
244
|
-
self.mergeable = github_pull_request.mergeable
|
|
245
42
|
self.additions = github_pull_request.additions
|
|
246
43
|
self.deletions = github_pull_request.deletions
|
|
247
|
-
self.
|
|
248
|
-
self.
|
|
249
|
-
|
|
250
|
-
self.base_ref = github_pull_request.base.ref
|
|
251
|
-
self.base_commit = find_or_create_commit_from_github_by_sha!(github_pull_request.base.sha, detached: true)
|
|
252
|
-
end
|
|
253
|
-
|
|
254
|
-
def merge_message
|
|
255
|
-
return title unless merge_requested_by
|
|
256
|
-
"#{title}\n\n#{MERGE_REQUEST_FIELD}: #{merge_requested_by.login}\n"
|
|
257
|
-
end
|
|
258
|
-
|
|
259
|
-
def stale?
|
|
260
|
-
return false unless base_commit
|
|
261
|
-
spec = stack.cached_deploy_spec
|
|
262
|
-
if max_branch_age = spec.max_divergence_age
|
|
263
|
-
return true if Time.now.utc - head.committed_at > max_branch_age
|
|
264
|
-
end
|
|
265
|
-
if commit_count_limit = spec.max_divergence_commits
|
|
266
|
-
return true if comparison.behind_by > commit_count_limit
|
|
44
|
+
self.user = User.find_or_create_by_login!(github_pull_request.user.login)
|
|
45
|
+
self.assignees = github_pull_request.assignees.map do |github_user|
|
|
46
|
+
User.find_or_create_by_login!(github_user.login)
|
|
267
47
|
end
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
def comparison
|
|
272
|
-
@comparison ||= Shipit.github.api.compare(
|
|
273
|
-
stack.github_repo_name,
|
|
274
|
-
base_ref,
|
|
275
|
-
head.sha,
|
|
276
|
-
)
|
|
277
|
-
end
|
|
278
|
-
|
|
279
|
-
private
|
|
280
|
-
|
|
281
|
-
def record_merge_status_change
|
|
282
|
-
@merge_status_changed ||= saved_change_to_attribute?(:merge_status)
|
|
283
|
-
end
|
|
284
|
-
|
|
285
|
-
def emit_hooks
|
|
286
|
-
return unless @merge_status_changed
|
|
287
|
-
@merge_status_changed = nil
|
|
288
|
-
Hook.emit('merge', stack, pull_request: self, status: merge_status, stack: stack)
|
|
48
|
+
self.labels = github_pull_request.labels.map(&:name)
|
|
49
|
+
self.head = find_or_create_commit_from_github_by_sha!(github_pull_request.head.sha)
|
|
289
50
|
end
|
|
290
51
|
|
|
291
|
-
def find_or_create_commit_from_github_by_sha!(sha
|
|
52
|
+
def find_or_create_commit_from_github_by_sha!(sha)
|
|
292
53
|
if commit = stack.commits.by_sha(sha)
|
|
293
54
|
commit
|
|
294
55
|
else
|
|
295
56
|
github_commit = Shipit.github.api.commit(stack.github_repo_name, sha)
|
|
296
|
-
stack.commits.create_from_github!(github_commit
|
|
57
|
+
stack.commits.create_from_github!(github_commit)
|
|
297
58
|
end
|
|
298
59
|
rescue ActiveRecord::RecordNotUnique
|
|
299
60
|
retry
|
|
@@ -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
|
|
@@ -14,6 +44,10 @@ module Shipit
|
|
|
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,6 +62,10 @@ 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
|
Shipit.github.url(full_name)
|
|
33
71
|
end
|
|
@@ -39,5 +77,21 @@ module Shipit
|
|
|
39
77
|
def git_url
|
|
40
78
|
"https://#{Shipit.github.domain}/#{owner}/#{name}.git"
|
|
41
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
|
|
42
96
|
end
|
|
43
97
|
end
|