shipit-engine 0.32.0 → 0.35.1

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.
Files changed (235) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +13 -2
  3. data/app/assets/images/magic-solid.svg +1 -0
  4. data/app/assets/javascripts/shipit/repositories_search.js.coffee +60 -0
  5. data/app/assets/javascripts/shipit/{search.js.coffee → stack_search.js.coffee} +0 -0
  6. data/app/assets/stylesheets/_pages/_deploy.scss +2 -3
  7. data/app/assets/stylesheets/_pages/_repositories.scss +148 -0
  8. data/app/assets/stylesheets/_pages/_stacks.scss +19 -0
  9. data/app/assets/stylesheets/shipit.scss +1 -0
  10. data/app/controllers/shipit/api/ccmenu_controller.rb +1 -1
  11. data/app/controllers/shipit/api/deploys_controller.rb +2 -0
  12. data/app/controllers/shipit/api/{pull_requests_controller.rb → merge_requests_controller.rb} +8 -8
  13. data/app/controllers/shipit/api/rollbacks_controller.rb +2 -1
  14. data/app/controllers/shipit/api/stacks_controller.rb +15 -1
  15. data/app/controllers/shipit/deploys_controller.rb +1 -1
  16. data/app/controllers/shipit/merge_requests_controller.rb +31 -0
  17. data/app/controllers/shipit/merge_status_controller.rb +15 -15
  18. data/app/controllers/shipit/repositories_controller.rb +74 -0
  19. data/app/controllers/shipit/stacks_controller.rb +2 -2
  20. data/app/controllers/shipit/tasks_controller.rb +2 -2
  21. data/app/controllers/shipit/webhooks_controller.rb +23 -4
  22. data/app/helpers/shipit/chunks_helper.rb +2 -2
  23. data/app/helpers/shipit/github_url_helper.rb +8 -0
  24. data/app/helpers/shipit/shipit_helper.rb +0 -1
  25. data/app/helpers/shipit/stacks_helper.rb +4 -0
  26. data/app/jobs/shipit/create_on_github_job.rb +1 -0
  27. data/app/jobs/shipit/deliver_hook_job.rb +1 -1
  28. data/app/jobs/shipit/destroy_repository_job.rb +24 -0
  29. data/app/jobs/shipit/destroy_stack_job.rb +2 -2
  30. data/app/jobs/shipit/github_sync_job.rb +13 -9
  31. data/app/jobs/shipit/perform_task_job.rb +4 -98
  32. data/app/jobs/shipit/process_merge_requests_job.rb +32 -0
  33. data/app/jobs/shipit/refresh_merge_request_job.rb +11 -0
  34. data/app/jobs/shipit/update_github_last_deployed_ref_job.rb +1 -1
  35. data/app/models/shipit/anonymous_user.rb +10 -2
  36. data/app/models/shipit/check_run.rb +38 -2
  37. data/app/models/shipit/command_line_user.rb +4 -0
  38. data/app/models/shipit/commit.rb +31 -20
  39. data/app/models/shipit/commit_checks.rb +14 -13
  40. data/app/models/shipit/commit_deployment.rb +3 -3
  41. data/app/models/shipit/commit_deployment_status.rb +3 -3
  42. data/app/models/shipit/deploy.rb +17 -11
  43. data/app/models/shipit/deploy_spec/file_system.rb +11 -5
  44. data/app/models/shipit/deploy_spec/lerna_discovery.rb +12 -4
  45. data/app/models/shipit/deploy_spec.rb +16 -4
  46. data/app/models/shipit/duration.rb +2 -0
  47. data/app/models/shipit/hook.rb +28 -2
  48. data/app/models/shipit/merge_request.rb +304 -0
  49. data/app/models/shipit/provisioning_handler/base.rb +30 -0
  50. data/app/models/shipit/provisioning_handler/unregistered_provisioning_handler.rb +35 -0
  51. data/app/models/shipit/provisioning_handler.rb +32 -0
  52. data/app/models/shipit/pull_request.rb +26 -265
  53. data/app/models/shipit/pull_request_assignment.rb +10 -0
  54. data/app/models/shipit/release_status.rb +1 -1
  55. data/app/models/shipit/repository.rb +63 -3
  56. data/app/models/shipit/review_stack.rb +130 -0
  57. data/app/models/shipit/review_stack_provisioning_queue.rb +39 -0
  58. data/app/models/shipit/rollback.rb +5 -0
  59. data/app/models/shipit/stack.rb +78 -30
  60. data/app/models/shipit/status/group.rb +1 -1
  61. data/app/models/shipit/task.rb +62 -9
  62. data/app/models/shipit/task_execution_strategy/base.rb +20 -0
  63. data/app/models/shipit/task_execution_strategy/default.rb +109 -0
  64. data/app/models/shipit/team.rb +4 -2
  65. data/app/models/shipit/user.rb +10 -1
  66. data/app/models/shipit/webhooks/handlers/pull_request/assigned_handler.rb +74 -0
  67. data/app/models/shipit/webhooks/handlers/pull_request/closed_handler.rb +68 -0
  68. data/app/models/shipit/webhooks/handlers/pull_request/edited_handler.rb +74 -0
  69. data/app/models/shipit/webhooks/handlers/pull_request/label_capturing_handler.rb +127 -0
  70. data/app/models/shipit/webhooks/handlers/pull_request/labeled_handler.rb +106 -0
  71. data/app/models/shipit/webhooks/handlers/pull_request/opened_handler.rb +83 -0
  72. data/app/models/shipit/webhooks/handlers/pull_request/reopened_handler.rb +88 -0
  73. data/app/models/shipit/webhooks/handlers/pull_request/review_stack_adapter.rb +103 -0
  74. data/app/models/shipit/webhooks/handlers/pull_request/unlabeled_handler.rb +107 -0
  75. data/app/models/shipit/webhooks/handlers/push_handler.rb +4 -1
  76. data/app/models/shipit/webhooks.rb +10 -0
  77. data/app/serializers/shipit/deploy_serializer.rb +6 -0
  78. data/app/serializers/shipit/merge_request_serializer.rb +21 -0
  79. data/app/serializers/shipit/pull_request_serializer.rb +5 -8
  80. data/app/serializers/shipit/review_stack_serializer.rb +7 -0
  81. data/app/serializers/shipit/stack_serializer.rb +7 -6
  82. data/app/serializers/shipit/tail_task_serializer.rb +10 -2
  83. data/app/serializers/shipit/task_serializer.rb +1 -1
  84. data/app/validators/subset_validator.rb +1 -1
  85. data/app/views/layouts/merge_status.html.erb +1 -1
  86. data/app/views/shipit/merge_requests/_merge_request.html.erb +29 -0
  87. data/app/views/shipit/{pull_requests → merge_requests}/index.html.erb +2 -2
  88. data/app/views/shipit/merge_requests/merge_requests/_pull_request.html.erb +29 -0
  89. data/app/views/shipit/merge_requests/merge_requests/index.html.erb +20 -0
  90. data/app/views/shipit/merge_status/_merge_queue_button.html.erb +3 -3
  91. data/app/views/shipit/merge_status/backlogged.html.erb +1 -1
  92. data/app/views/shipit/merge_status/failure.html.erb +1 -1
  93. data/app/views/shipit/merge_status/locked.html.erb +1 -1
  94. data/app/views/shipit/merge_status/success.html.erb +2 -2
  95. data/app/views/shipit/repositories/_header.html.erb +19 -0
  96. data/app/views/shipit/repositories/index.html.erb +31 -0
  97. data/app/views/shipit/repositories/new.html.erb +23 -0
  98. data/app/views/shipit/repositories/settings.html.erb +53 -0
  99. data/app/views/shipit/repositories/show.html.erb +30 -0
  100. data/app/views/shipit/stacks/_banners.html.erb +15 -1
  101. data/app/views/shipit/stacks/_header.html.erb +5 -2
  102. data/app/views/shipit/stacks/_stack.html.erb +8 -0
  103. data/app/views/shipit/stacks/index.html.erb +2 -1
  104. data/app/views/shipit/stacks/new.html.erb +1 -1
  105. data/app/views/shipit/stacks/settings.html.erb +5 -5
  106. data/app/views/shipit/stacks/show.html.erb +1 -1
  107. data/app/views/shipit/tasks/_task_output.html.erb +1 -1
  108. data/config/routes.rb +15 -5
  109. data/config/secrets.development.example.yml +24 -0
  110. data/config/secrets.development.shopify.yml +20 -9
  111. data/db/migrate/20200706145406_add_review_stacks.rb +12 -0
  112. data/db/migrate/20200804144639_rename_pull_request_to_merge_request.rb +7 -0
  113. data/db/migrate/20200804161512_rename_commits_pull_request_id_to_merge_request_id.rb +5 -0
  114. data/db/migrate/20200813134712_recreate_shipit_pull_requests.rb +22 -0
  115. data/db/migrate/20200813194056_create_pull_request_assignments.rb +8 -0
  116. data/db/migrate/20201001125502_add_provision_pr_stacks_flag_to_repositories.rb +7 -0
  117. data/db/migrate/20201008145809_add_retry_attempt_to_tasks.rb +5 -0
  118. data/db/migrate/20201008152744_add_max_retries_to_tasks.rb +5 -0
  119. data/db/migrate/20210325194053_remove_stacks_branch_default.rb +5 -0
  120. data/db/migrate/20210504200438_add_github_updated_at_to_check_runs.rb +5 -0
  121. data/db/migrate/20210823075617_change_check_runs_github_updated_at_default.rb +5 -0
  122. data/lib/shipit/command.rb +7 -6
  123. data/lib/shipit/commands.rb +18 -5
  124. data/lib/shipit/engine.rb +2 -0
  125. data/lib/shipit/flock.rb +8 -1
  126. data/lib/shipit/github_app.rb +8 -6
  127. data/lib/shipit/octokit_iterator.rb +3 -3
  128. data/lib/shipit/review_stack_commands.rb +8 -0
  129. data/lib/shipit/simple_message_verifier.rb +2 -2
  130. data/lib/shipit/stack_commands.rb +36 -7
  131. data/lib/shipit/task_commands.rb +8 -1
  132. data/lib/shipit/version.rb +1 -1
  133. data/lib/shipit.rb +50 -16
  134. data/lib/snippets/publish-lerna-independent-packages +35 -34
  135. data/lib/snippets/publish-lerna-independent-packages-legacy +39 -0
  136. data/lib/tasks/cron.rake +11 -2
  137. data/test/controllers/api/ccmenu_controller_test.rb +1 -1
  138. data/test/controllers/api/deploys_controller_test.rb +17 -0
  139. data/test/controllers/api/{pull_requests_controller_test.rb → merge_requests_controller_test.rb} +12 -12
  140. data/test/controllers/api/outputs_controller_test.rb +1 -0
  141. data/test/controllers/api/rollback_controller_test.rb +1 -1
  142. data/test/controllers/api/stacks_controller_test.rb +42 -8
  143. data/test/controllers/{pull_requests_controller_test.rb → merge_requests_controller_test.rb} +6 -6
  144. data/test/controllers/repositories_controller_test.rb +71 -0
  145. data/test/controllers/stacks_controller_test.rb +9 -1
  146. data/test/controllers/tasks_controller_test.rb +14 -2
  147. data/test/controllers/webhooks_controller_test.rb +27 -12
  148. data/test/dummy/app/assets/config/manifest.js +3 -0
  149. data/test/dummy/config/application.rb +7 -2
  150. data/test/dummy/config/database.yml +9 -0
  151. data/test/dummy/config/environments/development.rb +1 -4
  152. data/test/dummy/config/environments/test.rb +0 -5
  153. data/test/dummy/config/secrets_double_github_app.yml +79 -0
  154. data/test/dummy/db/schema.rb +56 -17
  155. data/test/dummy/db/seeds.rb +2 -1
  156. data/test/fixtures/payloads/check_suite_master.json +4 -32
  157. data/test/fixtures/payloads/invalid_pull_request.json +117 -0
  158. data/test/fixtures/payloads/provision_disabled_pull_request.json +454 -0
  159. data/test/fixtures/payloads/pull_request_assigned.json +480 -0
  160. data/test/fixtures/payloads/pull_request_closed.json +454 -0
  161. data/test/fixtures/payloads/pull_request_labeled.json +461 -0
  162. data/test/fixtures/payloads/pull_request_opened.json +454 -0
  163. data/test/fixtures/payloads/pull_request_reopened.json +454 -0
  164. data/test/fixtures/payloads/pull_request_unlabeled.json +454 -0
  165. data/test/fixtures/payloads/pull_request_with_no_repo.json +454 -0
  166. data/test/fixtures/payloads/push_master.json +1 -1
  167. data/test/fixtures/payloads/push_not_master.json +1 -1
  168. data/test/fixtures/shipit/commits.yml +17 -4
  169. data/test/fixtures/shipit/hooks.yml +1 -0
  170. data/test/fixtures/shipit/merge_requests.yml +141 -0
  171. data/test/fixtures/shipit/pull_request_assignments.yml +3 -0
  172. data/test/fixtures/shipit/pull_requests.yml +10 -131
  173. data/test/fixtures/shipit/repositories.yml +1 -0
  174. data/test/fixtures/shipit/stacks.yml +145 -0
  175. data/test/fixtures/shipit/statuses.yml +9 -0
  176. data/test/fixtures/shipit/tasks.yml +4 -1
  177. data/test/fixtures/shipit/users.yml +7 -0
  178. data/test/helpers/json_helper.rb +5 -1
  179. data/test/helpers/payloads_helper.rb +4 -0
  180. data/test/jobs/chunk_rollup_job_test.rb +15 -1
  181. data/test/jobs/destroy_repository_job_test.rb +27 -0
  182. data/test/jobs/github_sync_job_test.rb +2 -1
  183. data/test/jobs/perform_task_job_test.rb +8 -8
  184. data/test/jobs/{merge_pull_requests_job_test.rb → process_merge_requests_job_test.rb} +18 -18
  185. data/test/lib/shipit/deploy_commands_test.rb +16 -0
  186. data/test/lib/shipit/task_commands_test.rb +17 -0
  187. data/test/models/commit_deployment_status_test.rb +3 -3
  188. data/test/models/commits_test.rb +24 -13
  189. data/test/models/deploy_spec_test.rb +64 -24
  190. data/test/models/deploys_test.rb +188 -14
  191. data/test/models/hook_test.rb +30 -1
  192. data/test/models/{pull_request_test.rb → merge_request_test.rb} +49 -34
  193. data/test/models/pull_request_assignment_test.rb +16 -0
  194. data/test/models/shipit/check_run_test.rb +124 -5
  195. data/test/models/shipit/provisioning_handler/base_test.rb +33 -0
  196. data/test/models/shipit/provisioning_handler/unregistered_provisioning_handler_test.rb +49 -0
  197. data/test/models/shipit/provisioning_handler_test.rb +64 -0
  198. data/test/models/shipit/pull_request_test.rb +52 -0
  199. data/test/models/shipit/repository_test.rb +5 -1
  200. data/test/models/shipit/review_stack_provision_status_test.rb +77 -0
  201. data/test/models/shipit/review_stack_provisioning_queue_test.rb +63 -0
  202. data/test/models/shipit/review_stack_test.rb +91 -0
  203. data/test/models/{stacks_test.rb → shipit/stacks_test.rb} +52 -8
  204. data/test/models/shipit/webhooks/handlers/pull_request/assigned_handler_test.rb +45 -0
  205. data/test/models/shipit/webhooks/handlers/pull_request/closed_handler_test.rb +192 -0
  206. data/test/models/shipit/webhooks/handlers/pull_request/edited_handler_test.rb +47 -0
  207. data/test/models/shipit/webhooks/handlers/pull_request/label_capturing_handler_test.rb +209 -0
  208. data/test/models/shipit/webhooks/handlers/pull_request/labeled_handler_test.rb +332 -0
  209. data/test/models/shipit/webhooks/handlers/pull_request/opened_handler_test.rb +238 -0
  210. data/test/models/shipit/webhooks/handlers/pull_request/reopened_handler_test.rb +282 -0
  211. data/test/models/shipit/webhooks/handlers/pull_request/review_stack_adapter_test.rb +107 -0
  212. data/test/models/shipit/webhooks/handlers/pull_request/unlabeled_handler_test.rb +324 -0
  213. data/test/models/shipit/{wehbooks → webhooks}/handlers_test.rb +0 -0
  214. data/test/models/tasks_test.rb +66 -3
  215. data/test/serializers/shipit/pull_request_serializer_test.rb +29 -0
  216. data/test/test_helper.rb +15 -0
  217. data/test/unit/anonymous_user_serializer_test.rb +1 -1
  218. data/test/unit/command_test.rb +8 -3
  219. data/test/unit/commit_serializer_test.rb +1 -1
  220. data/test/unit/deploy_commands_test.rb +73 -17
  221. data/test/unit/deploy_serializer_test.rb +1 -1
  222. data/test/unit/github_app_test.rb +2 -3
  223. data/test/unit/github_apps_test.rb +416 -0
  224. data/test/unit/github_url_helper_test.rb +5 -0
  225. data/test/unit/shipit_deployment_checks_test.rb +77 -0
  226. data/test/unit/shipit_task_execution_strategy_test.rb +47 -0
  227. data/test/unit/shipit_test.rb +14 -0
  228. data/test/unit/user_serializer_test.rb +1 -1
  229. metadata +306 -188
  230. data/app/controllers/shipit/pull_requests_controller.rb +0 -31
  231. data/app/jobs/shipit/merge_pull_requests_job.rb +0 -32
  232. data/app/jobs/shipit/refresh_pull_request_job.rb +0 -11
  233. data/app/views/shipit/pull_requests/_pull_request.html.erb +0 -29
  234. data/test/fixtures/shipit/output_chunks.yml +0 -47
  235. data/test/models/output_chunk_test.rb +0 -21
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+ # rubocop:disable Lint/MissingSuper
2
3
  module Shipit
