shipit-engine 0.7.0 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (92) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +50 -2
  3. data/app/assets/stylesheets/_pages/_deploy.scss +3 -2
  4. data/app/controllers/shipit/api/base_controller.rb +5 -0
  5. data/app/controllers/shipit/api/deploys_controller.rb +2 -1
  6. data/app/controllers/shipit/api/tasks_controller.rb +4 -1
  7. data/app/controllers/shipit/deploys_controller.rb +1 -1
  8. data/app/controllers/shipit/github_authentication_controller.rb +4 -2
  9. data/app/controllers/shipit/rollbacks_controller.rb +1 -1
  10. data/app/controllers/shipit/tasks_controller.rb +14 -2
  11. data/app/helpers/shipit/github_url_helper.rb +4 -2
  12. data/app/helpers/shipit/stacks_helper.rb +3 -3
  13. data/app/jobs/shipit/continuous_delivery_job.rb +12 -0
  14. data/app/jobs/shipit/create_on_github_job.rb +11 -0
  15. data/app/jobs/shipit/fetch_deployed_revision_job.rb +1 -1
  16. data/app/models/shipit/anonymous_user.rb +4 -0
  17. data/app/models/shipit/commit.rb +8 -10
  18. data/app/models/shipit/commit_deployment.rb +56 -0
  19. data/app/models/shipit/commit_deployment_status.rb +57 -0
  20. data/app/models/shipit/deploy.rb +32 -6
  21. data/app/models/shipit/deploy_spec.rb +8 -0
  22. data/app/models/shipit/deploy_spec/rubygems_discovery.rb +1 -1
  23. data/app/models/shipit/rollback.rb +10 -0
  24. data/app/models/shipit/stack.rb +30 -12
  25. data/app/models/shipit/status_group.rb +1 -1
  26. data/app/models/shipit/task.rb +1 -0
  27. data/app/models/shipit/task_definition.rb +20 -1
  28. data/app/models/shipit/user.rb +10 -2
  29. data/app/models/shipit/variable_definition.rb +2 -4
  30. data/app/serializers/shipit/commit_serializer.rb +19 -1
  31. data/app/serializers/shipit/deploy_serializer.rb +7 -1
  32. data/app/serializers/shipit/short_commit_serializer.rb +1 -1
  33. data/app/serializers/shipit/task_serializer.rb +17 -1
  34. data/app/views/shipit/_variables.html.erb +15 -0
  35. data/app/views/shipit/deploys/_concurrent_deploy_warning.html.erb +1 -1
  36. data/app/views/shipit/deploys/_deploy.html.erb +2 -2
  37. data/app/views/shipit/deploys/new.html.erb +3 -17
  38. data/app/views/shipit/deploys/rollback.html.erb +3 -17
  39. data/app/views/shipit/tasks/new.html.erb +12 -4
  40. data/config/locales/en.yml +11 -0
  41. data/db/migrate/20160210183823_add_allow_concurrency_to_tasks.rb +5 -0
  42. data/db/migrate/20160303163611_create_shipit_commit_deployments.rb +14 -0
  43. data/db/migrate/20160303170913_create_shipit_commit_deployment_statuses.rb +12 -0
  44. data/db/migrate/20160303203940_add_encrypted_token_to_users.rb +6 -0
  45. data/lib/shipit.rb +7 -1
  46. data/lib/shipit/engine.rb +3 -1
  47. data/lib/shipit/environment_variables.rb +34 -0
  48. data/lib/shipit/simple_message_verifier.rb +0 -1
  49. data/lib/shipit/task_commands.rb +1 -0
  50. data/lib/shipit/version.rb +1 -1
  51. data/test/controllers/api/deploys_controller_test.rb +15 -0
  52. data/test/controllers/api/tasks_controller_test.rb +15 -0
  53. data/test/controllers/github_authentication_controller_test.rb +23 -5
  54. data/test/controllers/tasks_controller_test.rb +27 -2
  55. data/test/controllers/webhooks_controller_test.rb +8 -2
  56. data/test/dummy/config/database.mysql.yml +1 -1
  57. data/test/dummy/config/secrets.example.yml +2 -2
  58. data/test/dummy/config/secrets.yml +2 -2
  59. data/test/dummy/data/stacks/byroot/junk/production/git/bar.txt +1 -0
  60. data/test/dummy/data/stacks/byroot/junk/production/git/dkfdsf +0 -0
  61. data/test/dummy/data/stacks/byroot/junk/production/git/dskjfsd +0 -0
  62. data/test/dummy/data/stacks/byroot/junk/production/git/dslkjfjsdf +0 -0
  63. data/test/dummy/data/stacks/byroot/junk/production/git/plopfizz +0 -0
  64. data/test/dummy/data/stacks/byroot/junk/production/git/sd +0 -0
  65. data/test/dummy/data/stacks/byroot/junk/production/git/sdkfjsdf +1 -0
  66. data/test/dummy/data/stacks/byroot/junk/production/git/sdlfjsdfdsfj +0 -0
  67. data/test/dummy/data/stacks/byroot/junk/production/git/sdlkfjsdlkfjsdlkfjdsfsdfksdfjsldkfjsdlkfjsdf +0 -0
  68. data/test/dummy/data/stacks/byroot/junk/production/git/shipit.yml +27 -0
  69. data/test/dummy/data/stacks/byroot/junk/production/git/toto.txt +2 -0
  70. data/test/dummy/db/development.sqlite3 +0 -0
  71. data/test/dummy/db/schema.rb +35 -7
  72. data/test/dummy/db/seeds.rb +3 -0
  73. data/test/dummy/db/test.sqlite3 +0 -0
  74. data/test/fixtures/shipit/commit_deployment_statuses.yml +19 -0
  75. data/test/fixtures/shipit/commit_deployments.yml +37 -0
  76. data/test/fixtures/shipit/commits.yml +1 -1
  77. data/test/fixtures/shipit/stacks.yml +12 -0
  78. data/test/fixtures/shipit/tasks.yml +4 -0
  79. data/test/fixtures/shipit/users.yml +2 -0
  80. data/test/jobs/fetch_deployed_revision_job_test.rb +3 -3
  81. data/test/models/commit_deployment_status_test.rb +27 -0
  82. data/test/models/commit_deployment_test.rb +37 -0
  83. data/test/models/commits_test.rb +7 -4
  84. data/test/models/deploys_test.rb +17 -1
  85. data/test/models/stacks_test.rb +13 -13
  86. data/test/models/task_definitions_test.rb +10 -0
  87. data/test/models/team_test.rb +8 -2
  88. data/test/models/users_test.rb +20 -2
  89. data/test/unit/deploy_spec_test.rb +29 -0
  90. data/test/unit/environment_variables_test.rb +36 -0
  91. data/test/unit/github_url_helper_test.rb +0 -8
  92. metadata +76 -20
