shipit-engine 0.29.0 → 0.30.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 +37 -2
- data/app/assets/images/archive-solid.svg +1 -0
- data/app/assets/stylesheets/_pages/_stacks.scss +76 -0
- data/app/controllers/shipit/api/stacks_controller.rb +20 -1
- data/app/controllers/shipit/api_clients_controller.rb +49 -0
- data/app/controllers/shipit/merge_status_controller.rb +8 -4
- data/app/controllers/shipit/stacks_controller.rb +58 -9
- data/app/controllers/shipit/webhooks_controller.rb +2 -130
- data/app/helpers/shipit/stacks_helper.rb +4 -0
- data/app/jobs/shipit/background_job/unique.rb +3 -1
- data/app/jobs/shipit/continuous_delivery_job.rb +1 -0
- data/app/jobs/shipit/destroy_stack_job.rb +2 -2
- data/app/models/shipit/commit.rb +21 -9
- data/app/models/shipit/commit_deployment.rb +15 -11
- data/app/models/shipit/commit_deployment_status.rb +6 -2
- data/app/models/shipit/deploy.rb +48 -7
- data/app/models/shipit/deploy_stats.rb +57 -0
- data/app/models/shipit/repository.rb +38 -0
- data/app/models/shipit/stack.rb +41 -34
- data/app/models/shipit/task.rb +26 -4
- data/app/models/shipit/webhooks.rb +32 -0
- data/app/models/shipit/webhooks/handlers/check_suite_handler.rb +19 -0
- data/app/models/shipit/webhooks/handlers/handler.rb +40 -0
- data/app/models/shipit/webhooks/handlers/membership_handler.rb +45 -0
- data/app/models/shipit/webhooks/handlers/push_handler.rb +20 -0
- data/app/models/shipit/webhooks/handlers/status_handler.rb +26 -0
- data/app/serializers/shipit/stack_serializer.rb +6 -1
- data/app/validators/ascii_only_validator.rb +3 -3
- data/app/views/layouts/_head.html.erb +0 -0
- data/app/views/layouts/shipit.html.erb +4 -2
- data/app/views/shipit/api_clients/index.html.erb +36 -0
- data/app/views/shipit/api_clients/new.html.erb +33 -0
- data/app/views/shipit/api_clients/show.html.erb +35 -0
- data/app/views/shipit/merge_status/logged_out.erb +1 -1
- data/app/views/shipit/stacks/_header.html.erb +12 -7
- data/app/views/shipit/stacks/_links.html.erb +1 -0
- data/app/views/shipit/stacks/index.html.erb +7 -2
- data/app/views/shipit/stacks/settings.html.erb +19 -0
- data/app/views/shipit/stacks/statistics.html.erb +82 -0
- data/config/locales/en.yml +14 -2
- data/config/routes.rb +4 -0
- data/db/migrate/20191209231045_create_shipit_repositories.rb +12 -0
- data/db/migrate/20191209231307_add_repository_reference_to_stacks.rb +15 -0
- data/db/migrate/20191216162728_backfill_repository_data.rb +22 -0
- data/db/migrate/20191216163010_remove_repository_information_from_stacks.rb +20 -0
- data/db/migrate/20191219205202_add_archived_since_to_stacks.rb +6 -0
- data/db/migrate/20200102175621_optional_task_commits.rb +6 -0
- data/db/migrate/20200109132519_add_sha_to_commit_deployments.rb +5 -0
- data/lib/shipit/github_app.rb +32 -3
- data/lib/shipit/task_commands.rb +10 -2
- data/lib/shipit/version.rb +1 -1
- data/test/controllers/api/ccmenu_controller_test.rb +1 -1
- data/test/controllers/api/stacks_controller_test.rb +14 -6
- data/test/controllers/api_clients_controller_test.rb +103 -0
- data/test/controllers/merge_status_controller_test.rb +21 -4
- data/test/controllers/stacks_controller_test.rb +35 -0
- data/test/controllers/webhooks_controller_test.rb +26 -0
- data/test/dummy/config/environments/development.rb +22 -4
- data/test/dummy/db/schema.rb +17 -6
- data/test/dummy/db/seeds.rb +20 -6
- data/test/fixtures/shipit/commit_deployment_statuses.yml +4 -4
- data/test/fixtures/shipit/commit_deployments.yml +8 -8
- data/test/fixtures/shipit/commits.yml +23 -0
- data/test/fixtures/shipit/repositories.yml +23 -0
- data/test/fixtures/shipit/stacks.yml +100 -16
- data/test/fixtures/shipit/tasks.yml +66 -3
- data/test/jobs/destroy_stack_job_test.rb +9 -0
- data/test/models/commit_deployment_status_test.rb +33 -4
- data/test/models/commit_deployment_test.rb +8 -11
- data/test/models/commits_test.rb +22 -2
- data/test/models/deploy_stats_test.rb +112 -0
- data/test/models/deploys_test.rb +55 -17
- data/test/models/pull_request_test.rb +1 -1
- data/test/models/shipit/repository_test.rb +76 -0
- data/test/models/shipit/wehbooks/handlers_test.rb +26 -0
- data/test/models/stacks_test.rb +44 -51
- data/test/models/undeployed_commits_test.rb +13 -0
- data/test/test_helper.rb +3 -1
- data/test/unit/deploy_commands_test.rb +9 -0
- data/test/unit/github_app_test.rb +136 -0
- metadata +161 -128
@@ -4,6 +4,8 @@ module Shipit
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
DEFAULT_TIMEOUT = 10
|
6
6
|
|
7
|
+
ConcurrentJobError = Class.new(StandardError)
|
8
|
+
|
7
9
|
included do
|
8
10
|
around_perform { |job, block| job.acquire_lock(&block) }
|
9
11
|
cattr_accessor :lock_timeout
|
@@ -19,7 +21,7 @@ module Shipit
|
|
19
21
|
)
|
20
22
|
mutex.lock(&block)
|
21
23
|
rescue Redis::Lock::LockTimeout
|
22
|
-
raise unless self.class.drop_duplicate_jobs?
|
24
|
+
raise ConcurrentJobError unless self.class.drop_duplicate_jobs?
|
23
25
|
end
|
24
26
|
|
25
27
|
def lock_key(*args)
|
@@ -17,7 +17,8 @@ module Shipit
|
|
17
17
|
def perform(stack)
|
18
18
|
Shipit::ApiClient.where(stack_id: stack.id).delete_all
|
19
19
|
commits_ids = Shipit::Commit.where(stack_id: stack.id).pluck(:id)
|
20
|
-
|
20
|
+
tasks_ids = Shipit::Task.where(stack_id: stack.id).pluck(:id)
|
21
|
+
commit_deployments_ids = Shipit::CommitDeployment.where(task_id: tasks_ids).pluck(:id)
|
21
22
|
Shipit::CommitDeploymentStatus.where(commit_deployment_id: commit_deployments_ids).delete_all
|
22
23
|
Shipit::CommitDeployment.where(id: commit_deployments_ids).delete_all
|
23
24
|
Shipit::Status.where(commit_id: commits_ids).delete_all
|
@@ -25,7 +26,6 @@ module Shipit
|
|
25
26
|
Shipit::GithubHook.where(stack_id: stack.id).destroy_all
|
26
27
|
Shipit::Hook.where(stack_id: stack.id).delete_all
|
27
28
|
Shipit::PullRequest.where(stack_id: stack.id).delete_all
|
28
|
-
tasks_ids = Shipit::Task.where(stack_id: stack.id).pluck(:id)
|
29
29
|
tasks_ids.each_slice(100) do |ids|
|
30
30
|
Shipit::OutputChunk.where(task_id: ids).delete_all
|
31
31
|
Shipit::Task.where(id: ids).delete_all
|
data/app/models/shipit/commit.rb
CHANGED
@@ -2,6 +2,8 @@ module Shipit
|
|
2
2
|
class Commit < ActiveRecord::Base
|
3
3
|
include DeferredTouch
|
4
4
|
|
5
|
+
RECENT_COMMIT_THRESHOLD = 10.seconds
|
6
|
+
|
5
7
|
AmbiguousRevision = Class.new(StandardError)
|
6
8
|
|
7
9
|
belongs_to :stack
|
@@ -102,6 +104,14 @@ module Shipit
|
|
102
104
|
)
|
103
105
|
end
|
104
106
|
|
107
|
+
def message=(message)
|
108
|
+
limit = self.class.columns_hash['message'].limit
|
109
|
+
if limit && message && message.size > limit
|
110
|
+
message = message.slice(0, limit)
|
111
|
+
end
|
112
|
+
super(message)
|
113
|
+
end
|
114
|
+
|
105
115
|
def reload(*)
|
106
116
|
@status = nil
|
107
117
|
super
|
@@ -126,7 +136,9 @@ module Shipit
|
|
126
136
|
end
|
127
137
|
|
128
138
|
def refresh_statuses!
|
129
|
-
github_statuses = stack.handle_github_redirections
|
139
|
+
github_statuses = stack.handle_github_redirections do
|
140
|
+
Shipit.github.api.statuses(github_repo_name, sha, per_page: 100)
|
141
|
+
end
|
130
142
|
github_statuses.each do |status|
|
131
143
|
create_status_from_github!(status)
|
132
144
|
end
|
@@ -177,13 +189,7 @@ module Shipit
|
|
177
189
|
def active?
|
178
190
|
return false unless stack.active_task?
|
179
191
|
|
180
|
-
|
181
|
-
|
182
|
-
if active_task.since_commit == active_task.until_commit
|
183
|
-
id == active_task.since_commit.id
|
184
|
-
else
|
185
|
-
id > active_task.since_commit.id && id <= active_task.until_commit.id
|
186
|
-
end
|
192
|
+
stack.active_task.includes_commit?(self)
|
187
193
|
end
|
188
194
|
|
189
195
|
def deployable?
|
@@ -242,7 +248,9 @@ module Shipit
|
|
242
248
|
|
243
249
|
def schedule_continuous_delivery
|
244
250
|
return unless deployable? && stack.continuous_deployment? && stack.deployable?
|
245
|
-
|
251
|
+
# This buffer is to allow for statuses and checks to be refreshed before evaluating if the commit is deployable
|
252
|
+
# - e.g. if the commit was fast-forwarded with already passing CI.
|
253
|
+
ContinuousDeliveryJob.set(wait: RECENT_COMMIT_THRESHOLD).perform_later(stack)
|
246
254
|
end
|
247
255
|
|
248
256
|
def github_commit
|
@@ -311,6 +319,10 @@ module Shipit
|
|
311
319
|
update!(locked: false, lock_author: nil)
|
312
320
|
end
|
313
321
|
|
322
|
+
def recently_pushed?
|
323
|
+
created_at > RECENT_COMMIT_THRESHOLD.ago
|
324
|
+
end
|
325
|
+
|
314
326
|
private
|
315
327
|
|
316
328
|
def message_parser
|
@@ -1,6 +1,5 @@
|
|
1
1
|
module Shipit
|
2
2
|
class CommitDeployment < ActiveRecord::Base
|
3
|
-
belongs_to :commit
|
4
3
|
belongs_to :task
|
5
4
|
has_many :statuses, dependent: :destroy, class_name: 'CommitDeploymentStatus'
|
6
5
|
|
@@ -9,11 +8,10 @@ module Shipit
|
|
9
8
|
delegate :stack, :author, to: :task
|
10
9
|
|
11
10
|
def create_on_github!
|
12
|
-
return unless commit.pull_request?
|
13
|
-
|
14
11
|
create_deployment_on_github!
|
15
12
|
statuses.order(id: :asc).each(&:create_on_github!)
|
16
|
-
rescue Octokit::NotFound, Octokit::Forbidden
|
13
|
+
rescue Octokit::NotFound, Octokit::Forbidden => error
|
14
|
+
Rails.logger.warn("Got #{error.class.name} creating deployment or statuses: #{error.message}")
|
17
15
|
# If no one can create the deployment we can only give up
|
18
16
|
end
|
19
17
|
|
@@ -34,25 +32,31 @@ module Shipit
|
|
34
32
|
update!(github_id: response.id, api_url: response.url)
|
35
33
|
end
|
36
34
|
|
37
|
-
def pull_request_head
|
38
|
-
pull_request = Shipit.github.api.pull_request(stack.github_repo_name, commit.pull_request_number)
|
39
|
-
pull_request.head.sha
|
40
|
-
end
|
41
|
-
|
42
35
|
def schedule_create_on_github
|
43
36
|
CreateOnGithubJob.perform_later(self)
|
44
37
|
end
|
45
38
|
|
39
|
+
def short_sha
|
40
|
+
sha[0..9]
|
41
|
+
end
|
42
|
+
|
46
43
|
private
|
47
44
|
|
48
45
|
def create_deployment_on_github(client)
|
49
46
|
client.create_deployment(
|
50
47
|
stack.github_repo_name,
|
51
|
-
|
48
|
+
sha,
|
52
49
|
auto_merge: false,
|
53
50
|
required_contexts: [],
|
54
|
-
description: "Via Shipit",
|
51
|
+
description: "Via #{Shipit.app_name}",
|
55
52
|
environment: stack.environment,
|
53
|
+
payload: {
|
54
|
+
shipit: {
|
55
|
+
task_id: task.id,
|
56
|
+
from_sha: task.since_commit.sha,
|
57
|
+
to_sha: task.until_commit.sha,
|
58
|
+
},
|
59
|
+
},
|
56
60
|
)
|
57
61
|
end
|
58
62
|
end
|
@@ -1,5 +1,7 @@
|
|
1
1
|
module Shipit
|
2
2
|
class CommitDeploymentStatus < ActiveRecord::Base
|
3
|
+
DESCRIPTION_CHARACTER_LIMIT_ON_GITHUB = 140
|
4
|
+
|
3
5
|
belongs_to :commit_deployment
|
4
6
|
|
5
7
|
after_commit :schedule_create_on_github, on: :create
|
@@ -25,7 +27,7 @@ module Shipit
|
|
25
27
|
def description
|
26
28
|
I18n.t(
|
27
29
|
"deployment_description.#{task_type}.#{status}",
|
28
|
-
sha: task.until_commit.
|
30
|
+
sha: task.until_commit.short_sha,
|
29
31
|
author: task.author.login,
|
30
32
|
stack: stack.to_param,
|
31
33
|
)
|
@@ -45,8 +47,10 @@ module Shipit
|
|
45
47
|
client.create_deployment_status(
|
46
48
|
commit_deployment.api_url,
|
47
49
|
status,
|
50
|
+
accept: 'application/vnd.github.flash-preview+json',
|
48
51
|
target_url: url_helpers.stack_deploy_url(stack, task),
|
49
|
-
description: description,
|
52
|
+
description: description.truncate(DESCRIPTION_CHARACTER_LIMIT_ON_GITHUB),
|
53
|
+
environment_url: stack.deploy_url,
|
50
54
|
)
|
51
55
|
end
|
52
56
|
|
data/app/models/shipit/deploy.rb
CHANGED
@@ -14,20 +14,41 @@ module Shipit
|
|
14
14
|
after_transition any => any, do: :update_last_deploy_time
|
15
15
|
end
|
16
16
|
|
17
|
+
belongs_to :until_commit, class_name: 'Commit', required: true, inverse_of: :deploys
|
18
|
+
belongs_to :since_commit, class_name: 'Commit', required: true, inverse_of: :deploys
|
17
19
|
has_many :commit_deployments, dependent: :destroy, inverse_of: :task, foreign_key: :task_id do
|
18
20
|
GITHUB_STATUSES = {
|
19
21
|
'pending' => 'pending',
|
22
|
+
'running' => 'in_progress',
|
20
23
|
'failed' => 'failure',
|
24
|
+
'timedout' => 'failure',
|
21
25
|
'success' => 'success',
|
26
|
+
'faulty' => 'error',
|
22
27
|
'error' => 'error',
|
23
28
|
'aborted' => 'error',
|
24
29
|
}.freeze
|
25
30
|
|
26
31
|
def append_status(task_status)
|
27
32
|
if github_status = GITHUB_STATUSES[task_status]
|
28
|
-
|
33
|
+
# Deployments and statuses are created async, we reload the association to ensure we update all instances
|
34
|
+
reload.each do |deployment|
|
35
|
+
Rails.logger.info(
|
36
|
+
"Creating #{github_status} deploy status for deployment #{deployment.id}. "\
|
37
|
+
"Commit: #{deployment.sha}, Github id: #{deployment.github_id}, "\
|
38
|
+
"Repo: #{deployment.stack.repo_name}, Environment: #{deployment.stack.environment}, "\
|
39
|
+
"API Url: #{deployment.api_url}.",
|
40
|
+
)
|
29
41
|
deployment.statuses.create!(status: github_status)
|
30
42
|
end
|
43
|
+
else
|
44
|
+
each do |deployment|
|
45
|
+
Rails.logger.warn(
|
46
|
+
"No GitHub status for task status #{task_status}. "\
|
47
|
+
"Commit: #{deployment.sha}, Github id: #{deployment.github_id}, "\
|
48
|
+
"Repo: #{deployment.stack.repo_name}, Environment: #{deployment.stack.environment}, "\
|
49
|
+
"API Url: #{deployment.api_url}.",
|
50
|
+
)
|
51
|
+
end
|
31
52
|
end
|
32
53
|
end
|
33
54
|
end
|
@@ -215,12 +236,36 @@ module Shipit
|
|
215
236
|
end
|
216
237
|
end
|
217
238
|
|
239
|
+
def update_commit_deployments
|
240
|
+
commit_deployments.append_status(status)
|
241
|
+
end
|
242
|
+
|
218
243
|
private
|
219
244
|
|
220
245
|
def create_commit_deployments
|
221
|
-
|
222
|
-
|
246
|
+
# Create one deployment for the head of the batch
|
247
|
+
commit_deployments.create!(sha: until_commit.sha)
|
248
|
+
|
249
|
+
# Create one for each pull request in the batch, to give feedback on the PR timeline
|
250
|
+
commits.select(&:pull_request?).each do |commit|
|
251
|
+
if (pull_request_head = pull_request_head_for_commit(commit))
|
252
|
+
commit_deployments.create!(sha: pull_request_head)
|
253
|
+
end
|
223
254
|
end
|
255
|
+
|
256
|
+
# Immediately update to publish the status to the commit deployments
|
257
|
+
update_commit_deployments
|
258
|
+
rescue Octokit::ClientError => error
|
259
|
+
Rails.logger.warn("Got #{error.class.name} (#{error.message}) when creating CommitDeployments for Deploy##{id}")
|
260
|
+
end
|
261
|
+
|
262
|
+
def pull_request_head_for_commit(commit)
|
263
|
+
pull_request = Shipit.github.api.pull_request(commit.stack.github_repo_name, commit.pull_request_number)
|
264
|
+
pull_request.head.sha
|
265
|
+
rescue Octokit::ClientError => error
|
266
|
+
pr_ref = "#{commit.stack.github_repo_name}##{commit.pull_request_number}"
|
267
|
+
Rails.logger.warn("Got #{error.class.name} (#{error.message}) when loading pull request #{pr_ref}")
|
268
|
+
nil
|
224
269
|
end
|
225
270
|
|
226
271
|
def update_release_status
|
@@ -245,10 +290,6 @@ module Shipit
|
|
245
290
|
end
|
246
291
|
end
|
247
292
|
|
248
|
-
def update_commit_deployments
|
249
|
-
commit_deployments.append_status(status)
|
250
|
-
end
|
251
|
-
|
252
293
|
def trigger_revert_if_required
|
253
294
|
return unless rollback_once_aborted?
|
254
295
|
return unless supports_rollback?
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module Shipit
|
2
|
+
class DeployStats
|
3
|
+
delegate :empty?, to: :@deploys
|
4
|
+
|
5
|
+
def initialize(deploys)
|
6
|
+
@deploys = deploys
|
7
|
+
@durations = @deploys.map { |d| d.duration.value }.compact
|
8
|
+
end
|
9
|
+
|
10
|
+
def count
|
11
|
+
@deploys.length
|
12
|
+
end
|
13
|
+
|
14
|
+
def average_duration
|
15
|
+
return if empty?
|
16
|
+
@durations.sum / @durations.length.to_f
|
17
|
+
end
|
18
|
+
|
19
|
+
def max_duration
|
20
|
+
@durations.max
|
21
|
+
end
|
22
|
+
|
23
|
+
def min_duration
|
24
|
+
@durations.min
|
25
|
+
end
|
26
|
+
|
27
|
+
def median_duration
|
28
|
+
return if @durations.empty?
|
29
|
+
(sorted_durations[(@durations.length - 1) / 2] + sorted_durations[@durations.length / 2]) / 2.0
|
30
|
+
end
|
31
|
+
|
32
|
+
def success_rate
|
33
|
+
return if empty?
|
34
|
+
(@deploys.count(&:success?) / @deploys.length.to_f) * 100
|
35
|
+
end
|
36
|
+
|
37
|
+
def compare(compare_stats)
|
38
|
+
{
|
39
|
+
count: percent_change(compare_stats.count, count),
|
40
|
+
average_duration: percent_change(compare_stats.average_duration, average_duration),
|
41
|
+
median_duration: percent_change(compare_stats.median_duration, median_duration),
|
42
|
+
}
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def sorted_durations
|
48
|
+
@sorted ||= @durations.sort
|
49
|
+
end
|
50
|
+
|
51
|
+
def percent_change(from, to)
|
52
|
+
return if to.nil? || from.nil?
|
53
|
+
return to * 100 if from.zero?
|
54
|
+
((to - from) / from.to_f) * 100
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
module Shipit
|
2
|
+
class Repository < ApplicationRecord
|
3
|
+
OWNER_MAX_SIZE = 39
|
4
|
+
private_constant :OWNER_MAX_SIZE
|
5
|
+
|
6
|
+
NAME_MAX_SIZE = 100
|
7
|
+
private_constant :NAME_MAX_SIZE
|
8
|
+
|
9
|
+
validates :name, uniqueness: {scope: %i(owner), case_sensitive: false,
|
10
|
+
message: 'cannot be used more than once'}
|
11
|
+
validates :owner, :name, presence: true, ascii_only: true
|
12
|
+
validates :owner, format: {with: /\A[a-z0-9_\-\.]+\z/}, length: {maximum: OWNER_MAX_SIZE}
|
13
|
+
validates :name, format: {with: /\A[a-z0-9_\-\.]+\z/}, length: {maximum: NAME_MAX_SIZE}
|
14
|
+
|
15
|
+
has_many :stacks, dependent: :destroy
|
16
|
+
|
17
|
+
def self.from_github_repo_name(github_repo_name)
|
18
|
+
repo_owner, repo_name = github_repo_name.downcase.split('/')
|
19
|
+
find_by(owner: repo_owner, name: repo_name)
|
20
|
+
end
|
21
|
+
|
22
|
+
def name=(n)
|
23
|
+
super(n&.downcase)
|
24
|
+
end
|
25
|
+
|
26
|
+
def owner=(o)
|
27
|
+
super(o&.downcase)
|
28
|
+
end
|
29
|
+
|
30
|
+
def http_url
|
31
|
+
Shipit.github.url("#{owner}/#{name}")
|
32
|
+
end
|
33
|
+
|
34
|
+
def git_url
|
35
|
+
"https://#{Shipit.github.domain}/#{owner}/#{name}.git"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
data/app/models/shipit/stack.rb
CHANGED
@@ -22,8 +22,6 @@ module Shipit
|
|
22
22
|
end
|
23
23
|
end
|
24
24
|
|
25
|
-
REPO_OWNER_MAX_SIZE = 39
|
26
|
-
REPO_NAME_MAX_SIZE = 100
|
27
25
|
ENVIRONMENT_MAX_SIZE = 50
|
28
26
|
REQUIRED_HOOKS = %i(push status).freeze
|
29
27
|
|
@@ -40,6 +38,14 @@ module Shipit
|
|
40
38
|
has_many :hooks, dependent: :destroy
|
41
39
|
has_many :api_clients, dependent: :destroy
|
42
40
|
belongs_to :lock_author, class_name: :User, optional: true
|
41
|
+
belongs_to :repository
|
42
|
+
validates_associated :repository
|
43
|
+
|
44
|
+
scope :not_archived, -> { where(archived_since: nil) }
|
45
|
+
|
46
|
+
def repository
|
47
|
+
super || build_repository
|
48
|
+
end
|
43
49
|
|
44
50
|
def lock_author(*)
|
45
51
|
super || AnonymousUser.new
|
@@ -49,11 +55,6 @@ module Shipit
|
|
49
55
|
super(user&.logged_in? ? user : nil)
|
50
56
|
end
|
51
57
|
|
52
|
-
def self.repo(full_name)
|
53
|
-
repo_owner, repo_name = full_name.downcase.split('/')
|
54
|
-
where(repo_owner: repo_owner, repo_name: repo_name)
|
55
|
-
end
|
56
|
-
|
57
58
|
before_validation :update_defaults
|
58
59
|
before_destroy :clear_local_files
|
59
60
|
before_save :set_locked_since
|
@@ -66,11 +67,10 @@ module Shipit
|
|
66
67
|
after_commit :sync_github, on: :create
|
67
68
|
after_commit :schedule_merges_if_necessary, on: :update
|
68
69
|
|
69
|
-
validates :
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
validates :repo_name, format: {with: /\A[a-z0-9_\-\.]+\z/}, length: {maximum: REPO_NAME_MAX_SIZE}
|
70
|
+
validates :repository, uniqueness: {
|
71
|
+
scope: %i(environment), case_sensitive: false,
|
72
|
+
message: 'cannot be used more than once with this environment. Check archived stacks.'
|
73
|
+
}
|
74
74
|
validates :environment, format: {with: /\A[a-z0-9\-_\:]+\z/}, length: {maximum: ENVIRONMENT_MAX_SIZE}
|
75
75
|
validates :deploy_url, format: {with: URI.regexp(%w(http https ssh))}, allow_blank: true
|
76
76
|
|
@@ -157,7 +157,8 @@ module Shipit
|
|
157
157
|
return
|
158
158
|
end
|
159
159
|
|
160
|
-
if commit.deploy_failed? || (checks? && !EphemeralCommitChecks.new(commit).run.success?)
|
160
|
+
if commit.deploy_failed? || (checks? && !EphemeralCommitChecks.new(commit).run.success?) ||
|
161
|
+
commit.recently_pushed?
|
161
162
|
continuous_delivery_delayed!
|
162
163
|
return
|
163
164
|
end
|
@@ -320,21 +321,12 @@ module Shipit
|
|
320
321
|
cached_deploy_spec&.pull_request_merge_method || Shipit.default_merge_method
|
321
322
|
end
|
322
323
|
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
end
|
330
|
-
|
331
|
-
def repo_http_url
|
332
|
-
Shipit.github.url("#{repo_owner}/#{repo_name}")
|
333
|
-
end
|
334
|
-
|
335
|
-
def repo_git_url
|
336
|
-
"https://#{Shipit.github.domain}/#{repo_owner}/#{repo_name}.git"
|
337
|
-
end
|
324
|
+
delegate :name=, to: :repository, prefix: :repo
|
325
|
+
delegate :name, to: :repository, prefix: :repo
|
326
|
+
delegate :owner=, to: :repository, prefix: :repo
|
327
|
+
delegate :owner, to: :repository, prefix: :repo
|
328
|
+
delegate :http_url, to: :repository, prefix: :repo
|
329
|
+
delegate :git_url, to: :repository, prefix: :repo
|
338
330
|
|
339
331
|
def base_path
|
340
332
|
Rails.root.join('data', 'stacks', repo_owner, repo_name, environment)
|
@@ -389,7 +381,7 @@ module Shipit
|
|
389
381
|
if resource.try(:message) == 'Moved Permanently'
|
390
382
|
resource = Shipit.github.api.get(resource.url)
|
391
383
|
end
|
392
|
-
update!(
|
384
|
+
repository.update!(owner: resource.owner.login, name: resource.name)
|
393
385
|
end
|
394
386
|
|
395
387
|
def active_task?
|
@@ -414,6 +406,18 @@ module Shipit
|
|
414
406
|
update!(lock_reason: nil, lock_author: nil, locked_since: nil)
|
415
407
|
end
|
416
408
|
|
409
|
+
def archived?
|
410
|
+
archived_since.present?
|
411
|
+
end
|
412
|
+
|
413
|
+
def archive!(user)
|
414
|
+
update!(archived_since: Time.now, lock_reason: "Archived", lock_author: user)
|
415
|
+
end
|
416
|
+
|
417
|
+
def unarchive!
|
418
|
+
update!(archived_since: nil, lock_reason: nil, lock_author: nil, locked_since: nil)
|
419
|
+
end
|
420
|
+
|
417
421
|
def to_param
|
418
422
|
[repo_owner, repo_name, environment].join('/')
|
419
423
|
end
|
@@ -429,11 +433,14 @@ module Shipit
|
|
429
433
|
|
430
434
|
def self.from_param!(param)
|
431
435
|
repo_owner, repo_name, environment = param.split('/')
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
436
|
+
includes(:repository)
|
437
|
+
.where(
|
438
|
+
repositories: {
|
439
|
+
owner: repo_owner.downcase,
|
440
|
+
name: repo_name.downcase,
|
441
|
+
},
|
442
|
+
environment: environment,
|
443
|
+
).first!
|
437
444
|
end
|
438
445
|
|
439
446
|
delegate :plugins, :task_definitions, :hidden_statuses, :required_statuses, :soft_failing_statuses,
|