3
4
  class TaskCommands < Commands
4
5
  delegate :fetch, :fetched?, to: :stack_commands
@@ -46,7 +47,7 @@ module Shipit
46
47
  end
47
48
 
48
49
  def checkout(commit)
49
- git('checkout', commit.sha, chdir: @task.working_directory)
50
+ git('-c', 'advice.detachedHead=false', 'checkout', commit.sha, chdir: @task.working_directory)
50
51
  end
51
52
 
52
53
  def clone
@@ -87,5 +88,11 @@ module Shipit
87
88
  @task.working_directory
88
89
  end
89
90
  end
91
+
92
+ private
93
+
94
+ def github
95
+ Shipit.github(organization: @stack.repository.owner)
96
+ end
90
97
  end
91
98
  end
@@ -1,4 +1,4 @@
1
1
  # frozen_string_literal: true
2
2
  module Shipit
3
- VERSION = '0.32.0'
3
+ VERSION = '0.35.1'
4
4
  end
data/lib/shipit.rb CHANGED
@@ -24,7 +24,6 @@ require 'safe_yaml/load'
24
24
  require 'securecompare'
25
25
 
26
26
  require 'redis-objects'
27
- require 'redis-namespace'
28
27
 
29
28
  require 'octokit'
30
29
  require 'faraday-http-cache'