@@ -0,0 +1,27 @@
1
+ review:
2
+ checklist:
3
+ - Blah Blah
4
+ checks:
5
+ - echo 42
6
+
7
+ deploy:
8
+ variables:
9
+ -
10
+ name: REBUILD
11
+ title: Force artifacts rebuild
12
+ default: '0'
13
+ override:
14
+ - echo 1
15
+ - sleep 10
16
+
17
+ rollback:
18
+ override:
19
+ - echo done
20
+
21
+
22
+ tasks:
23
+ restart:
24
+ action: Restart application
25
+ description: Trigger the restart of both app and jobs servers
26
+ steps:
27
+ - cap $ENVIRONMENT deploy:restart
Binary file
@@ -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: 20160122165559) do
14
+ ActiveRecord::Schema.define(version: 20160303203940) do
15
15
 
16
16
  create_table "api_clients", force: :cascade do |t|
17
17
  t.text "permissions", limit: 65535
@@ -24,6 +24,29 @@ ActiveRecord::Schema.define(version: 20160122165559) do
24
24
 
25
25
  add_index "api_clients", ["creator_id"], name: "index_api_clients_on_creator_id"
26
26
 
27
+ create_table "commit_deployment_statuses", force: :cascade do |t|
28
+ t.integer "commit_deployment_id"
29
+ t.string "status"
30
+ t.integer "github_id"
31
+ t.string "api_url"
32
+ t.datetime "created_at", null: false
33
+ t.datetime "updated_at", null: false
34
+ end
35
+
36
+ add_index "commit_deployment_statuses", ["commit_deployment_id"], name: "index_commit_deployment_statuses_on_commit_deployment_id"
37
+
38
+ create_table "commit_deployments", force: :cascade do |t|
39
+ t.integer "commit_id"
40
+ t.integer "task_id"
41
+ t.integer "github_id"
42
+ t.string "api_url"
43
+ t.datetime "created_at", null: false
44
+ t.datetime "updated_at", null: false
45
+ end
46
+
47
+ add_index "commit_deployments", ["commit_id", "task_id"], name: "index_commit_deployments_on_commit_id_and_task_id", unique: true
48
+ add_index "commit_deployments", ["task_id"], name: "index_commit_deployments_on_task_id"
49
+
27
50
  create_table "commits", force: :cascade do |t|
