shipit-engine 0.16.0 → 0.17.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 +1 -0
- data/app/assets/images/caret-down.svg +1 -0
- data/app/assets/javascripts/shipit/stacks.js.coffee +10 -0
- data/app/assets/stylesheets/_base/_banner.scss +7 -3
- data/app/assets/stylesheets/_base/_base.scss +0 -74
- data/app/assets/stylesheets/_base/_buttons.scss +7 -3
- data/app/assets/stylesheets/_base/_colors.scss +2 -0
- data/app/assets/stylesheets/_base/_icons.scss +8 -0
- data/app/assets/stylesheets/_base/_spacing.scss +21 -0
- data/app/assets/stylesheets/_pages/_commits.scss +41 -3
- data/app/assets/stylesheets/_structure/_layout.scss +8 -35
- data/app/assets/stylesheets/_structure/_main.scss +2 -2
- data/app/assets/stylesheets/_structure/_navigation.scss +89 -0
- data/app/assets/stylesheets/shipit.scss +3 -0
- data/app/controllers/concerns/shipit/api/rendering.rb +3 -6
- data/app/controllers/shipit/api/ccmenu_controller.rb +4 -0
- data/app/controllers/shipit/commits_controller.rb +18 -0
- data/app/jobs/shipit/destroy_stack_job.rb +25 -0
- data/app/jobs/shipit/github_sync_job.rb +12 -1
- data/app/jobs/shipit/merge_pull_requests_job.rb +3 -0
- data/app/models/shipit/commit.rb +14 -2
- data/app/models/shipit/deploy.rb +5 -0
- data/app/models/shipit/deploy_spec.rb +9 -6
- data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +24 -2
- data/app/models/shipit/pull_request.rb +16 -1
- data/app/models/shipit/stack.rb +11 -4
- data/app/models/shipit/task_definition.rb +4 -0
- data/app/models/shipit/team.rb +1 -1
- data/app/models/shipit/undeployed_commit.rb +1 -2
- data/app/models/shipit/user.rb +1 -1
- data/app/models/shipit/variable_definition.rb +5 -0
- data/app/serializers/shipit/stack_serializer.rb +1 -1
- data/app/views/layouts/shipit.html.erb +2 -1
- data/app/views/shipit/commits/_commit.html.erb +9 -1
- data/app/views/shipit/deploys/rollback.html.erb +1 -1
- data/app/views/shipit/stacks/_header.html.erb +15 -3
- data/app/views/shipit/stacks/settings.html.erb +1 -1
- data/config/locales/en.yml +9 -5
- data/config/routes.rb +1 -0
- data/db/migrate/20170310164315_add_merged_at_on_pull_requests.rb +9 -0
- data/db/migrate/20170314145604_add_last_deployed_at_to_stack.rb +9 -0
- data/db/migrate/20170320124156_add_locked_to_commits.rb +5 -0
- data/lib/shipit/task_commands.rb +1 -0
- data/lib/shipit/version.rb +1 -1
- data/test/controllers/api/ccmenu_controller_test.rb +6 -0
- data/test/controllers/api/stacks_controller_test.rb +6 -0
- data/test/controllers/api/tasks_controller_test.rb +31 -0
- data/test/controllers/commits_controller_test.rb +18 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/schema.rb +4 -1
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/db/test.sqlite3-journal +0 -0
- data/test/fixtures/shipit/commits.yml +1 -1
- data/test/fixtures/shipit/pull_requests.yml +33 -0
- data/test/fixtures/shipit/stacks.yml +4 -1
- data/test/jobs/github_sync_job_test.rb +49 -0
- data/test/jobs/merge_pull_requests_job_test.rb +18 -0
- data/test/models/commits_test.rb +71 -0
- data/test/models/deploy_spec_test.rb +15 -0
- data/test/models/deploys_test.rb +7 -0
- data/test/models/pull_request_test.rb +19 -1
- data/test/models/task_definitions_test.rb +9 -0
- data/test/models/undeployed_commits_test.rb +2 -7
- data/test/unit/deploy_commands_test.rb +7 -0
- data/test/unit/variable_definition_test.rb +10 -0
- metadata +15 -7
- data/app/assets/images/github.svg +0 -9
- data/app/assets/images/refresh.svg +0 -8
- data/app/assets/images/settings.svg +0 -33
- data/lib/snippets/deploy-to-gke +0 -161
@@ -3,12 +3,15 @@
|
|
3
3
|
|
4
4
|
@import "_base/_media-queries";
|
5
5
|
@import "_base/_utility";
|
6
|
+
@import "_base/_spacing";
|
6
7
|
@import "_base/_colors";
|
7
8
|
@import "_base/_base";
|
8
9
|
@import "_base/_forms";
|
10
|
+
@import "_base/_icons";
|
9
11
|
@import "_base/_buttons";
|
10
12
|
@import "_base/_banner";
|
11
13
|
@import "_structure/_layout";
|
14
|
+
@import "_structure/_navigation";
|
12
15
|
@import "_structure/_main";
|
13
16
|
@import "_base/status-items";
|
14
17
|
@import "_pages/_commits";
|
@@ -10,15 +10,12 @@ module Shipit
|
|
10
10
|
|
11
11
|
def render_resource(resource, options = {})
|
12
12
|
if resource.destroyed?
|
13
|
-
options
|
14
|
-
options[:text] = nil
|
13
|
+
head :no_content, options.reverse_merge(content_type: 'application/json')
|
15
14
|
elsif resource.errors.any?
|
16
|
-
options
|
17
|
-
options[:status] = :unprocessable_entity
|
15
|
+
render options.reverse_merge(status: :unprocessable_entity, json: {errors: resource.errors})
|
18
16
|
else
|
19
|
-
options
|
17
|
+
render options.reverse_merge(json: resource)
|
20
18
|
end
|
21
|
-
render options
|
22
19
|
end
|
23
20
|
end
|
24
21
|
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
module Shipit
|
2
|
+
class CommitsController < ShipitController
|
3
|
+
def update
|
4
|
+
commit.update(params.require(:commit).permit(:locked))
|
5
|
+
head :ok
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def commit
|
11
|
+
@commit ||= stack.commits.find(params[:id])
|
12
|
+
end
|
13
|
+
|
14
|
+
def stack
|
15
|
+
@stack ||= Stack.from_param!(params[:stack_id])
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -2,7 +2,32 @@ module Shipit
|
|
2
2
|
class DestroyStackJob < BackgroundJob
|
3
3
|
queue_as :default
|
4
4
|
|
5
|
+
# stack
|
6
|
+
# +-- api_clients
|
7
|
+
# +-- commits
|
8
|
+
# | +-- commit_deployments
|
9
|
+
# | | +-- statuses
|
10
|
+
# | +-- statuses
|
11
|
+
# +-- github_hooks
|
12
|
+
# +-- hooks
|
13
|
+
# +-- pull_requests
|
14
|
+
# +-- tasks
|
15
|
+
# +-- chunks
|
16
|
+
|
5
17
|
def perform(stack)
|
18
|
+
Shipit::ApiClient.where(stack_id: stack.id).delete_all
|
19
|
+
commits_ids = Shipit::Commit.where(stack_id: stack.id).pluck(:id)
|
20
|
+
commit_deployments_ids = Shipit::CommitDeployment.where(commit_id: commits_ids).pluck(:id)
|
21
|
+
Shipit::CommitDeploymentStatus.where(commit_deployment_id: commit_deployments_ids).delete_all
|
22
|
+
Shipit::CommitDeployment.where(id: commit_deployments_ids).delete_all
|
23
|
+
Shipit::Status.where(commit_id: commits_ids).delete_all
|
24
|
+
Shipit::Commit.where(id: commits_ids).delete_all
|
25
|
+
Shipit::GithubHook.where(stack_id: stack.id).destroy_all
|
26
|
+
Shipit::Hook.where(stack_id: stack.id).delete_all
|
27
|
+
Shipit::PullRequest.where(stack_id: stack.id).delete_all
|
28
|
+
tasks_ids = Shipit::Task.where(stack_id: stack.id).pluck(:id)
|
29
|
+
Shipit::OutputChunk.where(task_id: tasks_ids).delete_all
|
30
|
+
Shipit::Task.where(id: tasks_ids).delete_all
|
6
31
|
stack.destroy!
|
7
32
|
end
|
8
33
|
end
|
@@ -17,13 +17,24 @@ module Shipit
|
|
17
17
|
@stack.transaction do
|
18
18
|
shared_parent.try!(:detach_children!)
|
19
19
|
new_commits.each do |gh_commit|
|
20
|
-
|
20
|
+
append_commit(gh_commit)
|
21
21
|
end
|
22
22
|
end
|
23
23
|
end
|
24
24
|
CacheDeploySpecJob.perform_later(@stack)
|
25
25
|
end
|
26
26
|
|
27
|
+
def append_commit(gh_commit)
|
28
|
+
appended_commit = @stack.commits.create_from_github!(gh_commit)
|
29
|
+
if appended_commit.revert?
|
30
|
+
impacted_commits = @stack.undeployed_commits.reverse.drop_while { |c| !appended_commit.revert_of?(c) }
|
31
|
+
impacted_commits.pop # appended_commit
|
32
|
+
impacted_commits.each do |impacted_commit|
|
33
|
+
impacted_commit.update!(locked: true)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
27
38
|
def fetch_missing_commits(&block)
|
28
39
|
commits = []
|
29
40
|
iterator = Shipit::FirstParentCommitsIterator.new(&block)
|
@@ -8,6 +8,9 @@ module Shipit
|
|
8
8
|
pull_requests.each do |pull_request|
|
9
9
|
pull_request.refresh!
|
10
10
|
pull_request.reject_unless_mergeable!
|
11
|
+
if pull_request.closed?
|
12
|
+
pull_request.merged_upstream? ? pull_request.complete! : pull_request.cancel!
|
13
|
+
end
|
11
14
|
end
|
12
15
|
|
13
16
|
return false unless stack.allows_merges?
|
data/app/models/shipit/commit.rb
CHANGED
@@ -106,7 +106,7 @@ module Shipit
|
|
106
106
|
delegate :pending?, :success?, :error?, :failure?, :state, to: :status
|
107
107
|
|
108
108
|
def deployable?
|
109
|
-
success? || stack.ignore_ci?
|
109
|
+
!locked? && (success? || stack.ignore_ci?)
|
110
110
|
end
|
111
111
|
|
112
112
|
def children
|
@@ -126,13 +126,25 @@ module Shipit
|
|
126
126
|
end
|
127
127
|
|
128
128
|
def title
|
129
|
-
pull_request_title ||
|
129
|
+
pull_request_title || message_header
|
130
|
+
end
|
131
|
+
|
132
|
+
def message_header
|
133
|
+
message.lines.first.strip
|
130
134
|
end
|
131
135
|
|
132
136
|
def pull_request_title # TODO: remove in a few versions when it is assumed the commits table was backfilled
|
133
137
|
super || message_parser.pull_request_title
|
134
138
|
end
|
135
139
|
|
140
|
+
def revert?
|
141
|
+
title.start_with?('Revert "') && title.end_with?('"')
|
142
|
+
end
|
143
|
+
|
144
|
+
def revert_of?(commit)
|
145
|
+
title == %(Revert "#{commit.title}") || title == %(Revert "#{commit.message_header}")
|
146
|
+
end
|
147
|
+
|
136
148
|
def short_sha
|
137
149
|
sha[0..9]
|
138
150
|
end
|
data/app/models/shipit/deploy.rb
CHANGED
@@ -10,6 +10,7 @@ module Shipit
|
|
10
10
|
after_transition to: :success, do: :update_undeployed_commits_count
|
11
11
|
after_transition to: :aborted, do: :trigger_revert_if_required
|
12
12
|
after_transition any => any, do: :update_commit_deployments
|
13
|
+
after_transition any => any, do: :update_last_deploy_time
|
13
14
|
end
|
14
15
|
|
15
16
|
has_many :commit_deployments, dependent: :destroy, inverse_of: :task, foreign_key: :task_id do
|
@@ -180,5 +181,9 @@ module Shipit
|
|
180
181
|
def update_undeployed_commits_count
|
181
182
|
stack.update_undeployed_commits_count(until_commit)
|
182
183
|
end
|
184
|
+
|
185
|
+
def update_last_deploy_time
|
186
|
+
stack.update(last_deployed_at: ended_at)
|
187
|
+
end
|
183
188
|
end
|
184
189
|
end
|
@@ -108,21 +108,20 @@ module Shipit
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def task_definitions
|
111
|
-
(config('tasks') || {}).map
|
111
|
+
discover_task_definitions.merge(config('tasks') || {}).map do |name, definition|
|
112
|
+
TaskDefinition.new(name, coerce_task_definition(definition))
|
113
|
+
end
|
112
114
|
end
|
113
115
|
|
114
116
|
def find_task_definition(id)
|
115
|
-
|
117
|
+
definition = config('tasks', id) || discover_task_definitions[id]
|
118
|
+
TaskDefinition.new(id, coerce_task_definition(definition) || task_not_found!(id))
|
116
119
|
end
|
117
120
|
|
118
121
|
def filter_deploy_envs(env)
|
119
122
|
EnvironmentVariables.with(env).permit(deploy_variables)
|
120
123
|
end
|
121
124
|
|
122
|
-
def filter_task_envs(id, env)
|
123
|
-
find_task_definition(id).filter_envs(env)
|
124
|
-
end
|
125
|
-
|
126
125
|
def review_checklist
|
127
126
|
(config('review', 'checklist') || discover_review_checklist || []).map(&:strip).select(&:present?)
|
128
127
|
end
|
@@ -199,6 +198,10 @@ module Shipit
|
|
199
198
|
def discover_review_checklist
|
200
199
|
end
|
201
200
|
|
201
|
+
def discover_task_definitions
|
202
|
+
{}
|
203
|
+
end
|
204
|
+
|
202
205
|
def discover_dependencies_steps
|
203
206
|
end
|
204
207
|
|
@@ -9,6 +9,20 @@ module Shipit
|
|
9
9
|
discover_kubernetes || super
|
10
10
|
end
|
11
11
|
|
12
|
+
def discover_task_definitions
|
13
|
+
if kube_config.present?
|
14
|
+
{
|
15
|
+
'restart' => {
|
16
|
+
'action' => "Restart application",
|
17
|
+
'description' => "Simulates a rollout of Kubernetes deployments by using kubernetes-restart utility",
|
18
|
+
'steps' => [kubernetes_restart_cmd],
|
19
|
+
},
|
20
|
+
}
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
12
26
|
private
|
13
27
|
|
14
28
|
def discover_kubernetes
|
@@ -20,8 +34,8 @@ module Shipit
|
|
20
34
|
cmd << kube_config['template_dir']
|
21
35
|
end
|
22
36
|
|
23
|
-
cmd << kube_config
|
24
|
-
cmd << kube_config
|
37
|
+
cmd << kube_config.fetch('namespace')
|
38
|
+
cmd << kube_config.fetch('context')
|
25
39
|
|
26
40
|
[Shellwords.join(cmd)]
|
27
41
|
end
|
@@ -29,6 +43,14 @@ module Shipit
|
|
29
43
|
def kube_config
|
30
44
|
@kube_config ||= config('kubernetes') || {}
|
31
45
|
end
|
46
|
+
|
47
|
+
def kubernetes_restart_cmd
|
48
|
+
Shellwords.join([
|
49
|
+
"kubernetes-restart",
|
50
|
+
kube_config.fetch('namespace'),
|
51
|
+
kube_config.fetch('context'),
|
52
|
+
])
|
53
|
+
end
|
32
54
|
end
|
33
55
|
end
|
34
56
|
end
|
@@ -95,6 +95,10 @@ module Shipit
|
|
95
95
|
before_transition any => :pending do |pr|
|
96
96
|
pr.revalidated_at = Time.now.utc
|
97
97
|
end
|
98
|
+
|
99
|
+
before_transition %i(pending) => :merged do |pr|
|
100
|
+
Stack.increment_counter(:undeployed_commits_count, pr.stack_id)
|
101
|
+
end
|
98
102
|
end
|
99
103
|
|
100
104
|
def self.schedule_merges
|
@@ -164,7 +168,9 @@ module Shipit
|
|
164
168
|
merge_method: 'merge',
|
165
169
|
)
|
166
170
|
begin
|
167
|
-
Shipit.github_api.
|
171
|
+
if Shipit.github_api.pull_requests(stack.github_repo_name, base: branch).empty?
|
172
|
+
Shipit.github_api.delete_branch(stack.github_repo_name, branch)
|
173
|
+
end
|
168
174
|
rescue Octokit::UnprocessableEntity
|
169
175
|
# branch was already deleted somehow
|
170
176
|
end
|
@@ -203,6 +209,14 @@ module Shipit
|
|
203
209
|
RefreshPullRequestJob.perform_later(self)
|
204
210
|
end
|
205
211
|
|
212
|
+
def closed?
|
213
|
+
state == "closed"
|
214
|
+
end
|
215
|
+
|
216
|
+
def merged_upstream?
|
217
|
+
closed? && merged_at
|
218
|
+
end
|
219
|
+
|
206
220
|
def refresh!
|
207
221
|
update!(github_pull_request: Shipit.github_api.pull_request(stack.github_repo_name, number))
|
208
222
|
head.refresh_statuses!
|
@@ -219,6 +233,7 @@ module Shipit
|
|
219
233
|
self.deletions = github_pull_request.deletions
|
220
234
|
self.branch = github_pull_request.head.ref
|
221
235
|
self.head = find_or_create_commit_from_github_by_sha!(github_pull_request.head.sha, detached: true)
|
236
|
+
self.merged_at = github_pull_request.merged_at
|
222
237
|
end
|
223
238
|
|
224
239
|
def merge_message
|
data/app/models/shipit/stack.rb
CHANGED
@@ -82,13 +82,20 @@ module Shipit
|
|
82
82
|
end
|
83
83
|
|
84
84
|
def trigger_task(definition_id, user, env: nil)
|
85
|
+
definition = find_task_definition(definition_id)
|
86
|
+
env = env.try!(:to_h) || {}
|
87
|
+
|
88
|
+
definition.variables_with_defaults.each do |variable|
|
89
|
+
env[variable.name] ||= variable.default
|
90
|
+
end
|
91
|
+
|
85
92
|
commit = last_deployed_commit.presence || commits.first
|
86
93
|
task = tasks.create(
|
87
94
|
user_id: user.id,
|
88
|
-
definition:
|
95
|
+
definition: definition,
|
89
96
|
until_commit_id: commit.id,
|
90
97
|
since_commit_id: commit.id,
|
91
|
-
env:
|
98
|
+
env: definition.filter_envs(env),
|
92
99
|
)
|
93
100
|
task.enqueue
|
94
101
|
task
|
@@ -372,8 +379,8 @@ module Shipit
|
|
372
379
|
|
373
380
|
def update_undeployed_commits_count(after_commit = nil)
|
374
381
|
after_commit ||= last_deployed_commit
|
375
|
-
undeployed_commits = commits.reachable.newer_than(after_commit).
|
376
|
-
|
382
|
+
undeployed_commits = commits.reachable.newer_than(after_commit).count
|
383
|
+
update(undeployed_commits_count: undeployed_commits)
|
377
384
|
end
|
378
385
|
|
379
386
|
def broadcast_update
|
data/app/models/shipit/team.rb
CHANGED
@@ -2,8 +2,8 @@ module Shipit
|
|
2
2
|
class Team < ActiveRecord::Base
|
3
3
|
REQUIRED_HOOKS = %i(membership).freeze
|
4
4
|
|
5
|
-
has_many :members, class_name: :User, through: :memberships, source: :user
|
6
5
|
has_many :memberships
|
6
|
+
has_many :members, class_name: :User, through: :memberships, source: :user
|
7
7
|
|
8
8
|
has_many :github_hooks,
|
9
9
|
-> { where(event: REQUIRED_HOOKS) },
|
@@ -11,7 +11,7 @@ module Shipit
|
|
11
11
|
state = deployable? ? 'allowed' : status.state
|
12
12
|
unless bypass_safeties
|
13
13
|
state = 'deploying' if stack.active_task?
|
14
|
-
state = 'locked' if
|
14
|
+
state = 'locked' if locked?
|
15
15
|
end
|
16
16
|
state
|
17
17
|
end
|
@@ -19,7 +19,6 @@ module Shipit
|
|
19
19
|
def redeploy_state(bypass_safeties = false)
|
20
20
|
state = 'allowed'
|
21
21
|
unless bypass_safeties
|
22
|
-
state = 'locked' if stack.locked?
|
23
22
|
state = 'deploying' if stack.active_task?
|
24
23
|
end
|
25
24
|
state
|
data/app/models/shipit/user.rb
CHANGED
@@ -2,8 +2,8 @@ module Shipit
|
|
2
2
|
class User < ActiveRecord::Base
|
3
3
|
DEFAULT_AVATAR = URI.parse('https://avatars.githubusercontent.com/u/583231?')
|
4
4
|
|
5
|
-
has_many :teams, through: :memberships
|
6
5
|
has_many :memberships
|
6
|
+
has_many :teams, through: :memberships
|
7
7
|
has_many :authored_commits, class_name: :Commit, foreign_key: :author_id, inverse_of: :author
|
8
8
|
has_many :commits, foreign_key: :committer_id, inverse_of: :committer
|
9
9
|
has_many :tasks
|
@@ -6,9 +6,14 @@ module Shipit
|
|
6
6
|
@name = attributes.fetch('name')
|
7
7
|
@title = attributes['title']
|
8
8
|
@default = attributes['default'].to_s
|
9
|
+
@default_provided = attributes.key?('default')
|
9
10
|
@select = attributes['select'].presence
|
10
11
|
end
|
11
12
|
|
13
|
+
def default_provided?
|
14
|
+
@default_provided
|
15
|
+
end
|
16
|
+
|
12
17
|
def to_h
|
13
18
|
{
|
14
19
|
'name' => @name,
|
@@ -5,7 +5,7 @@ module Shipit
|
|
5
5
|
has_one :lock_author
|
6
6
|
attributes :id, :repo_owner, :repo_name, :environment, :html_url, :url, :tasks_url, :deploy_url, :pull_requests_url,
|
7
7
|
:deploy_spec, :undeployed_commits_count, :is_locked, :lock_reason, :continuous_deployment, :created_at,
|
8
|
-
:updated_at, :locked_since
|
8
|
+
:updated_at, :locked_since, :last_deployed_at
|
9
9
|
|
10
10
|
def url
|
11
11
|
api_stack_url(object)
|
@@ -1,7 +1,8 @@
|
|
1
1
|
<!DOCTYPE html>
|
2
|
-
<html data-controller="<%= controller_name %>" data-action="<%= action_name %>">
|
2
|
+
<html lang="<%= I18n.locale %>" data-controller="<%= controller_name %>" data-action="<%= action_name %>">
|
3
3
|
<head>
|
4
4
|
<title><%= [Shipit.app_name, @stack.try!(:repo_name)].compact.join(' - ') %></title>
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1">
|
5
6
|
<%= favicon_link_tag %>
|
6
7
|
<%= stylesheet_link_tag :shipit, media: 'all' %>
|
7
8
|
<%= javascript_include_tag :shipit %>
|