@@ -43,6 +42,7 @@ require 'shipit/simple_message_verifier'
43
42
  require 'shipit/command'
44
43
  require 'shipit/commands'
45
44
  require 'shipit/stack_commands'
45
+ require 'shipit/review_stack_commands'
46
46
  require 'shipit/task_commands'
47
47
  require 'shipit/deploy_commands'
48
48
  require 'shipit/rollback_commands'
@@ -59,10 +59,22 @@ SafeYAML::OPTIONS[:deserialize_symbols] = false
59
59
  module Shipit
60
60
  extend self
61
61
 
62
+ GithubOrganizationUnknown = Class.new(StandardError)
63
+ TOP_LEVEL_GH_KEYS = [:app_id, :installation_id, :webhook_secret, :private_key, :oauth, :domain]
64
+
62
65
  delegate :table_name_prefix, to: :secrets
63
66
 
64
- attr_accessor :disable_api_authentication, :timeout_exit_codes
65
- attr_writer :internal_hook_receivers, :task_logger, :preferred_org_emails
67
+ attr_accessor :disable_api_authentication, :timeout_exit_codes, :deployment_checks
68
+ attr_writer(
69
+ :internal_hook_receivers,
70
+ :preferred_org_emails,
71
+ :task_execution_strategy,
72
+ :task_logger,
73
+ )
74
+
75
+ def task_execution_strategy
76
+ @task_execution_strategy ||= Shipit::TaskExecutionStrategy::Default
77
+ end
66
78
 
