shipit-engine 0.10.0 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +33 -11
- data/app/assets/javascripts/shipit.js.coffee +7 -1
- data/app/assets/stylesheets/_base/_buttons.scss +3 -0
- data/app/assets/stylesheets/_base/_colors.scss +1 -1
- data/app/assets/stylesheets/_base/_status-items.scss +1 -1
- data/app/assets/stylesheets/_pages/_deploy.scss +1 -1
- data/app/assets/stylesheets/_structure/_main.scss +1 -1
- data/app/controllers/shipit/stacks_controller.rb +1 -5
- data/app/helpers/shipit/shipit_helper.rb +7 -9
- data/app/helpers/shipit/stacks_helper.rb +14 -28
- data/app/jobs/shipit/continuous_delivery_job.rb +1 -1
- data/app/jobs/shipit/update_estimated_deploy_duration.rb +9 -0
- data/app/models/shipit/commit_checks.rb +1 -1
- data/app/models/shipit/deploy.rb +1 -1
- data/app/models/shipit/deploy_spec/bundler_discovery.rb +1 -1
- data/app/models/shipit/deploy_spec/file_system.rb +6 -1
- data/app/models/shipit/deploy_spec.rb +12 -0
- data/app/models/shipit/duration.rb +29 -9
- data/app/models/shipit/github_hook.rb +0 -2
- data/app/models/shipit/stack.rb +48 -11
- data/app/models/shipit/task.rb +13 -2
- data/app/models/shipit/team.rb +1 -1
- data/app/models/shipit/undeployed_commit.rb +36 -0
- data/app/views/layouts/shipit.html.erb +6 -4
- data/app/views/shipit/deploys/show.html.erb +1 -1
- data/app/views/shipit/stacks/_header.html.erb +7 -0
- data/app/views/shipit/stacks/show.html.erb +1 -1
- data/config/locales/en.yml +9 -3
- data/config/secrets.development.example.yml +19 -0
- data/config/secrets.development.shopify.yml +19 -0
- data/config/secrets.development.yml +16 -0
- data/db/migrate/20160502150713_add_estimated_deploy_duration_to_stacks.rb +5 -0
- data/db/migrate/20160526192650_reorder_active_tasks_index.rb +7 -0
- data/lib/shipit/command.rb +15 -2
- data/lib/shipit/engine.rb +2 -1
- data/lib/shipit/stat.rb +13 -0
- data/lib/shipit/version.rb +1 -1
- data/lib/shipit.rb +13 -0
- data/lib/tasks/cron.rake +1 -0
- data/test/controllers/github_authentication_controller_test.rb +5 -5
- data/test/dummy/config/initializers/0_load_development_secrets.rb +9 -0
- data/test/dummy/config/secrets.yml +5 -16
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/schema.rb +14 -14
- data/test/dummy/db/seeds.rb +1 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/fixtures/shipit/stacks.yml +2 -2
- data/test/fixtures/shipit/tasks.yml +3 -1
- data/test/fixtures/shipit/users.yml +5 -0
- data/test/helpers/queries_helper.rb +1 -1
- data/test/models/deploys_test.rb +7 -0
- data/test/models/duration_test.rb +23 -0
- data/test/models/stacks_test.rb +93 -4
- data/test/models/undeployed_commits_test.rb +100 -0
- data/test/test_helper.rb +1 -0
- data/test/unit/deploy_spec_test.rb +1 -1
- data/test/unit/shipit_test.rb +2 -1
- metadata +19 -10
- data/db/schema.rb +0 -188
- data/test/dummy/config/secrets.example.yml +0 -35
data/app/models/shipit/team.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Shipit
|
2
|
+
class UndeployedCommit < DelegateClass(Commit)
|
3
|
+
attr_reader :index
|
4
|
+
|
5
|
+
def initialize(commit, index)
|
6
|
+
super(commit)
|
7
|
+
@index = index
|
8
|
+
end
|
9
|
+
|
10
|
+
def deploy_state(bypass_safeties = false)
|
11
|
+
state = deployable? ? 'allowed' : status.state
|
12
|
+
unless bypass_safeties
|
13
|
+
state = 'deploying' if stack.active_task?
|
14
|
+
state = 'locked' if stack.locked?
|
15
|
+
end
|
16
|
+
state
|
17
|
+
end
|
18
|
+
|
19
|
+
def redeploy_state(bypass_safeties = false)
|
20
|
+
state = 'allowed'
|
21
|
+
unless bypass_safeties
|
22
|
+
state = 'locked' if stack.locked?
|
23
|
+
state = 'deploying' if stack.active_task?
|
24
|
+
end
|
25
|
+
state
|
26
|
+
end
|
27
|
+
|
28
|
+
def deploy_disallowed?
|
29
|
+
!deployable? || !stack.deployable?
|
30
|
+
end
|
31
|
+
|
32
|
+
def deploy_discouraged?
|
33
|
+
stack.maximum_commits_per_deploy && index >= stack.maximum_commits_per_deploy
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -13,14 +13,16 @@
|
|
13
13
|
<%= content_tag :div, msg, class: ["flash-#{name}", :flash] %>
|
14
14
|
<% end %>
|
15
15
|
|
16
|
-
<div class="banner
|
16
|
+
<div class="banner enable-notifications banner--blue hidden">
|
17
17
|
<div class="banner__inner wrapper">
|
18
18
|
<div class="banner__content">
|
19
19
|
<h2 class="banner__title">Do you want to enable desktop notifications?</h2>
|
20
|
+
<div class="banner__accessory">
|
21
|
+
<button class="banner__btn btn">Enable notifications</button>
|
22
|
+
</div>
|
20
23
|
</div>
|
21
|
-
|
22
|
-
|
23
|
-
</div>
|
24
|
+
|
25
|
+
<a class="banner__dismiss">×</a>
|
24
26
|
</div>
|
25
27
|
</div>
|
26
28
|
|
@@ -24,6 +24,13 @@
|
|
24
24
|
</li>
|
25
25
|
</ul>
|
26
26
|
<ul class="nav__list nav__list--secondary">
|
27
|
+
<% if stack.links.present? %>
|
28
|
+
<% stack.links.each do |name, url| %>
|
29
|
+
<li class="nav__list__item">
|
30
|
+
<%= link_to name.humanize, url, :target => '_blank', :class => "#{name.dasherize}-url" %>
|
31
|
+
</li>
|
32
|
+
<% end %>
|
33
|
+
<% end %>
|
27
34
|
<li class="nav__list__item">
|
28
35
|
<%= link_to 'View on GitHub', github_repo_url(stack.repo_owner, stack.repo_name) %>
|
29
36
|
</li>
|
data/config/locales/en.yml
CHANGED
@@ -21,16 +21,22 @@
|
|
21
21
|
|
22
22
|
en:
|
23
23
|
deploy_button:
|
24
|
+
hint:
|
25
|
+
max_commits: It is recommended not to deploy more than %{maximum} commits at once.
|
24
26
|
caption:
|
25
27
|
pending: CI Pending...
|
26
28
|
failure: CI Failure
|
27
29
|
error: CI Error
|
28
30
|
unknown: Not Run
|
29
31
|
locked: Locked
|
30
|
-
deploying: Deploy in
|
31
|
-
|
32
|
+
deploying: A Deploy is in Progress...
|
33
|
+
allowed: Deploy
|
32
34
|
missing: Missing CI
|
33
|
-
|
35
|
+
redeploy_button:
|
36
|
+
caption:
|
37
|
+
deploying: A Deploy is in Progress...
|
38
|
+
allowed: Redeploy
|
39
|
+
locked: Locked
|
34
40
|
deploy_spec:
|
35
41
|
hint:
|
36
42
|
deploy: Impossible to detect how to deploy this application. Please define `deploy.override` in your shipit.yml
|
@@ -0,0 +1,19 @@
|
|
1
|
+
host: 'http://localhost:3000'
|
2
|
+
redis_url: 'redis://127.0.0.1:6379/0'
|
3
|
+
|
4
|
+
github_api:
|
5
|
+
# Can be obtained there: https://github.com/settings/tokens/new
|
6
|
+
# The required permissions are: `admin:org_hook`, `admin:repo_hook`, `read:org` and `repo`
|
7
|
+
access_token:
|
8
|
+
|
9
|
+
# Can be obtained there: https://github.com/settings/applications/new
|
10
|
+
# Set the "Authorization callback URL" as `<host>/github/auth/github/callback`
|
11
|
+
github_oauth:
|
12
|
+
id:
|
13
|
+
secret:
|
14
|
+
# teams: # Optional
|
15
|
+
|
16
|
+
# To work on the beta bootstrap re-write
|
17
|
+
# features:
|
18
|
+
# - bootstrap
|
19
|
+
|
@@ -0,0 +1,19 @@
|
|
1
|
+
host: 'http://shipit-engine.localhost'
|
2
|
+
redis_url: 'redis://shipit-engine.railgun:6379'
|
3
|
+
|
4
|
+
github_api:
|
5
|
+
# Can be obtained there: https://github.com/settings/tokens/new
|
6
|
+
# The required permissions are: `admin:org_hook`, `admin:repo_hook`, `read:org` and `repo`
|
7
|
+
access_token:
|
8
|
+
|
9
|
+
# Can be obtained there: https://github.com/settings/applications/new
|
10
|
+
# Set the "Authorization callback URL" as `<host>/github/auth/github/callback`
|
11
|
+
github_oauth:
|
12
|
+
id:
|
13
|
+
secret:
|
14
|
+
# teams: # Optional
|
15
|
+
|
16
|
+
# To work on the beta bootstrap re-write
|
17
|
+
# features:
|
18
|
+
# - bootstrap
|
19
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
host: 'http://shipit-engine.localhost'
|
2
|
+
redis_url: 'redis://shipit-engine.railgun:6379'
|
3
|
+
|
4
|
+
github_api:
|
5
|
+
access_token: caa4f8b2bb3d94269291faf9b54b85457db0173b
|
6
|
+
|
7
|
+
# If you want to test GitHub Authentication
|
8
|
+
github_oauth:
|
9
|
+
id: d2c8c96f8f226933186e
|
10
|
+
secret: e4ca5135bb7052318e8cc4e48f296ee58ad39e61
|
11
|
+
# teams:
|
12
|
+
|
13
|
+
# To work on the beta bootstrap re-write
|
14
|
+
# features:
|
15
|
+
# - bootstrap
|
16
|
+
|
@@ -0,0 +1,7 @@
|
|
1
|
+
class ReorderActiveTasksIndex < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
remove_index :tasks, name: :index_active_tasks
|
4
|
+
add_index :tasks, %i(stack_id allow_concurrency status), name: :index_active_tasks
|
5
|
+
remove_index :tasks, :stack_id # now useless since `index_active_tasks` starts by `stack_id`
|
6
|
+
end
|
7
|
+
end
|
data/lib/shipit/command.rb
CHANGED
@@ -15,7 +15,7 @@ module Shipit
|
|
15
15
|
|
16
16
|
attr_reader :out, :code, :chdir, :env, :args, :pid, :timeout
|
17
17
|
|
18
|
-
def initialize(*args, default_timeout:
|
18
|
+
def initialize(*args, default_timeout: Shipit.default_inactivity_timeout, env: {}, chdir:)
|
19
19
|
@args, options = parse_arguments(args)
|
20
20
|
@timeout = options['timeout'.freeze] || options[:timeout] || default_timeout
|
21
21
|
@env = env
|
@@ -170,12 +170,25 @@ module Shipit
|
|
170
170
|
end
|
171
171
|
|
172
172
|
def kill_and_wait(sig, wait, &block)
|
173
|
+
retry_count = 5
|
173
174
|
kill(sig, &block)
|
174
175
|
begin
|
175
176
|
with_timeout(wait) do
|
176
177
|
read_stream(@out, &block)
|
177
178
|
end
|
178
|
-
rescue TimedOut
|
179
|
+
rescue TimedOut
|
180
|
+
rescue Errno::EIO # EIO is somewhat expected on Linux: http://stackoverflow.com/a/10306782
|
181
|
+
# If we try to read the stream right after sending a signal, we often get an Errno::EIO.
|
182
|
+
if status = Process.wait(@pid, Process::WNOHANG)
|
183
|
+
return status
|
184
|
+
else
|
185
|
+
# If we let the child a little bit of time, it solves it.
|
186
|
+
retry_count -= 1
|
187
|
+
if retry_count > 0
|
188
|
+
sleep 0.05
|
189
|
+
retry
|
190
|
+
end
|
191
|
+
end
|
179
192
|
end
|
180
193
|
Process.wait(@pid, Process::WNOHANG)
|
181
194
|
end
|
data/lib/shipit/engine.rb
CHANGED
@@ -9,6 +9,7 @@ module Shipit
|
|
9
9
|
initializer 'shipit.config' do |app|
|
10
10
|
Rails.application.routes.default_url_options[:host] = Shipit.host
|
11
11
|
Shipit::Engine.routes.default_url_options[:host] = Shipit.host
|
12
|
+
Pubsubstub.redis_url = Shipit.redis_url.to_s
|
12
13
|
|
13
14
|
app.config.assets.paths << Emoji.images_path
|
14
15
|
app.config.assets.precompile += %w(
|
@@ -20,7 +21,7 @@ module Shipit
|
|
20
21
|
shipit_bs.css
|
21
22
|
)
|
22
23
|
app.config.assets.precompile << proc do |path|
|
23
|
-
path =~
|
24
|
+
path =~ %r{\Aplugins/[\-\w]+\.(js|css)\Z}
|
24
25
|
end
|
25
26
|
app.config.assets.precompile << proc do |path|
|
26
27
|
path.start_with?('emoji/') && path.end_with?('.png')
|
data/lib/shipit/stat.rb
ADDED
data/lib/shipit/version.rb
CHANGED
data/lib/shipit.rb
CHANGED
@@ -45,6 +45,7 @@ require 'shipit/task_commands'
|
|
45
45
|
require 'shipit/deploy_commands'
|
46
46
|
require 'shipit/rollback_commands'
|
47
47
|
require 'shipit/environment_variables'
|
48
|
+
require 'shipit/stat'
|
48
49
|
|
49
50
|
SafeYAML::OPTIONS[:default_mode] = :safe
|
50
51
|
SafeYAML::OPTIONS[:deserialize_symbols] = false
|
@@ -85,6 +86,14 @@ module Shipit
|
|
85
86
|
github_url('/api/v3/') if github_enterprise?
|
86
87
|
end
|
87
88
|
|
89
|
+
def user
|
90
|
+
if github_api.login
|
91
|
+
User.find_or_create_by_login!(github_api.login)
|
92
|
+
else
|
93
|
+
AnonymousUser.new
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
88
97
|
def github_api
|
89
98
|
@github_api ||= begin
|
90
99
|
client = Octokit::Client.new(github_api_credentials)
|
@@ -184,6 +193,10 @@ module Shipit
|
|
184
193
|
@bootstrap_view_path ||= Engine.root.join('app/views/bootstrap')
|
185
194
|
end
|
186
195
|
|
196
|
+
def default_inactivity_timeout
|
197
|
+
secrets.commands_inactivity_timeout || 5.minutes.to_i
|
198
|
+
end
|
199
|
+
|
187
200
|
protected
|
188
201
|
|
189
202
|
def revision_file
|
data/lib/tasks/cron.rake
CHANGED
@@ -10,11 +10,11 @@ module Shipit
|
|
10
10
|
extra: OmniAuth::AuthHash.new(
|
11
11
|
raw_info: OmniAuth::AuthHash.new(
|
12
12
|
id: 44,
|
13
|
-
name: 'Shipit',
|
14
|
-
email: 'shipit@example.com',
|
15
|
-
login: 'shipit',
|
13
|
+
name: 'Shipit User',
|
14
|
+
email: 'shipit-user@example.com',
|
15
|
+
login: 'shipit-user',
|
16
16
|
avatar_url: 'https://example.com',
|
17
|
-
api_url: 'https://github.com/api/v3/users/shipit',
|
17
|
+
api_url: 'https://github.com/api/v3/users/shipit-user',
|
18
18
|
),
|
19
19
|
),
|
20
20
|
)
|
@@ -24,7 +24,7 @@ module Shipit
|
|
24
24
|
get :callback
|
25
25
|
end
|
26
26
|
|
27
|
-
user = User.find_by_login('shipit')
|
27
|
+
user = User.find_by_login('shipit-user')
|
28
28
|
assert_equal 's3cr3t', user.github_access_token
|
29
29
|
assert_equal 44, user.github_id
|
30
30
|
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
local_secrets = Shipit::Engine.root.join('config/secrets.development.yml')
|
2
|
+
if local_secrets.exist?
|
3
|
+
secrets = YAML.load(local_secrets.read)
|
4
|
+
if Rails.env.development?
|
5
|
+
Rails.application.secrets.deep_merge!(secrets)
|
6
|
+
elsif Rails.env.test?
|
7
|
+
Rails.application.secrets.merge!(redis_url: secrets['redis_url'])
|
8
|
+
end
|
9
|
+
end
|
@@ -1,20 +1,5 @@
|
|
1
1
|
development:
|
2
|
-
features:
|
3
|
-
- bootstrap
|
4
2
|
secret_key_base: s3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3t
|
5
|
-
# github_domain: github.shopify.com
|
6
|
-
github_oauth:
|
7
|
-
id: 29f6c9084a8837f337ff
|
8
|
-
secret: 3f5d2c3bb35d4ff905189401c3a2c8f249800554
|
9
|
-
# team:
|
10
|
-
github_api:
|
11
|
-
access_token: d5a01c65f69d86ecc55dccdf347b19d6f9a16b3b
|
12
|
-
# login:
|
13
|
-
# password:
|
14
|
-
# api_endpoint:
|
15
|
-
host: 'http://localhost:3000'
|
16
|
-
redis_url: "redis://127.0.0.1:6379/7"
|
17
|
-
|
18
3
|
test:
|
19
4
|
secret_key_base: s3cr3ts3cr3ts3cr3ts3cr3ts3cr3ts3cr3t
|
20
5
|
host: shipit.com
|
@@ -26,5 +11,9 @@ test:
|
|
26
11
|
github_oauth:
|
27
12
|
id: 1d
|
28
13
|
secret: s3cr37
|
29
|
-
#
|
14
|
+
# teams:
|
15
|
+
# -
|
16
|
+
# -
|
30
17
|
redis_url: "redis://127.0.0.1:6379/7"
|
18
|
+
# features:
|
19
|
+
# - bootstrap
|
Binary file
|
data/test/dummy/db/schema.rb
CHANGED
@@ -11,7 +11,7 @@
|
|
11
11
|
#
|
12
12
|
# It's strongly recommended that you check this file into your version control system.
|
13
13
|
|
14
|
-
ActiveRecord::Schema.define(version:
|
14
|
+
ActiveRecord::Schema.define(version: 20160526192650) do
|
15
15
|
|
16
16
|
create_table "api_clients", force: :cascade do |t|
|
17
17
|
t.text "permissions", limit: 65535
|
@@ -130,21 +130,22 @@ ActiveRecord::Schema.define(version: 20160426155146) do
|
|
130
130
|
add_index "output_chunks", ["task_id"], name: "index_output_chunks_on_task_id"
|
131
131
|
|
132
132
|
create_table "stacks", force: :cascade do |t|
|
133
|
-
t.string "repo_name",
|
134
|
-
t.string "repo_owner",
|
135
|
-
t.string "environment",
|
133
|
+
t.string "repo_name", limit: 100, null: false
|
134
|
+
t.string "repo_owner", limit: 39, null: false
|
135
|
+
t.string "environment", limit: 50, default: "production", null: false
|
136
136
|
t.datetime "created_at"
|
137
137
|
t.datetime "updated_at"
|
138
|
-
t.string "branch",
|
139
|
-
t.string "deploy_url",
|
140
|
-
t.string "lock_reason",
|
141
|
-
t.integer "tasks_count",
|
142
|
-
t.boolean "continuous_deployment",
|
143
|
-
t.integer "undeployed_commits_count",
|
144
|
-
t.text "cached_deploy_spec",
|
145
|
-
t.integer "lock_author_id",
|
138
|
+
t.string "branch", limit: 255, default: "master", null: false
|
139
|
+
t.string "deploy_url", limit: 255
|
140
|
+
t.string "lock_reason", limit: 4096
|
141
|
+
t.integer "tasks_count", limit: 4, default: 0, null: false
|
142
|
+
t.boolean "continuous_deployment", default: false, null: false
|
143
|
+
t.integer "undeployed_commits_count", limit: 4, default: 0, null: false
|
144
|
+
t.text "cached_deploy_spec", limit: 65535
|
145
|
+
t.integer "lock_author_id", limit: 4
|
146
146
|
t.boolean "ignore_ci"
|
147
147
|
t.datetime "inaccessible_since"
|
148
|
+
t.integer "estimated_deploy_duration", default: 1, null: false
|
148
149
|
end
|
149
150
|
|
150
151
|
add_index "stacks", ["repo_owner", "repo_name", "environment"], name: "stack_unicity", unique: true
|
@@ -186,8 +187,7 @@ ActiveRecord::Schema.define(version: 20160426155146) do
|
|
186
187
|
|
187
188
|
add_index "tasks", ["rolled_up", "created_at", "status"], name: "index_tasks_on_rolled_up_and_created_at_and_status"
|
188
189
|
add_index "tasks", ["since_commit_id"], name: "index_tasks_on_since_commit_id"
|
189
|
-
add_index "tasks", ["stack_id"], name: "
|
190
|
-
add_index "tasks", ["status", "stack_id", "allow_concurrency"], name: "index_active_tasks"
|
190
|
+
add_index "tasks", ["stack_id", "allow_concurrency", "status"], name: "index_active_tasks"
|
191
191
|
add_index "tasks", ["type", "stack_id", "parent_id"], name: "index_tasks_by_stack_and_parent"
|
192
192
|
add_index "tasks", ["type", "stack_id", "status"], name: "index_tasks_by_stack_and_status"
|
193
193
|
add_index "tasks", ["until_commit_id"], name: "index_tasks_on_until_commit_id"
|
data/test/dummy/db/seeds.rb
CHANGED
data/test/dummy/db/test.sqlite3
CHANGED
Binary file
|
@@ -16,7 +16,7 @@ shipit:
|
|
16
16
|
]
|
17
17
|
},
|
18
18
|
"dependencies": {"override": []},
|
19
|
-
"deploy": {"override": null, "variables": [{"name": "SAFETY_DISABLED", "title": "Set to 1 to do dangerous things", "default": 0}]},
|
19
|
+
"deploy": {"override": null, "interval": 60, "variables": [{"name": "SAFETY_DISABLED", "title": "Set to 1 to do dangerous things", "default": 0}]},
|
20
20
|
"rollback": {"override": ["echo 'Rollback!'"]},
|
21
21
|
"fetch": ["echo '42'"],
|
22
22
|
"tasks": {
|
@@ -65,7 +65,7 @@ cyclimse:
|
|
65
65
|
]
|
66
66
|
},
|
67
67
|
"dependencies": {"override": []},
|
68
|
-
"deploy": {"override": null},
|
68
|
+
"deploy": {"max_commits": 2, "interval": 60, "override": null},
|
69
69
|
"rollback": {"override": ["echo 'Rollback!'"]},
|
70
70
|
"fetch": ["echo '42'"],
|
71
71
|
"tasks": {
|
@@ -8,6 +8,8 @@ shipit:
|
|
8
8
|
additions: 1
|
9
9
|
deletions: 1
|
10
10
|
created_at: <%= (60 - 1).minutes.ago.to_s(:db) %>
|
11
|
+
started_at: <%= (60 - 1).minutes.ago.to_s(:db) %>
|
12
|
+
ended_at: <%= (60 - 3).minutes.ago.to_s(:db) %>
|
11
13
|
|
12
14
|
shipit2:
|
13
15
|
user: walrus
|
@@ -79,7 +81,7 @@ shipit_complete:
|
|
79
81
|
deletions: 342
|
80
82
|
created_at: <%= (60 - 6).minutes.ago.to_s(:db) %>
|
81
83
|
started_at: <%= (60 - 6).minutes.ago.to_s(:db) %>
|
82
|
-
ended_at: <%= (60 -
|
84
|
+
ended_at: <%= (60 - 8).minutes.ago.to_s(:db) %>
|
83
85
|
|
84
86
|
shipit_aborted:
|
85
87
|
user: bob
|
@@ -7,7 +7,7 @@ module QueriesHelper
|
|
7
7
|
counter = SQLCounter.new(ignored_sql)
|
8
8
|
subscriber = ActiveSupport::Notifications.subscribe('sql.active_record', counter)
|
9
9
|
yield counter
|
10
|
-
queries = counter.log.
|
10
|
+
queries = counter.log.empty? ? '' : "\nQueries:\n#{counter.log.join("\n")}"
|
11
11
|
assert_equal num, counter.log.size, "#{counter.log.size} instead of #{num} queries were executed.#{queries}"
|
12
12
|
ensure
|
13
13
|
ActiveSupport::Notifications.unsubscribe(subscriber)
|
data/test/models/deploys_test.rb
CHANGED
@@ -218,6 +218,13 @@ module Shipit
|
|
218
218
|
end
|
219
219
|
end
|
220
220
|
|
221
|
+
test "transitioning to success schedule an update of the estimated deploy duration" do
|
222
|
+
@deploy = shipit_deploys(:shipit_running)
|
223
|
+
assert_enqueued_with(job: UpdateEstimatedDeployDurationJob, args: [@deploy.stack]) do
|
224
|
+
@deploy.complete!
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
221
228
|
test "transitioning to success schedule a fetch of the deployed revision" do
|
222
229
|
@deploy = shipit_deploys(:shipit_running)
|
223
230
|
assert_enqueued_with(job: FetchDeployedRevisionJob, args: [@deploy.stack]) do
|
@@ -2,6 +2,17 @@ require 'test_helper'
|
|
2
2
|
|
3
3
|
module Shipit
|
4
4
|
class DurationTest < ActiveSupport::TestCase
|
5
|
+
test "#<=> allow comparisons" do
|
6
|
+
assert_equal Duration.new(1), Duration.new(1)
|
7
|
+
assert Duration.new(2) > Duration.new(1)
|
8
|
+
assert Duration.new(2) > 1
|
9
|
+
assert 1 < Duration.new(2)
|
10
|
+
end
|
11
|
+
|
12
|
+
test "can be added to a Time instance" do
|
13
|
+
assert_equal Time.at(42), Time.at(40) + Duration.new(2)
|
14
|
+
end
|
15
|
+
|
5
16
|
test "#to_s is precise and readable for humans" do
|
6
17
|
assert_equal '1m01s', Duration.new(61).to_s
|
7
18
|
assert_equal '1m00s', Duration.new(60).to_s
|
@@ -9,5 +20,17 @@ module Shipit
|
|
9
20
|
assert_equal '2d00h00m00s', Duration.new(2.days).to_s
|
10
21
|
assert_equal '0s', Duration.new(0).to_s
|
11
22
|
end
|
23
|
+
|
24
|
+
test ".parse can read human format" do
|
25
|
+
assert_equal Duration.new(61), Duration.parse('1m01s')
|
26
|
+
assert_equal Duration.new(60), Duration.parse('1m00s')
|
27
|
+
assert_equal Duration.new(59), Duration.parse('59s')
|
28
|
+
assert_equal Duration.new(2.days), Duration.parse('2d00h00m00s')
|
29
|
+
assert_equal Duration.new(0), Duration.parse('0s')
|
30
|
+
end
|
31
|
+
|
32
|
+
test ".parse accepts integers as seconds" do
|
33
|
+
assert_equal Duration.new(42), Duration.parse(42)
|
34
|
+
end
|
12
35
|
end
|
13
36
|
end
|