28
51
  t.integer "stack_id", limit: 4, null: false
29
52
  t.integer "author_id", limit: 4, null: false
@@ -156,11 +179,14 @@ ActiveRecord::Schema.define(version: 20160122165559) do
156
179
  t.boolean "rollback_once_aborted", default: false, null: false
157
180
  t.text "env"
158
181
  t.integer "confirmations", default: 0, null: false
182
+ t.boolean "allow_concurrency", default: false, null: false
159
183
  end
160
184
 
161
185
  add_index "tasks", ["rolled_up", "created_at", "status"], name: "index_tasks_on_rolled_up_and_created_at_and_status"
162
186
  add_index "tasks", ["since_commit_id"], name: "index_tasks_on_since_commit_id"
163
187
  add_index "tasks", ["stack_id"], name: "index_tasks_on_stack_id"
188
+ add_index "tasks", ["type", "stack_id", "parent_id"], name: "index_tasks_by_stack_and_parent"
189
+ add_index "tasks", ["type", "stack_id", "status"], name: "index_tasks_by_stack_and_status"
164
190
  add_index "tasks", ["until_commit_id"], name: "index_tasks_on_until_commit_id"
165
191
  add_index "tasks", ["user_id"], name: "index_tasks_on_user_id"
166
192
 
@@ -177,14 +203,16 @@ ActiveRecord::Schema.define(version: 20160122165559) do
177
203
  add_index "teams", ["organization", "slug"], name: "index_teams_on_organization_and_slug", unique: true
178
204
 
179
205
  create_table "users", force: :cascade do |t|
180
- t.integer "github_id", limit: 4
181
- t.string "name", limit: 255, null: false
182
- t.string "email", limit: 255
183
- t.string "login", limit: 39
184
- t.string "api_url", limit: 255
206
+ t.integer "github_id", limit: 4
207
+ t.string "name", limit: 255, null: false
208
+ t.string "email", limit: 255
209
+ t.string "login", limit: 39
210
+ t.string "api_url", limit: 255
185
211
  t.datetime "created_at"
186
212
  t.datetime "updated_at"
187
- t.string "avatar_url", limit: 255
213
+ t.string "avatar_url", limit: 255
214
+ t.string "encrypted_github_access_token"
215
+ t.string "encrypted_github_access_token_iv"
188
216
  end
189
217
 
190
218
  add_index "users", ["login"], name: "index_users_on_login"
@@ -51,6 +51,9 @@ module Shipit
51
51
  "steps": [
52
52
  "bundle exec cap $ENVIRONMENT deploy:restart"
53
53
  ],