67
79
  self.timeout_exit_codes = [].freeze
68
80
 
@@ -82,7 +94,7 @@ module Shipit
82
94
  secrets.redis_url.present? ? URI(secrets.redis_url) : nil
83
95
  end
84
96
 
85
- def redis(namespace = nil)
97
+ def redis
86
98
  @redis ||= Redis.new(
87
99
  url: redis_url.to_s.presence,
88
100
  logger: Rails.logger,
@@ -90,17 +102,41 @@ module Shipit
90
102
  reconnect_delay: 0.5,
91
103
  reconnect_delay_max: 1,
92
104
  )
93
- return @redis unless namespace
94
- Redis::Namespace.new(namespace, redis: @redis)
95
105
  end
96
106
 
97
- def github
98
- @github ||= GitHubApp.new(secrets.github)
107
+ def github(organization: github_default_organization)
108
+ # Backward compatibility
109
+ # nil signifies the single github app config schema is being used
110
+ if github_default_organization.nil?
111
+ config = secrets.github
112
+ else
113
+ config = github_app_config(organization)
114
+ raise GithubOrganizationUnknown, organization if config.nil?
115
+ end
116
+ @github ||= {}
117
+ @github[organization] ||= GitHubApp.new(organization, config)
118
+ end
119
+
120
+ def github_default_organization
121
+ return nil unless secrets&.github
122
+ org = secrets.github.keys.first
123
+ TOP_LEVEL_GH_KEYS.include?(org) ? nil : org
124
+ end
125
+
126
+ def github_organizations
127
+ return [nil] unless github_default_organization
128
+ secrets.github.keys
129
+ end
130
+
131
+ def github_app_config(organization)
132
+ github_config = secrets.github.deep_transform_keys(&:downcase)
133
+ github_organization = organization.downcase.to_sym
134
+ github_config[github_organization]
99
135
  end
