shipit-engine 0.15.0 → 0.16.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/README.md +34 -1
- data/app/assets/javascripts/shipit/page_updater.js.coffee +63 -0
- data/app/assets/javascripts/shipit/stacks.js.coffee +9 -21
- data/app/assets/stylesheets/_base/_base.scss +2 -2
- data/app/assets/stylesheets/_base/_colors.scss +0 -1
- data/app/assets/stylesheets/_base/_forms.scss +14 -0
- data/app/assets/stylesheets/_pages/_commits.scss +16 -6
- data/app/assets/stylesheets/_pages/_settings.scss +8 -0
- data/app/assets/stylesheets/_pages/_stacks.scss +1 -1
- data/app/controllers/shipit/api/base_controller.rb +7 -3
- data/app/controllers/shipit/api/ccmenu_controller.rb +33 -0
- data/app/controllers/shipit/api/pull_requests_controller.rb +36 -0
- data/app/controllers/shipit/api/stacks_controller.rb +1 -0
- data/app/controllers/shipit/ccmenu_url_controller.rb +22 -0
- data/app/controllers/shipit/pull_requests_controller.rb +30 -0
- data/app/controllers/shipit/stacks_controller.rb +7 -2
- data/app/controllers/shipit/webhooks_controller.rb +1 -2
- data/app/helpers/shipit/github_url_helper.rb +8 -2
- data/app/helpers/shipit/shipit_helper.rb +9 -0
- data/app/helpers/shipit/stacks_helper.rb +22 -7
- data/app/jobs/shipit/background_job/unique.rb +19 -1
- data/app/jobs/shipit/cache_deploy_spec_job.rb +1 -1
- data/app/jobs/shipit/merge_pull_requests_job.rb +26 -0
- data/app/jobs/shipit/perform_task_job.rb +1 -1
- data/app/jobs/shipit/refresh_pull_request_job.rb +8 -0
- data/app/models/concerns/shipit/deferred_touch.rb +6 -1
- data/app/models/shipit/anonymous_user.rb +4 -0
- data/app/models/shipit/application_record.rb +5 -0
- data/app/models/shipit/commit.rb +51 -49
- data/app/models/shipit/commit_message.rb +32 -0
- data/app/models/shipit/deploy.rb +5 -0
- data/app/models/shipit/deploy_spec.rb +26 -1
- data/app/models/shipit/deploy_spec/file_system.rb +6 -1
- data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +10 -13
- data/app/models/shipit/deploy_spec/npm_discovery.rb +2 -1
- data/app/models/shipit/duration.rb +3 -1
- data/app/models/shipit/hook.rb +1 -0
- data/app/models/shipit/pull_request.rb +252 -0
- data/app/models/shipit/stack.rb +33 -17
- data/app/models/shipit/status.rb +1 -16
- data/app/models/shipit/status/common.rb +45 -0
- data/app/models/shipit/status/group.rb +82 -0
- data/app/models/shipit/status/missing.rb +30 -0
- data/app/models/shipit/status/unknown.rb +33 -0
- data/app/models/shipit/unlimited_api_client.rb +10 -0
- data/app/serializers/shipit/commit_serializer.rb +1 -1
- data/app/serializers/shipit/pull_request_serializer.rb +20 -0
- data/app/serializers/shipit/stack_serializer.rb +6 -2
- data/app/views/layouts/shipit.html.erb +41 -39
- data/app/views/shipit/ccmenu/project.xml.builder +13 -0
- data/app/views/shipit/commits/_commit.html.erb +1 -1
- data/app/views/shipit/deploys/_deploy.html.erb +1 -1
- data/app/views/shipit/pull_requests/_pull_request.html.erb +29 -0
- data/app/views/shipit/pull_requests/index.html.erb +20 -0
- data/app/views/shipit/shared/_author.html.erb +7 -0
- data/app/views/shipit/stacks/_header.html.erb +5 -0
- data/app/views/shipit/stacks/settings.html.erb +13 -0
- data/app/views/shipit/stacks/show.html.erb +3 -2
- data/app/views/shipit/statuses/_group.html.erb +1 -1
- data/app/views/shipit/tasks/_task.html.erb +1 -1
- data/config/initializers/inflections.rb +3 -0
- data/config/locales/en.yml +1 -3
- data/config/routes.rb +8 -0
- data/db/migrate/20170130113633_create_shipit_pull_requests.rb +25 -0
- data/db/migrate/20170208143657_add_pull_request_number_and_title_to_commits.rb +7 -0
- data/db/migrate/20170208154609_backfill_merge_commits.rb +13 -0
- data/db/migrate/20170209160355_add_branch_to_pull_requests.rb +5 -0
- data/db/migrate/20170215123538_add_merge_queue_enabled_to_stacks.rb +5 -0
- data/db/migrate/20170220152410_improve_users_indexing.rb +6 -0
- data/db/migrate/20170221102128_improve_tasks_indexing.rb +8 -0
- data/db/migrate/20170221130336_add_last_revalidated_at_on_pull_requests.rb +10 -0
- data/lib/shipit.rb +2 -0
- data/lib/shipit/version.rb +1 -1
- data/lib/tasks/cron.rake +1 -0
- data/test/controllers/api/ccmenu_controller_test.rb +57 -0
- data/test/controllers/api/commits_controller_test.rb +1 -1
- data/test/controllers/api/pull_requests_controller_test.rb +59 -0
- data/test/controllers/ccmenu_controller_test.rb +33 -0
- data/test/controllers/pull_requests_controller_test.rb +31 -0
- data/test/controllers/webhooks_controller_test.rb +3 -4
- data/test/dummy/config/environments/development.rb +3 -1
- data/test/dummy/data/stacks/shopify/junk/production/git/README.md +8 -0
- data/test/dummy/data/stacks/shopify/junk/production/git/circle.yml +4 -0
- data/test/dummy/data/stacks/shopify/junk/production/git/shipit.yml +4 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/schema.rb +45 -11
- data/test/dummy/db/seeds.rb +33 -10
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/fixtures/shipit/commits.yml +14 -0
- data/test/fixtures/shipit/pull_requests.yml +56 -0
- data/test/fixtures/shipit/stacks.yml +5 -1
- data/test/fixtures/shipit/statuses.yml +8 -0
- data/test/helpers/json_helper.rb +16 -14
- data/test/jobs/merge_pull_requests_job_test.rb +59 -0
- data/test/models/commits_test.rb +104 -49
- data/test/{unit → models}/deploy_spec_test.rb +138 -12
- data/test/models/deploys_test.rb +10 -4
- data/test/models/pull_request_test.rb +197 -0
- data/test/models/stacks_test.rb +46 -53
- data/test/models/status/group_test.rb +44 -0
- data/test/models/status/missing_test.rb +23 -0
- data/test/models/status_test.rb +3 -6
- data/test/unit/csv_serializer_test.rb +10 -2
- metadata +57 -12
- data/app/models/shipit/missing_status.rb +0 -21
- data/app/models/shipit/status_group.rb +0 -35
- data/app/models/shipit/unknown_status.rb +0 -48
- data/app/views/shipit/commits/_commit_author.html.erb +0 -7
- data/test/models/missing_status_test.rb +0 -23
- data/test/models/status_group_test.rb +0 -26
|
@@ -27,8 +27,7 @@ module Shipit
|
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
def state
|
|
30
|
-
if
|
|
31
|
-
commit = stack.commits.find_by_sha!(params.sha)
|
|
30
|
+
if commit = stack.commits.find_by_sha(params.sha)
|
|
32
31
|
commit.create_status_from_github!(params)
|
|
33
32
|
end
|
|
34
33
|
head :ok
|
|
@@ -40,8 +40,14 @@ module Shipit
|
|
|
40
40
|
github_repo_url(commit.stack.repo_owner, commit.stack.repo_name, 'commit', commit.sha)
|
|
41
41
|
end
|
|
42
42
|
|
|
43
|
-
def github_pull_request_url(
|
|
44
|
-
|
|
43
|
+
def github_pull_request_url(pull_request_or_commit)
|
|
44
|
+
stack = pull_request_or_commit.stack
|
|
45
|
+
number = if pull_request_or_commit.respond_to?(:pull_request_number)
|
|
46
|
+
pull_request_or_commit.pull_request_number
|
|
47
|
+
else
|
|
48
|
+
pull_request_or_commit.number
|
|
49
|
+
end
|
|
50
|
+
github_repo_url(stack.repo_owner, stack.repo_name, 'pull', number)
|
|
45
51
|
end
|
|
46
52
|
|
|
47
53
|
def link_to_github_deploy(deploy)
|
|
@@ -1,5 +1,14 @@
|
|
|
1
1
|
module Shipit
|
|
2
2
|
module ShipitHelper
|
|
3
|
+
def subscribe(url, *selectors)
|
|
4
|
+
content_for(:update_subscription) do
|
|
5
|
+
[
|
|
6
|
+
tag('meta', name: 'subscription-channel', content: url),
|
|
7
|
+
*selectors.map { |s| tag('meta', name: 'subscription-selector', content: s) },
|
|
8
|
+
].join("\n").html_safe
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
|
|
3
12
|
def emojify(content)
|
|
4
13
|
h(content).to_str.gsub(/:([\w+-]+):/) do |match|
|
|
5
14
|
if emoji = Emoji.find_by_alias($1)
|
|
@@ -33,16 +33,26 @@ module Shipit
|
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def github_change_url(commit)
|
|
36
|
-
commit.
|
|
36
|
+
if commit.pull_request?
|
|
37
|
+
github_pull_request_url(commit)
|
|
38
|
+
else
|
|
39
|
+
github_commit_url(commit)
|
|
40
|
+
end
|
|
37
41
|
end
|
|
38
42
|
|
|
39
|
-
def render_commit_message(
|
|
40
|
-
message =
|
|
41
|
-
content_tag(:span, emojify(message
|
|
43
|
+
def render_commit_message(pull_request_or_commit)
|
|
44
|
+
message = pull_request_or_commit.title.to_s.truncate(COMMIT_TITLE_LENGTH)
|
|
45
|
+
content_tag(:span, emojify(message), class: 'event-message')
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def render_pull_request_title_with_link(pull_request)
|
|
49
|
+
message = render_commit_message(pull_request)
|
|
50
|
+
link_to(message, github_pull_request_url(pull_request), target: '_blank')
|
|
42
51
|
end
|
|
43
52
|
|
|
44
53
|
def render_commit_message_with_link(commit)
|
|
45
|
-
|
|
54
|
+
message = render_commit_message(commit)
|
|
55
|
+
link_to(message, github_change_url(commit), target: '_blank')
|
|
46
56
|
end
|
|
47
57
|
|
|
48
58
|
def render_commit_id_link(commit)
|
|
@@ -53,8 +63,13 @@ module Shipit
|
|
|
53
63
|
end
|
|
54
64
|
end
|
|
55
65
|
|
|
56
|
-
def pull_request_link(
|
|
57
|
-
|
|
66
|
+
def pull_request_link(pull_request_or_commit)
|
|
67
|
+
number = if pull_request_or_commit.respond_to?(:pull_request_number)
|
|
68
|
+
pull_request_or_commit.pull_request_number
|
|
69
|
+
else
|
|
70
|
+
pull_request_or_commit.number
|
|
71
|
+
end
|
|
72
|
+
link_to("##{number}", github_pull_request_url(pull_request_or_commit), target: '_blank', class: 'number')
|
|
58
73
|
end
|
|
59
74
|
|
|
60
75
|
def render_raw_commit_id_link(commit)
|
|
@@ -2,12 +2,12 @@ module Shipit
|
|
|
2
2
|
class BackgroundJob
|
|
3
3
|
module Unique
|
|
4
4
|
extend ActiveSupport::Concern
|
|
5
|
-
|
|
6
5
|
DEFAULT_TIMEOUT = 10
|
|
7
6
|
|
|
8
7
|
included do
|
|
9
8
|
around_perform { |job, block| job.acquire_lock(&block) }
|
|
10
9
|
cattr_accessor :lock_timeout
|
|
10
|
+
on_duplicate :retry
|
|
11
11
|
end
|
|
12
12
|
|
|
13
13
|
def acquire_lock(&block)
|
|
@@ -18,11 +18,29 @@ module Shipit
|
|
|
18
18
|
timeout: self.class.lock_timeout || 0,
|
|
19
19
|
)
|
|
20
20
|
mutex.lock(&block)
|
|
21
|
+
rescue Redis::Lock::LockTimeout
|
|
22
|
+
raise unless self.class.drop_duplicate_jobs?
|
|
21
23
|
end
|
|
22
24
|
|
|
23
25
|
def lock_key(*args)
|
|
24
26
|
ActiveJob::Arguments.serialize([self.class.name] + args).join('-')
|
|
25
27
|
end
|
|
28
|
+
|
|
29
|
+
module ClassMethods
|
|
30
|
+
ACTIONS = %i(retry drop).freeze
|
|
31
|
+
ACTIONS_LIST = ACTIONS.map(&:inspect).join(', ').freeze
|
|
32
|
+
def on_duplicate(action)
|
|
33
|
+
unless ACTIONS.include?(action)
|
|
34
|
+
raise ArgumentsError, "invalid action: #{action.inspect}, should be one of #{ACTIONS_LIST}"
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
@on_duplicate = action
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def drop_duplicate_jobs?
|
|
41
|
+
@on_duplicate == :drop
|
|
42
|
+
end
|
|
43
|
+
end
|
|
26
44
|
end
|
|
27
45
|
end
|
|
28
46
|
end
|
|
@@ -6,7 +6,7 @@ module Shipit
|
|
|
6
6
|
return if stack.inaccessible?
|
|
7
7
|
|
|
8
8
|
commands = Commands.for(stack)
|
|
9
|
-
commands.with_temporary_working_directory(commit: stack.commits.last) do |path|
|
|
9
|
+
commands.with_temporary_working_directory(commit: stack.commits.reachable.last) do |path|
|
|
10
10
|
stack.update!(cached_deploy_spec: DeploySpec::FileSystem.new(path, stack.environment))
|
|
11
11
|
end
|
|
12
12
|
end
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
module Shipit
|
|
2
|
+
class MergePullRequestsJob < BackgroundJob
|
|
3
|
+
include BackgroundJob::Unique
|
|
4
|
+
on_duplicate :drop
|
|
5
|
+
|
|
6
|
+
def perform(stack)
|
|
7
|
+
pull_requests = stack.pull_requests.to_be_merged.to_a
|
|
8
|
+
pull_requests.each do |pull_request|
|
|
9
|
+
pull_request.refresh!
|
|
10
|
+
pull_request.reject_unless_mergeable!
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
return false unless stack.allows_merges?
|
|
14
|
+
|
|
15
|
+
pull_requests.select(&:pending?).each do |pull_request|
|
|
16
|
+
pull_request.refresh!
|
|
17
|
+
begin
|
|
18
|
+
pull_request.merge!
|
|
19
|
+
rescue PullRequest::NotReady
|
|
20
|
+
MergePullRequestsJob.set(wait: 10.seconds).perform_later(stack)
|
|
21
|
+
return false
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
@@ -77,7 +77,12 @@ module Shipit
|
|
|
77
77
|
|
|
78
78
|
def schedule_touches
|
|
79
79
|
return unless self.class.deferred_touches
|
|
80
|
-
|
|
80
|
+
deferred_touches = self.class.deferred_touches.reject do |m, _fk, _a|
|
|
81
|
+
ActiveRecord::NoTouching.applied_to?(m.constantize)
|
|
82
|
+
end
|
|
83
|
+
return if deferred_touches.empty?
|
|
84
|
+
|
|
85
|
+
touches = deferred_touches.map { |m, fk, a| [m, self[fk], a].join('|') }
|
|
81
86
|
Shipit.redis.sadd(SET_KEY, touches)
|
|
82
87
|
if DeferredTouch.enabled
|
|
83
88
|
Rails.cache.fetch(CACHE_KEY, expires_in: THROTTLE_TTL) do
|
data/app/models/shipit/commit.rb
CHANGED
|
@@ -8,9 +8,11 @@ module Shipit
|
|
|
8
8
|
has_many :deploys
|
|
9
9
|
has_many :statuses, -> { order(created_at: :desc) }, dependent: :destroy
|
|
10
10
|
has_many :commit_deployments, dependent: :destroy
|
|
11
|
+
belongs_to :pull_request, inverse_of: :merge_commit
|
|
11
12
|
|
|
12
13
|
deferred_touch stack: :updated_at
|
|
13
14
|
|
|
15
|
+
before_create :identify_pull_request
|
|
14
16
|
after_commit { broadcast_update }
|
|
15
17
|
after_create { stack.update_undeployed_commits_count }
|
|
16
18
|
|
|
@@ -21,7 +23,8 @@ module Shipit
|
|
|
21
23
|
|
|
22
24
|
scope :reachable, -> { where(detached: false) }
|
|
23
25
|
|
|
24
|
-
delegate :broadcast_update, :github_repo_name,
|
|
26
|
+
delegate :broadcast_update, :github_repo_name, :hidden_statuses, :required_statuses,
|
|
27
|
+
:soft_failing_statuses, to: :stack
|
|
25
28
|
|
|
26
29
|
def self.newer_than(commit)
|
|
27
30
|
return all unless commit
|
|
@@ -69,12 +72,14 @@ module Shipit
|
|
|
69
72
|
end
|
|
70
73
|
|
|
71
74
|
def reload(*)
|
|
72
|
-
@
|
|
75
|
+
@status = nil
|
|
73
76
|
super
|
|
74
77
|
end
|
|
75
78
|
|
|
76
|
-
def self.create_from_github!(commit)
|
|
77
|
-
from_github(commit)
|
|
79
|
+
def self.create_from_github!(commit, extra_attributes = {})
|
|
80
|
+
record = from_github(commit)
|
|
81
|
+
record.update!(extra_attributes)
|
|
82
|
+
record
|
|
78
83
|
end
|
|
79
84
|
|
|
80
85
|
def schedule_refresh_statuses!
|
|
@@ -112,30 +117,26 @@ module Shipit
|
|
|
112
117
|
children.detach!
|
|
113
118
|
end
|
|
114
119
|
|
|
115
|
-
def
|
|
116
|
-
|
|
120
|
+
def pull_request?
|
|
121
|
+
pull_request_number.present?
|
|
117
122
|
end
|
|
118
123
|
|
|
119
|
-
def pull_request_number
|
|
120
|
-
|
|
124
|
+
def pull_request_number # TODO: remove in a few versions when it is assumed the commits table was backfilled
|
|
125
|
+
super || message_parser.pull_request_number
|
|
121
126
|
end
|
|
122
127
|
|
|
123
|
-
def
|
|
124
|
-
|
|
128
|
+
def title
|
|
129
|
+
pull_request_title || message
|
|
125
130
|
end
|
|
126
131
|
|
|
127
|
-
def
|
|
128
|
-
|
|
132
|
+
def pull_request_title # TODO: remove in a few versions when it is assumed the commits table was backfilled
|
|
133
|
+
super || message_parser.pull_request_title
|
|
129
134
|
end
|
|
130
135
|
|
|
131
136
|
def short_sha
|
|
132
137
|
sha[0..9]
|
|
133
138
|
end
|
|
134
139
|
|
|
135
|
-
def parsed
|
|
136
|
-
@parsed ||= message.match(/\AMerge pull request #(?<pr_id>\d+) from [\w\-.\/]+\n\n(?<pr_title>.*)/)
|
|
137
|
-
end
|
|
138
|
-
|
|
139
140
|
def schedule_continuous_delivery
|
|
140
141
|
return unless deployable? && stack.continuous_deployment? && stack.deployable?
|
|
141
142
|
ContinuousDeliveryJob.perform_later(stack)
|
|
@@ -156,30 +157,8 @@ module Shipit
|
|
|
156
157
|
)
|
|
157
158
|
end
|
|
158
159
|
|
|
159
|
-
def visible_statuses
|
|
160
|
-
stack.filter_visible_statuses(last_statuses).presence || [UnknownStatus.new(self)]
|
|
161
|
-
end
|
|
162
|
-
|
|
163
|
-
def meaningful_statuses
|
|
164
|
-
stack.filter_meaningful_statuses(last_statuses).presence || [UnknownStatus.new(self)]
|
|
165
|
-
end
|
|
166
|
-
|
|
167
|
-
def last_statuses
|
|
168
|
-
@last_statuses ||= statuses.to_a.uniq(&:context).sort_by(&:context).presence || [UnknownStatus.new(self)]
|
|
169
|
-
end
|
|
170
|
-
|
|
171
160
|
def status
|
|
172
|
-
|
|
173
|
-
status = visibles.size > 1 ? StatusGroup.new(significant_status, visibles) : visibles.first
|
|
174
|
-
missing_statuses.empty? ? status : MissingStatus.new(status, missing_statuses)
|
|
175
|
-
end
|
|
176
|
-
|
|
177
|
-
def significant_status
|
|
178
|
-
statuses = meaningful_statuses
|
|
179
|
-
return UnknownStatus.new(self) if statuses.empty?
|
|
180
|
-
return statuses.first if statuses.all?(&:success?)
|
|
181
|
-
non_success_statuses = statuses.reject(&:success?)
|
|
182
|
-
non_success_statuses.reject(&:pending?).first || non_success_statuses.first || UnknownStatus.new(self)
|
|
161
|
+
@status ||= Status::Group.compact(self, statuses)
|
|
183
162
|
end
|
|
184
163
|
|
|
185
164
|
def deployed?
|
|
@@ -190,24 +169,47 @@ module Shipit
|
|
|
190
169
|
stack.deploys.unsuccessful.where(until_commit_id: id).any?
|
|
191
170
|
end
|
|
192
171
|
|
|
172
|
+
def identify_pull_request
|
|
173
|
+
return unless message_parser.pull_request?
|
|
174
|
+
if pull_request = stack.pull_requests.find_by_number(message_parser.pull_request_number)
|
|
175
|
+
self.pull_request = pull_request
|
|
176
|
+
self.pull_request_number = pull_request.number
|
|
177
|
+
self.pull_request_title = pull_request.title
|
|
178
|
+
self.author = pull_request.merge_requested_by if pull_request.merge_requested_by
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
self.pull_request_number = message_parser.pull_request_number unless self[:pull_request_number]
|
|
182
|
+
self.pull_request_title = message_parser.pull_request_title unless self[:pull_request_title]
|
|
183
|
+
end
|
|
184
|
+
|
|
193
185
|
private
|
|
194
186
|
|
|
187
|
+
def message_parser
|
|
188
|
+
@message_parser ||= CommitMessage.new(message)
|
|
189
|
+
end
|
|
190
|
+
|
|
195
191
|
def add_status
|
|
196
|
-
|
|
192
|
+
already_deployed = deployed?
|
|
193
|
+
|
|
194
|
+
previous_status = status
|
|
197
195
|
yield
|
|
198
196
|
reload # to get the statuses into the right order (since sorted :desc)
|
|
199
|
-
new_status =
|
|
197
|
+
new_status = status
|
|
200
198
|
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
Hook.emit(:deployable_status, stack, payload.merge(deployable_status: new_status))
|
|
199
|
+
unless already_deployed
|
|
200
|
+
payload = {commit: self, stack: stack, status: new_status.state}
|
|
201
|
+
Hook.emit(:commit_status, stack, payload.merge(commit_status: new_status)) if previous_status != new_status
|
|
205
202
|
end
|
|
206
|
-
new_status
|
|
207
|
-
end
|
|
208
203
|
|
|
209
|
-
|
|
210
|
-
|
|
204
|
+
if previous_status.simple_state != new_status.simple_state
|
|
205
|
+
if !already_deployed && (!new_status.pending? || previous_status.unknown?)
|
|
206
|
+
Hook.emit(:deployable_status, stack, payload.merge(deployable_status: new_status))
|
|
207
|
+
end
|
|
208
|
+
if new_status.pending? || new_status.success?
|
|
209
|
+
stack.schedule_merges
|
|
210
|
+
end
|
|
211
|
+
end
|
|
212
|
+
new_status
|
|
211
213
|
end
|
|
212
214
|
end
|
|
213
215
|
end
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
module Shipit
|
|
2
|
+
class CommitMessage
|
|
3
|
+
GITHUB_MERGE_COMMIT_PATTERN = %r{\AMerge pull request #(?<pr_id>\d+) from [\w\-./]+\n\n(?<pr_title>.*)}
|
|
4
|
+
|
|
5
|
+
def initialize(text)
|
|
6
|
+
@text = text
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def pull_request?
|
|
10
|
+
!!parsed
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def pull_request_number
|
|
14
|
+
parsed && parsed['pr_id'].to_i
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def pull_request_title
|
|
18
|
+
parsed && parsed['pr_title']
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def to_s
|
|
22
|
+
@text
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
private
|
|
26
|
+
|
|
27
|
+
def parsed
|
|
28
|
+
return @parsed if defined?(@parsed)
|
|
29
|
+
@parsed = to_s.match(GITHUB_MERGE_COMMIT_PATTERN)
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
data/app/models/shipit/deploy.rb
CHANGED
|
@@ -6,6 +6,7 @@ module Shipit
|
|
|
6
6
|
|
|
7
7
|
state_machine :status do
|
|
8
8
|
after_transition to: :success, do: :schedule_continuous_delivery
|
|
9
|
+
after_transition to: :success, do: :schedule_merges
|
|
9
10
|
after_transition to: :success, do: :update_undeployed_commits_count
|
|
10
11
|
after_transition to: :aborted, do: :trigger_revert_if_required
|
|
11
12
|
after_transition any => any, do: :update_commit_deployments
|
|
@@ -163,6 +164,10 @@ module Shipit
|
|
|
163
164
|
self.deletions = commits.map(&:deletions).compact.sum
|
|
164
165
|
end
|
|
165
166
|
|
|
167
|
+
def schedule_merges
|
|
168
|
+
stack.schedule_merges
|
|
169
|
+
end
|
|
170
|
+
|
|
166
171
|
def schedule_continuous_delivery
|
|
167
172
|
return unless stack.continuous_deployment?
|
|
168
173
|
ContinuousDeliveryJob.perform_later(stack)
|
|
@@ -64,7 +64,7 @@ module Shipit
|
|
|
64
64
|
alias_method :dependencies_steps!, :dependencies_steps
|
|
65
65
|
|
|
66
66
|
def maximum_commits_per_deploy
|
|
67
|
-
config('deploy', 'max_commits')
|
|
67
|
+
config('deploy', 'max_commits') { 8 }
|
|
68
68
|
end
|
|
69
69
|
|
|
70
70
|
def pause_between_deploys
|
|
@@ -143,6 +143,31 @@ module Shipit
|
|
|
143
143
|
Array.wrap(config('ci', 'allow_failures'))
|
|
144
144
|
end
|
|
145
145
|
|
|
146
|
+
def pull_request_required_statuses
|
|
147
|
+
if config('merge', 'require') || config('merge', 'ignore')
|
|
148
|
+
Array.wrap(config('merge', 'require'))
|
|
149
|
+
else
|
|
150
|
+
required_statuses
|
|
151
|
+
end
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
def pull_request_ignored_statuses
|
|
155
|
+
if config('merge', 'require') || config('merge', 'ignore')
|
|
156
|
+
Array.wrap(config('merge', 'ignore'))
|
|
157
|
+
else
|
|
158
|
+
soft_failing_statuses | hidden_statuses
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
|
|
162
|
+
def revalidate_pull_requests_after
|
|
163
|
+
if timeout = config('merge', 'revalidate_after')
|
|
164
|
+
begin
|
|
165
|
+
Duration.parse(timeout)
|
|
166
|
+
rescue Duration::ParseError
|
|
167
|
+
end
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
|
|
146
171
|
def review_checks
|
|
147
172
|
config('review', 'checks') || []
|
|
148
173
|
end
|