54
+ "variables": [
55
+ {"name": "SAFETY_DISABLED", "title": "Set to 1 to do stuff", "default": "0"}
56
+ ],
54
57
  "checklist": [
55
58
  "Hold on your butts",
56
59
  "Eat some chips"
Binary file
@@ -0,0 +1,19 @@
1
+ shipit_deploy_second_pending:
2
+ commit_deployment: shipit_deploy_second
3
+ status: pending
4
+ github_id: 42
5
+ api_url: https://api.github.com/repos/shopify/shipit-engine/deployments/1/statuses/42
6
+
7
+ shipit_deploy_second_success:
8
+ commit_deployment: shipit_deploy_second
9
+ status: success
10
+ github_id: 43
11
+ api_url: https://api.github.com/repos/shopify/shipit-engine/deployments/1/statuses/43
12
+
13
+ shipit2_deploy_third_pending:
14
+ commit_deployment: shipit2_deploy_third
15
+ status: pending
16
+
17
+ shipit2_deploy_third_failure:
18
+ commit_deployment: shipit2_deploy_third
19
+ status: failure
@@ -0,0 +1,37 @@
1
+ shipit_deploy_second:
2
+ commit_id: 2 # second
3
+ task: shipit
4
+ api_url: https://api.github.com/repos/shopify/shipit-engine/deployments/1
5
+ github_id: 1
6
+
7
+ shipit2_deploy_third:
8
+ commit_id: 3 # third
9
+ task: shipit2
10
+ api_url: https://api.github.com/repos/shopify/shipit-engine/deployments/2
11
+ github_id: 2
12
+
13
+ shipit_pending_third:
14
+ commit_id: 3 # third
15
+ task: shipit_pending
16
+ api_url: https://api.github.com/repos/shopify/shipit-engine/deployments/3
17
+ github_id: 3
18
+
19
+ shipit_pending_fourth:
20
+ commit_id: 4 # fourth
21
+ task: shipit_pending
22
+
23
+ shipit_running_fourth:
24
+ commit_id: 4 # fourth
25
+ task: shipit_running
26
+
27
+ shipit_complete_fourth:
28
+ commit_id: 4 # fourth
29
+ task: shipit_complete
30
+
31
+ shipit_aborted_fourth:
32
+ commit_id: 4 # fourth
33
+ task: shipit_aborted
34
+
35
+ shipit_rollback_fourth:
36
+ commit_id: 4 # fourth
37
+ task: shipit_rollback
@@ -40,7 +40,7 @@ third:
40
40
  fourth:
41
41
  id: 4
42
42
  sha: 467578b362bf2b4df5903e1c7960929361c3435a
43
- message: "#yoloshipit!"
43
+ message: "Merge pull request #7 from shipit-engine/yoloshipit\n\nyoloshipit!"
44
44
  stack: shipit
45
45
  author: walrus
46
46
  committer: walrus
@@ -23,9 +23,21 @@ shipit:
23
23
  "restart": {
24
24
  "action": "Restart application",
25
25
  "description": "Restart app and job servers",
26
+ "variables": [
27
+ {"name": "FOO", "title": "Set to 0 to foo", "default": 1},
28
+ {"name": "BAR", "title": "Set to 1 to bar", "default": 0}
29
+ ],
26
30
  "steps": [
27
31
  "cap $ENVIRONMENT deploy:restart"
28
32
  ]
33
+ },
34
+ "flush_cache": {
35
+ "action": "Flush cache",
36
+ "description": "Flush the application cache",
37
+ "steps": [
38
+ "cap $ENVIRONMENT cache:flush"
39
+ ],
40
+ "allow_concurrency": true
29
41
  }
30
42
  },