100
136
 
101
137
  def legacy_github_api
102
138
  if secrets&.github_api.present?
103
- @legacy_github_api ||= github.new_client(access_token: secrets.github_api['access_token'])
139
+ @legacy_github_api ||= github.new_client(access_token: secrets.github_api[:access_token])
104
140
  end
105
141
  end
106
142
 
@@ -165,13 +201,11 @@ module Shipit
165
201
  end
166
202
 
167
203
  def revision
168
- @revision ||= begin
169
- if revision_file.exist?
170
- revision_file.read
171
- else
172
- %x(git rev-parse HEAD)
173
- end.strip
174
- end
204
+ @revision ||= if revision_file.exist?
205
+ revision_file.read
206
+ else
207
+ %x(git rev-parse HEAD)
208
+ end.strip
175
209
  end
176
210
 
177
211
  def default_inactivity_timeout
@@ -1,39 +1,40 @@
1
1
  #!/usr/bin/env node
2
- const {resolve} = require('path');
3
- const {execSync} = require('child_process')
4
- const Repository = require(resolve('.', 'node_modules', 'lerna', 'lib', 'Repository'));
5
- const PackageUtilities = require(resolve('.', 'node_modules', 'lerna', 'lib', 'PackageUtilities'));
6
-
7
- function npmTag(version) {
8
- const isNext = ['-beta', '-alpha', '-rc', '-next'].some(distributionType =>
9
- version.includes(distributionType),
10
- );
11
- return isNext ? 'next' : 'latest';
12
- }
2
+ const { execSync } = require("child_process");
13
3
 
14
- const taggedPackages = execSync('git tag --points-at HEAD')
4
+ const taggedPackages = execSync("git tag --points-at HEAD")
15
5
  .toString()
16
6
  .trim()
17
- .split('\n')
18
- .map(tag => {
19
- if (tag.startsWith('@')) {
20
- return `@${tag.split('@')[1]}`;
21
- }
22
- return tag.split('@')[0];
23
- });
24
-
25
- const repository = new Repository('.');
26
- const unsortedPackages = PackageUtilities.getPackages({rootPath: '.', packageConfigs: repository.packageConfigs});
27
- const packages = PackageUtilities.topologicallyBatchPackages(unsortedPackages, true)
28
- .reduce((acc, packageGroup) => [...acc, ...packageGroup], [])
29
- .filter(({name}) => taggedPackages.includes(name));
30
-
31
- packages.forEach(({name, version}) => {
32
- const command = `node_modules/.bin/lerna publish --yes --npm-client=npm --skip-npm=false --skip-git --force-publish=${name} --repo-version=${version} --scope=${name} --npm-tag=${npmTag(
33
- version,
34
- )}`;
35
-
36
- // eslint-disable-next-line no-console
37
- console.log(command);
38
- require('child_process').execSync(command);
7
+ .split("\n");
8
+
9
+ // anything that matches `-` after MAJOR.MINOR.PATCH
10
+ const validPattern = new RegExp(/\d+\.\d+\.\d+-(\w+)/);
11
+
12
+ // Ensure that all releases use the same prerelease suffix.
13
+ // We want to only release all final versions, or all betas etc
14
+ const allPrereleaseSuffixes = taggedPackages.map((version) => {
15
+ const result = validPattern.exec(version);
16
+ return result ? result[1] : '';
39
17
  });
18
+ if ((new Set(allPrereleaseSuffixes)).size > 1) {
19
+ throw Error("All packages must be of the same type of release. Versions cannot be mixed.");
20
+ }
21
+
22
+ // set this using machine.environment.SHIPIT_LERNA_PUBLISH_MECHANISM in your shipit.yml
23
+ const publishMechanism = process.env.SHIPIT_LERNA_PUBLISH_MECHANISM || 'from-git';
24
+
25
+ if (!['from-package', 'from-git'].includes(publishMechanism)) {
26
+ throw Error("SHIPIT_LERNA_PUBLISH_MECHANISM must be 'from-package' or 'from-git'.");
27
+ }
28
+
29
+ const command = [
30
+ "node_modules/.bin/lerna publish",
31
+ publishMechanism,
32
+ "--yes",
33
+ "--dist-tag latest",
34
+ "--pre-dist-tag next",
35
+ ];
36
+
37
+ const commandString = command.join(" ");
38
+
39
+ console.log(`${commandString}`);
40
+ execSync(commandString);
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env node
2
+ const {resolve} = require('path');
3
+ const {execSync} = require('child_process')
4
+ const Repository = require(resolve('.', 'node_modules', 'lerna', 'lib', 'Repository'));
5
+ const PackageUtilities = require(resolve('.', 'node_modules', 'lerna', 'lib', 'PackageUtilities'));
6
+
7
+ function npmTag(version) {
8
+ const isNext = ['-beta', '-alpha', '-rc', '-next'].some(distributionType =>
9
+ version.includes(distributionType),
10
+ );
11
+ return isNext ? 'next' : 'latest';
12
+ }
13
+
14
+ const taggedPackages = execSync('git tag --points-at HEAD')
15
+ .toString()
16
+ .trim()
17
+ .split('\n')
18
+ .map(tag => {
19
+ if (tag.startsWith('@')) {
20
+ return `@${tag.split('@')[1]}`;
21
+ }
22
+ return tag.split('@')[0];
23
+ });
24
+
25
+ const repository = new Repository('.');
26
+ const unsortedPackages = PackageUtilities.getPackages({rootPath: '.', packageConfigs: repository.packageConfigs});
27
+ const packages = PackageUtilities.topologicallyBatchPackages(unsortedPackages, true)
28
+ .reduce((acc, packageGroup) => [...acc, ...packageGroup], [])
29
+ .filter(({name}) => taggedPackages.includes(name));
30
+
31
+ packages.forEach(({name, version}) => {
32
+ const command = `node_modules/.bin/lerna publish --yes --npm-client=npm --skip-npm=false --skip-git --force-publish=${name} --repo-version=${version} --scope=${name} --npm-tag=${npmTag(
33
+ version,
34
+ )}`;
35
+
36
+ // eslint-disable-next-line no-console
37
+ console.log(command);
38
+ require('child_process').execSync(command);
39
+ });
data/lib/tasks/cron.rake CHANGED
@@ -5,11 +5,12 @@ namespace :cron do
5
5
  Shipit::Stack.refresh_deployed_revisions
6
6
  Shipit::Stack.schedule_continuous_delivery
7
7
  Shipit::GithubStatus.refresh_status
8
- Shipit::PullRequest.schedule_merges
8
+ Shipit::MergeRequest.schedule_merges
9
9
  Shipit::ReapDeadTasksJob.perform_later
10
+ Shipit::ReviewStackProvisioningQueue.work
10
11
  end
11
12
 
12
- task hourly: %i(rollup refresh_users)
13
+ task hourly: %i(rollup refresh_users clear_stale_caches delete_old_deployment_directories)
13
14
 
14
15
  desc "Rolls-up output chunks for completed deploys older than an hour"
15
16
  task rollup: :environment do
@@ -19,4 +20,12 @@ namespace :cron do
19
20
  task refresh_users: :environment do
20
21
  Shipit::User.refresh_shard(Time.now.hour % 24, 24)
21
22
  end
23
+
24
+ task clear_stale_caches: :environment do
25
+ Shipit::ReviewStack.clear_stale_caches
26
+ end
27
+
28
+ task delete_old_deployment_directories: :environment do
29
+ Shipit::ReviewStack.delete_old_deployment_directories
30
+ end
22
31
  end
@@ -44,7 +44,7 @@ module Shipit
44
44
  end
45
45
 
46
46
  test "stacks with no deploys render correctly" do
47
- stack = Stack.create!(repository: Repository.new(owner: "foo", name: "bar"))
47
+ stack = Stack.create!(repository: Repository.new(owner: "foo", name: "bar"), branch: 'main')
48
48
  get :show, params: { stack_id: stack.to_param }
49
49
  assert_payload 'lastBuildStatus', 'Success'
50
50
  end
@@ -83,6 +83,23 @@ module Shipit
83
83
  assert_response :conflict
84
84
  end
85
85
 
86
+ test "#create refuses to deploy unsuccessful commits if the require_ci flag is passed" do
87
+ Commit.any_instance.expects(:deployable?).returns(false)
88
+
89
+ assert_no_difference -> { @stack.deploys.count } do
90
+ post :create, params: { stack_id: @stack.to_param, sha: @commit.sha, require_ci: true }
91
+ end
92
+ assert_response :unprocessable_entity
93
+ assert_json 'errors.require_ci', ["Commit is not deployable"]
94
+ end
95
+
96
+ test "#create deploys failing commits if the require_ci flag is not passed" do
97
+ Commit.any_instance.expects(:deployable?).returns(false)
98
+
99
+ post :create, params: { stack_id: @stack.to_param, sha: @commit.sha }
100
+ assert_response :accepted
101
+ end
102
+
86
103
  test "#create refuses to deploy locked stacks" do
87
104
  @stack.update!(lock_reason: 'Something broken')
88
105
 
@@ -3,52 +3,52 @@ require 'test_helper'
3
3
 
4
4
  module Shipit
5
5
  module Api
6
- class PullRequestsControllerTest < ActionController::TestCase
6
+ class MergeRequestsControllerTest < ActionController::TestCase
7
7
  setup do
8
8
  @stack = shipit_stacks(:shipit)
9
- @pull_request = shipit_pull_requests(:shipit_pending)
9
+ @merge_request = shipit_merge_requests(:shipit_pending)
10
10
  authenticate!
11
11
  end
12
12
 
13
13
  test "#index returns a list of pull requests" do
14
- pull_request = @stack.pull_requests.last
14
+ merge_request = @stack.merge_requests.last
15
15
 
16
16
  get :index, params: { stack_id: @stack.to_param }
17
17
  assert_response :ok
18
- assert_json '0.id', pull_request.id
18
+ assert_json '0.id', merge_request.id
19
19
  end
20
20
 
21
21
  test "#show returns a single pull requests" do
22
- get :show, params: { stack_id: @stack.to_param, id: @pull_request.number.to_s }
22
+ get :show, params: { stack_id: @stack.to_param, id: @merge_request.number.to_s }
23
23
  assert_response :ok
24
- assert_json 'id', @pull_request.id
24
+ assert_json 'id', @merge_request.id
25
25
  end
26
26
 
27
27
  test "#update responds with Accepted if the pull request was queued" do
28
- assert_enqueued_with(job: RefreshPullRequestJob) do
28
+ assert_enqueued_with(job: RefreshMergeRequestJob) do
29
29
  put :update, params: { stack_id: @stack.to_param, id: '64' }
30
30
  end
31
31
  assert_response :accepted
32
32
  end
33
33
 
34
34
  test "#update responds with Accepted if the pull request was already queued" do
35
- assert_enqueued_with(job: RefreshPullRequestJob) do
35
+ assert_enqueued_with(job: RefreshMergeRequestJob) do
36
36
  put :update, params: { stack_id: @stack.to_param, id: '65' }
37
37
  end
38
38
  assert_response :accepted
39
39
  end
40
40
 
41
41
  test "#update responds with method not allowed if the pull request was already merged" do
42
- @pull_request.complete!
43
- put :update, params: { stack_id: @stack.to_param, id: @pull_request.number.to_s }
42
+ @merge_request.complete!
43
+ put :update, params: { stack_id: @stack.to_param, id: @merge_request.number.to_s }
44
44
  assert_response :method_not_allowed
45
45
  assert_json 'message', 'This pull request was already merged.'
46
46
  end
47
47
 
48
48
  test "#destroy cancels the merge if the pull request was waiting" do
49
- delete :destroy, params: { stack_id: @stack.to_param, id: @pull_request.number.to_s }
49
+ delete :destroy, params: { stack_id: @stack.to_param, id: @merge_request.number.to_s }
50
50
  assert_response :no_content
51
- assert_predicate @pull_request.reload, :canceled?
51
+ assert_predicate @merge_request.reload, :canceled?
52
52
  end
53
53
 
54
54
  test "#destroy silently fail if the pull request was unknown" do
@@ -11,6 +11,7 @@ module Shipit
11
11
 
12
12
  test "#show returns the task output as plain text" do
13
13
  task = @stack.tasks.last
14
+ task.write("dummy output")
14
15
 
15
16
  get :show, params: { stack_id: @stack.to_param, task_id: task.id }
16
17
  assert_response :ok
@@ -106,7 +106,7 @@ module Shipit
106
106
  last_deploy.reload
107
107
  assert_response :accepted
108
108
  refute_predicate last_deploy, :active?
109
- assert_json 'rollback_once_aborted_to.until_commit_id', @commit.id
109
+ assert_json 'rollback_once_aborted_to.revision.sha', @commit.sha
110
110
  end
111
111
  end
112
112
  end
@@ -23,7 +23,7 @@ module Shipit
23
23
 
24
24
  test "#create fails with invalid stack" do
25
25
  assert_no_difference "Stack.count" do
26
- post :create, params: { repo_owner: 'some', repo_name: 'owner/path' }
26
+ post :create, params: { repo_owner: 'some', repo_name: 'owner/path', branch: 'main' }
27
27
  end
28
28
  assert_response :unprocessable_entity
29
29
  assert_json 'errors', 'repository' => ['is invalid']
@@ -48,12 +48,12 @@ module Shipit
48
48
 
49
49
  assert_no_difference -> { Stack.count } do
50
50
  post :create,
51
- params: {
52
- repo_name: existing_stack.repo_name,
53
- repo_owner: existing_stack.repo_owner,
54
- environment: existing_stack.environment,
55
- branch: existing_stack.branch,
56
- }
51
+ params: {
52
+ repo_name: existing_stack.repo_name,
53
+ repo_owner: existing_stack.repo_owner,
54
+ environment: existing_stack.environment,
55
+ branch: existing_stack.branch,
56
+ }
57
57
  end
58
58
 
59
59
  assert_response :unprocessable_entity
@@ -82,9 +82,22 @@ module Shipit
82
82
  assert_equal true, @stack.continuous_deployment
83
83
  end
84
84
 
85
+ test "#update allows changing the branch name" do
86
+ assert_equal 'master', @stack.branch
87
+
88
+ patch :update, params: {
89
+ id: @stack.to_param,
90
+ branch: 'test',
91
+ }
92
+
93
+ assert_response :ok
94
+ @stack.reload
95
+
96
+ assert_equal 'test', @stack.branch
97
+ end
98
+
85
99
  test "#index returns a list of stacks" do
86
100
  stack = Stack.last
87
-
88
101
  get :index
89
102
  assert_response :ok
90
103
  assert_json '0.id', stack.id
@@ -93,6 +106,27 @@ module Shipit
93
106
  end
94
107
  end
95
108
 
109
+ test "#index returns a list of stacks filtered by repo if name and owner given" do
110
+ repo = shipit_repositories(:shipit)
111
+ get :index, params: { repo_owner: repo.owner, repo_name: repo.name }
112
+ assert_response :ok
113
+ assert_json do |stacks|
114
+ assert_equal stacks.size, repo.stacks.size
115
+ end
116
+ end
117
+
118
+ test "#index returns a list of stacks filtered by repo and api client" do
119
+ authenticate!(:here_come_the_walrus)
120
+
121
+ repo = shipit_repositories(:soc)
122
+
123
+ get :index, params: { repo_owner: repo.owner, repo_name: repo.name }
124
+ assert_response :ok
125
+ assert_json do |stacks|
126
+ assert_equal 0, stacks.size
127
+ end
128
+ end
129
+
96
130
  test "#index is paginable" do
97
131
  get :index, params: { page_size: 1 }
98
132
  assert_json do |list|