31
43
  "ci": {
@@ -32,6 +32,10 @@ shipit_restart:
32
32
  "id": "restart",
33
33
  "action": "Restart application",
34
34
  "description": "Restart app and job servers",
35
+ "variables": [
36
+ {"name": "FOO", "title": "Set to 0 to foo", "default": 1},
37
+ {"name": "BAR", "title": "Set to 1 to bar", "default": 0}
38
+ ],
35
39
  "steps": [
36
40
  "cap $ENVIRONMENT deploy:restart"
37
41
  ]
@@ -2,6 +2,8 @@ walrus:
2
2
  name: Lando Walrussian
3
3
  email: walrus@shopify.com
4
4
  login: walrus
5
+ encrypted_github_access_token: FuQv9jpHmMZ8Px64xmqASJtKlefv # t0k3n
6
+ encrypted_github_access_token_iv: "QNS4smChXEXtOjxb\n"
5
7
 
6
8
  bob:
7
9
  name: Bob the Builder
@@ -9,21 +9,21 @@ module Shipit
9
9
  end
10
10
 
11
11
  test 'the job abort if the stack is deploying' do
12
- @stack.expects(:deploying?).returns(true)
12
+ @stack.expects(:active_task?).returns(true)
13
13
  assert_no_difference 'Deploy.count' do
14
14
  @job.perform(@stack)
15
15
  end
16
16
  end
17
17
 
18
18
  test 'the job abort if #fetch_deployed_revision returns nil' do
19
- @stack.expects(:deploying?).returns(false)
19
+ @stack.expects(:active_task?).returns(false)
20
20
  StackCommands.any_instance.expects(:fetch_deployed_revision).returns(nil)
21
21
  @stack.expects(:update_deployed_revision).never
22
22
  @job.perform(@stack)
23
23
  end
24
24
 
25
25
  test 'the job call update_deployed_revision if #fetch_deployed_revision returns something' do
26
- @stack.expects(:deploying?).returns(false)
26
+ @stack.expects(:active_task?).returns(false)
27
27
  StackCommands.any_instance.expects(:fetch_deployed_revision).returns(@commit.sha)
28
28
  @stack.expects(:update_deployed_revision).with(@commit.sha)
29
29
  @job.perform(@stack)
@@ -0,0 +1,27 @@
1
+ require 'test_helper'
2
+
3
+ module Shipit
4
+ class CommitDeploymentStatusTest < ActiveSupport::TestCase
5
+ setup do
6
+ @status = shipit_commit_deployment_statuses(:shipit2_deploy_third_pending)
7
+ @deployment = @status.commit_deployment
8
+ @task = @deployment.task
9
+ @commit = @deployment.commit
10
+ @author = @deployment.author
11
+ end
12
+
13
+ test 'creation on GitHub' do
14
+ response = stub(id: 44, url: 'https://example.com')
15
+ @author.github_api.expects(:create_deployment_status).with(
16
+ @deployment.api_url,
17
+ 'pending',
18
+ target_url: "http://shipit.com/shopify/shipit-engine/production/deploys/#{@task.id}",
19
+ description: "walrus triggered the deploy of shopify/shipit-engine/production to #{@commit.sha}",
20
+ ).returns(response)
21
+
22
+ @status.create_on_github!
23
+ assert_equal response.id, @status.github_id
24
+ assert_equal response.url, @status.api_url
25
+ end
26
+ end
27
+ end
@@ -0,0 +1,37 @@
1
+ require 'test_helper'
2
+
3
+ module Shipit
4
+ class CommitDeploymentTest < ActiveSupport::TestCase
5
+ setup do
6
+ @deployment = shipit_commit_deployments(:shipit_pending_fourth)
7
+ @commit = @deployment.commit
8
+ @task = @deployment.task
9
+ @stack = @task.stack
10
+ @author = @deployment.author
11
+ end
12
+
13
+ test "there can only be one record per deploy and commit pair" do
14
+ assert_raises ActiveRecord::RecordNotUnique do
15
+ CommitDeployment.create!(task: @deployment.task, commit: @deployment.commit)
16
+ end
17
+ end
18
+
19
+ test "creation on GitHub" do
20
+ pull_request_response = stub(head: stub(sha: '6dcb09b5b57875f334f61aebed695e2e4193db5e'))
21
+ @author.github_api.expects(:pull_request).with('shopify/shipit-engine', 7).returns(pull_request_response)
22
+
23
+ deployment_response = stub(id: 42, url: 'https://example.com')
24
+ @author.github_api.expects(:create_deployment).with(
25
+ 'shopify/shipit-engine',
26
+ pull_request_response.head.sha,
27
+ auto_merge: false,
28
+ description: "Via Shipit",
29
+ environment: @stack.environment,
30
+ ).returns(deployment_response)
31
+
32
+ @deployment.create_on_github!
33
+ assert_equal deployment_response.id, @deployment.github_id
34
+ assert_equal deployment_response.url, @deployment.api_url
35
+ end
36
+ end
37
+ end
@@ -20,9 +20,9 @@ module Shipit
20
20
  assert_equal "Bump to v1.0.1", @pr.pull_request_title
21
21
  end
22
22
 
23
- test "#pull_request_id extract the pull request id from the message" do
24
- assert_equal 31, @pr.pull_request_id
25
- assert_nil @commit.pull_request_id
23
+ test "#pull_request_number extract the pull request id from the message" do
24
+ assert_equal 31, @pr.pull_request_number
25
+ assert_nil @commit.pull_request_number
26
26
  end
27
27
 
28
28
  test "#pull_request_title extract the pull request title from the message" do
@@ -69,7 +69,10 @@ module Shipit
69
69
  @stack.deploys.destroy_all
70
70
 
71
71
  assert_difference "Deploy.count" do
72
- @stack.commits.last.statuses.create!(state: 'success', context: 'ci/travis')
72
+ assert_enqueued_with(job: ContinuousDeliveryJob, args: [@stack]) do
73
+ @stack.commits.last.statuses.create!(state: 'success', context: 'ci/travis')
74
+ end
75
+ ContinuousDeliveryJob.new.perform(@stack)
73
76
  end
74
77
  end
75
78
 
@@ -148,10 +148,14 @@ module Shipit
148
148
  shipit_commits(:fifth).statuses.create!(state: 'success')
149
149
 
150
150
  deploy = shipit_deploys(:shipit_running)
151
+ deploy.stack.tasks.where.not(id: deploy.id).update_all(status: 'success')
151
152
  deploy.stack.update(continuous_deployment: true)
152
153
 
153
154
  assert_difference "Deploy.count" do
154
- deploy.complete!
155
+ assert_enqueued_with(job: ContinuousDeliveryJob, args: [deploy.stack]) do
156
+ deploy.complete!
157
+ end
158
+ ContinuousDeliveryJob.new.perform(deploy.stack)
155
159
  end
156
160
  end
157
161
 
@@ -207,6 +211,18 @@ module Shipit
207
211
  end
208
212
  end
209
213
 
214
+ test "creating a deploy creates one CommitDeployment per commit" do
215
+ shipit = shipit_stacks(:shipit)
216
+ deploy = shipit.deploys.build(
217
+ since_commit: shipit.commits.first,
218
+ until_commit: shipit.commits.last,
219
+ )
220
+
221
+ assert_difference -> { CommitDeployment.count }, deploy.commits.size do
222
+ deploy.save!
223
+ end
224
+ end
225
+
210
226
  test "#build_rollback returns an unsaved record" do
211
227
  assert @deploy.build_rollback.new_record?
212
228
  end
@@ -205,39 +205,39 @@ module Shipit
205
205
  shipit_stacks(:shipit).destroy
206
206
  end
207
207
 
208
- test "#deploying? is false if stack has no deploy in either pending or running state" do
208
+ test "#active_task? is false if stack has no deploy in either pending or running state" do
209
209
  @stack.deploys.active.destroy_all
210
- refute @stack.deploying?
210
+ refute @stack.active_task?
211
211
  end
212
212
 
213
- test "#deploying? is false if stack has no deploy at all" do
213
+ test "#active_task? is false if stack has no deploy at all" do
214
214
  @stack.deploys.destroy_all
215
- refute @stack.deploying?
215
+ refute @stack.active_task?
216
216
  end
217
217
 
218
- test "#deploying? is true if stack has a deploy in either pending or running state" do
218
+ test "#active_task? is true if stack has a deploy in either pending or running state" do
219
219
  @stack.trigger_deploy(shipit_commits(:third), AnonymousUser.new)
220
- assert @stack.deploying?
220
+ assert @stack.active_task?
221
221
  end
222
222
 
223
- test "#deploying? is true if a rollback is ongoing" do
223
+ test "#active_task? is true if a rollback is ongoing" do
224
224
  shipit_deploys(:shipit_complete).trigger_rollback(AnonymousUser.new)
225
- assert @stack.deploying?
225
+ assert @stack.active_task?
226
226
  end
227
227
 
228
- test "#deploying? is memoized" do
228
+ test "#active_task? is memoized" do
229
229
  assert_queries(1) do
230
- 10.times { @stack.deploying? }
230
+ 10.times { @stack.active_task? }
231
231
  end
232
232
  end
233
233
 
234
- test "#deploying? cache is cleared if a deploy change state" do
234
+ test "#active_task? cache is cleared if a deploy change state" do
235
235
  assert_queries(1) do
236
- 10.times { @stack.deploying? }
236
+ 10.times { @stack.active_task? }
237
237
  end
238
238
  @stack.tasks.where(status: 'running').first.error!
239
239
  assert_queries(1) do
240
- 10.times { @stack.deploying? }
240
+ 10.times { @stack.active_task? }
241
241
  end
242
242
  end
243
243