shipit-engine 0.38.0 → 0.40.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.
Files changed (323) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +48 -4
  3. data/Rakefile +2 -1
  4. data/app/assets/javascripts/shipit/continuous_delivery_schedule.js.coffee +15 -0
  5. data/app/controllers/concerns/shipit/active_model_serializers_patch.rb +1 -0
  6. data/app/controllers/concerns/shipit/api/cacheable.rb +1 -0
  7. data/app/controllers/concerns/shipit/api/paginable.rb +3 -2
  8. data/app/controllers/concerns/shipit/api/rendering.rb +1 -0
  9. data/app/controllers/concerns/shipit/authentication.rb +1 -0
  10. data/app/controllers/concerns/shipit/pagination.rb +3 -2
  11. data/app/controllers/shipit/api/base_controller.rb +12 -10
  12. data/app/controllers/shipit/api/ccmenu_controller.rb +2 -1
  13. data/app/controllers/shipit/api/commits_controller.rb +2 -3
  14. data/app/controllers/shipit/api/deploys_controller.rb +6 -1
  15. data/app/controllers/shipit/api/hooks_controller.rb +4 -3
  16. data/app/controllers/shipit/api/locks_controller.rb +1 -0
  17. data/app/controllers/shipit/api/merge_requests_controller.rb +6 -5
  18. data/app/controllers/shipit/api/outputs_controller.rb +1 -0
  19. data/app/controllers/shipit/api/release_statuses_controller.rb +2 -1
  20. data/app/controllers/shipit/api/rollbacks_controller.rb +1 -0
  21. data/app/controllers/shipit/api/stacks_controller.rb +15 -14
  22. data/app/controllers/shipit/api/tasks_controller.rb +6 -5
  23. data/app/controllers/shipit/api_clients_controller.rb +6 -7
  24. data/app/controllers/shipit/ccmenu_url_controller.rb +3 -2
  25. data/app/controllers/shipit/commit_checks_controller.rb +2 -1
  26. data/app/controllers/shipit/commits_controller.rb +1 -0
  27. data/app/controllers/shipit/continuous_delivery_schedules_controller.rb +42 -0
  28. data/app/controllers/shipit/deploys_controller.rb +6 -5
  29. data/app/controllers/shipit/github_authentication_controller.rb +6 -0
  30. data/app/controllers/shipit/merge_requests_controller.rb +1 -0
  31. data/app/controllers/shipit/merge_status_controller.rb +30 -26
  32. data/app/controllers/shipit/release_statuses_controller.rb +1 -0
  33. data/app/controllers/shipit/repositories_controller.rb +4 -7
  34. data/app/controllers/shipit/rollbacks_controller.rb +2 -1
  35. data/app/controllers/shipit/shipit_controller.rb +1 -0
  36. data/app/controllers/shipit/stacks_controller.rb +27 -31
  37. data/app/controllers/shipit/status_controller.rb +1 -0
  38. data/app/controllers/shipit/tasks_controller.rb +3 -1
  39. data/app/controllers/shipit/webhooks_controller.rb +2 -1
  40. data/app/helpers/shipit/api_clients_helper.rb +1 -0
  41. data/app/helpers/shipit/chunks_helper.rb +3 -1
  42. data/app/helpers/shipit/deploys_helper.rb +7 -3
  43. data/app/helpers/shipit/github_url_helper.rb +5 -4
  44. data/app/helpers/shipit/merge_status_helper.rb +1 -0
  45. data/app/helpers/shipit/shipit_helper.rb +11 -10
  46. data/app/helpers/shipit/stacks_helper.rb +10 -11
  47. data/app/helpers/shipit/tasks_helper.rb +2 -1
  48. data/app/jobs/shipit/background_job/unique.rb +3 -2
  49. data/app/jobs/shipit/background_job.rb +9 -1
  50. data/app/jobs/shipit/cache_deploy_spec_job.rb +2 -1
  51. data/app/jobs/shipit/chunk_rollup_job.rb +1 -0
  52. data/app/jobs/shipit/clear_git_cache_job.rb +1 -0
  53. data/app/jobs/shipit/continuous_delivery_job.rb +5 -0
  54. data/app/jobs/shipit/create_on_github_job.rb +1 -0
  55. data/app/jobs/shipit/create_release_statuses_job.rb +2 -0
  56. data/app/jobs/shipit/deferred_touch_job.rb +1 -0
  57. data/app/jobs/shipit/deliver_hook_job.rb +1 -0
  58. data/app/jobs/shipit/destroy_job.rb +1 -0
  59. data/app/jobs/shipit/destroy_repository_job.rb +1 -0
  60. data/app/jobs/shipit/destroy_stack_job.rb +36 -15
  61. data/app/jobs/shipit/emit_event_job.rb +1 -0
  62. data/app/jobs/shipit/fetch_commit_stats_job.rb +1 -0
  63. data/app/jobs/shipit/fetch_deployed_revision_job.rb +1 -0
  64. data/app/jobs/shipit/github_sync_job.rb +4 -2
  65. data/app/jobs/shipit/mark_deploy_healthy_job.rb +1 -0
  66. data/app/jobs/shipit/perform_commit_checks_job.rb +1 -0
  67. data/app/jobs/shipit/perform_task_job.rb +1 -0
  68. data/app/jobs/shipit/process_merge_requests_job.rb +2 -0
  69. data/app/jobs/shipit/purge_old_deliveries_job.rb +1 -0
  70. data/app/jobs/shipit/reap_dead_tasks_job.rb +1 -0
  71. data/app/jobs/shipit/refresh_check_runs_job.rb +1 -0
  72. data/app/jobs/shipit/refresh_github_user_job.rb +1 -0
  73. data/app/jobs/shipit/refresh_merge_request_job.rb +1 -0
  74. data/app/jobs/shipit/refresh_statuses_job.rb +1 -0
  75. data/app/jobs/shipit/setup_github_hook_job.rb +1 -0
  76. data/app/jobs/shipit/update_estimated_deploy_duration_job.rb +1 -0
  77. data/app/jobs/shipit/update_github_last_deployed_ref_job.rb +6 -7
  78. data/app/models/concerns/shipit/deferred_touch.rb +5 -2
  79. data/app/models/shipit/anonymous_user.rb +4 -5
  80. data/app/models/shipit/api_client.rb +5 -3
  81. data/app/models/shipit/application_record.rb +1 -0
  82. data/app/models/shipit/check_run.rb +7 -6
  83. data/app/models/shipit/command_line_user.rb +4 -5
  84. data/app/models/shipit/commit.rb +46 -32
  85. data/app/models/shipit/commit_checks.rb +4 -2
  86. data/app/models/shipit/commit_deployment.rb +7 -5
  87. data/app/models/shipit/commit_deployment_status.rb +5 -3
  88. data/app/models/shipit/commit_message.rb +2 -0
  89. data/app/models/shipit/continuous_delivery_schedule.rb +84 -0
  90. data/app/models/shipit/delivery.rb +5 -4
  91. data/app/models/shipit/deploy.rb +46 -26
  92. data/app/models/shipit/deploy_spec/bundler_discovery.rb +3 -1
  93. data/app/models/shipit/deploy_spec/capistrano_discovery.rb +1 -0
  94. data/app/models/shipit/deploy_spec/file_system.rb +48 -17
  95. data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +4 -3
  96. data/app/models/shipit/deploy_spec/lerna_discovery.rb +32 -31
  97. data/app/models/shipit/deploy_spec/npm_discovery.rb +18 -13
  98. data/app/models/shipit/deploy_spec/pypi_discovery.rb +5 -4
  99. data/app/models/shipit/deploy_spec/rubygems_discovery.rb +1 -0
  100. data/app/models/shipit/deploy_spec.rb +25 -30
  101. data/app/models/shipit/deploy_stats.rb +6 -1
  102. data/app/models/shipit/duration.rb +5 -3
  103. data/app/models/shipit/ephemeral_commit_checks.rb +8 -7
  104. data/app/models/shipit/github_hook.rb +1 -0
  105. data/app/models/shipit/github_status.rb +1 -0
  106. data/app/models/shipit/hook.rb +9 -7
  107. data/app/models/shipit/membership.rb +1 -0
  108. data/app/models/shipit/merge_request.rb +26 -16
  109. data/app/models/shipit/output_chunk.rb +1 -0
  110. data/app/models/shipit/provisioning_handler.rb +1 -0
  111. data/app/models/shipit/pull_request.rb +2 -2
  112. data/app/models/shipit/record.rb +1 -0
  113. data/app/models/shipit/release_status.rb +4 -3
  114. data/app/models/shipit/repository.rb +12 -11
  115. data/app/models/shipit/review_stack.rb +3 -1
  116. data/app/models/shipit/review_stack_provisioning_queue.rb +2 -2
  117. data/app/models/shipit/rollback.rb +2 -0
  118. data/app/models/shipit/stack.rb +71 -60
  119. data/app/models/shipit/status/common.rb +1 -0
  120. data/app/models/shipit/status/group.rb +5 -3
  121. data/app/models/shipit/status/missing.rb +2 -1
  122. data/app/models/shipit/status/unknown.rb +1 -0
  123. data/app/models/shipit/status.rb +5 -4
  124. data/app/models/shipit/task.rb +40 -31
  125. data/app/models/shipit/task_definition.rb +10 -7
  126. data/app/models/shipit/task_execution_strategy/default.rb +13 -13
  127. data/app/models/shipit/team.rb +13 -12
  128. data/app/models/shipit/undeployed_commit.rb +8 -3
  129. data/app/models/shipit/unlimited_api_client.rb +2 -2
  130. data/app/models/shipit/user.rb +23 -16
  131. data/app/models/shipit/variable_definition.rb +2 -1
  132. data/app/models/shipit/webhooks/handlers/check_suite_handler.rb +1 -0
  133. data/app/models/shipit/webhooks/handlers/handler.rb +1 -0
  134. data/app/models/shipit/webhooks/handlers/membership_handler.rb +1 -0
  135. data/app/models/shipit/webhooks/handlers/pull_request/assigned_handler.rb +10 -10
  136. data/app/models/shipit/webhooks/handlers/pull_request/closed_handler.rb +1 -1
  137. data/app/models/shipit/webhooks/handlers/pull_request/edited_handler.rb +10 -10
  138. data/app/models/shipit/webhooks/handlers/pull_request/label_capturing_handler.rb +2 -2
  139. data/app/models/shipit/webhooks/handlers/pull_request/labeled_handler.rb +2 -2
  140. data/app/models/shipit/webhooks/handlers/pull_request/reopened_handler.rb +1 -1
  141. data/app/models/shipit/webhooks/handlers/pull_request/review_stack_adapter.rb +3 -3
  142. data/app/models/shipit/webhooks/handlers/pull_request/unlabeled_handler.rb +1 -1
  143. data/app/models/shipit/webhooks/handlers/push_handler.rb +2 -1
  144. data/app/models/shipit/webhooks/handlers/status_handler.rb +1 -0
  145. data/app/models/shipit/webhooks.rb +3 -2
  146. data/app/serializers/concerns/shipit/conditional_attributes.rb +1 -0
  147. data/app/serializers/shipit/anonymous_user_serializer.rb +1 -0
  148. data/app/serializers/shipit/command_line_user_serializer.rb +1 -0
  149. data/app/serializers/shipit/commit_serializer.rb +2 -1
  150. data/app/serializers/shipit/deploy_serializer.rb +1 -0
  151. data/app/serializers/shipit/hook_serializer.rb +1 -0
  152. data/app/serializers/shipit/merge_request_serializer.rb +2 -1
  153. data/app/serializers/shipit/rollback_serializer.rb +1 -0
  154. data/app/serializers/shipit/short_commit_serializer.rb +1 -0
  155. data/app/serializers/shipit/stack_serializer.rb +4 -3
  156. data/app/serializers/shipit/tail_task_serializer.rb +4 -1
  157. data/app/serializers/shipit/task_serializer.rb +1 -0
  158. data/app/serializers/shipit/user_serializer.rb +1 -0
  159. data/app/validators/ascii_only_validator.rb +4 -3
  160. data/app/validators/subset_validator.rb +1 -0
  161. data/app/views/shipit/_variables.html.erb +1 -1
  162. data/app/views/shipit/ccmenu/project.xml.builder +2 -1
  163. data/app/views/shipit/continuous_delivery_schedules/show.html.erb +59 -0
  164. data/app/views/shipit/merge_status/failure.html.erb +1 -1
  165. data/app/views/shipit/missing_settings.html.erb +1 -1
  166. data/app/views/shipit/stacks/_settings_form.erb +1 -0
  167. data/config/initializers/inflections.rb +1 -0
  168. data/config/locales/en.yml +1 -0
  169. data/config/routes.rb +21 -18
  170. data/config/secrets.development.example.yml +1 -1
  171. data/config/secrets.development.shopify.yml +1 -1
  172. data/db/migrate/20240821003007_add_continuous_delivery_schedules.rb +13 -0
  173. data/db/migrate/20250207203053_embiggen_github_ids.rb +8 -0
  174. data/lib/shipit/cast_value.rb +1 -0
  175. data/lib/shipit/command.rb +29 -9
  176. data/lib/shipit/commands.rb +4 -2
  177. data/lib/shipit/csv_serializer.rb +3 -0
  178. data/lib/shipit/deploy_commands.rb +2 -1
  179. data/lib/shipit/engine.rb +6 -5
  180. data/lib/shipit/environment_variables.rb +2 -0
  181. data/lib/shipit/first_parent_commits_iterator.rb +2 -3
  182. data/lib/shipit/flock.rb +11 -9
  183. data/lib/shipit/github_app.rb +14 -16
  184. data/lib/shipit/github_http_cache_middleware.rb +1 -0
  185. data/lib/shipit/null_serializer.rb +1 -0
  186. data/lib/shipit/octokit_check_runs.rb +2 -3
  187. data/lib/shipit/octokit_iterator.rb +2 -0
  188. data/lib/shipit/paginator.rb +1 -0
  189. data/lib/shipit/rollback_commands.rb +2 -1
  190. data/lib/shipit/same_site_cookie_middleware.rb +1 -0
  191. data/lib/shipit/simple_message_verifier.rb +1 -0
  192. data/lib/shipit/stack_commands.rb +35 -27
  193. data/lib/shipit/stat.rb +1 -0
  194. data/lib/shipit/task_commands.rb +7 -6
  195. data/lib/shipit/version.rb +2 -1
  196. data/lib/shipit.rb +30 -17
  197. data/lib/tasks/cron.rake +2 -1
  198. data/lib/tasks/dev.rake +3 -2
  199. data/lib/tasks/shipit.rake +3 -2
  200. data/lib/tasks/teams.rake +3 -2
  201. data/test/controllers/api/base_controller_test.rb +1 -0
  202. data/test/controllers/api/ccmenu_controller_test.rb +4 -3
  203. data/test/controllers/api/commits_controller_test.rb +1 -0
  204. data/test/controllers/api/deploys_controller_test.rb +26 -1
  205. data/test/controllers/api/hooks_controller_test.rb +6 -5
  206. data/test/controllers/api/locks_controller_test.rb +1 -0
  207. data/test/controllers/api/merge_requests_controller_test.rb +1 -0
  208. data/test/controllers/api/outputs_controller_test.rb +1 -0
  209. data/test/controllers/api/release_statuses_controller_test.rb +4 -3
  210. data/test/controllers/api/rollback_controller_test.rb +3 -2
  211. data/test/controllers/api/stacks_controller_test.rb +13 -12
  212. data/test/controllers/api/tasks_controller_test.rb +7 -6
  213. data/test/controllers/api_clients_controller_test.rb +10 -10
  214. data/test/controllers/ccmenu_controller_test.rb +1 -0
  215. data/test/controllers/commit_checks_controller_test.rb +1 -0
  216. data/test/controllers/commits_controller_test.rb +9 -8
  217. data/test/controllers/continuous_delivery_schedules_controller_test.rb +66 -0
  218. data/test/controllers/deploys_controller_test.rb +4 -2
  219. data/test/controllers/github_authentication_controller_test.rb +6 -4
  220. data/test/controllers/merge_requests_controller_test.rb +1 -0
  221. data/test/controllers/merge_status_controller_test.rb +5 -4
  222. data/test/controllers/release_statuses_controller_test.rb +1 -0
  223. data/test/controllers/repositories_controller_test.rb +6 -5
  224. data/test/controllers/rollbacks_controller_test.rb +3 -2
  225. data/test/controllers/stacks_controller_test.rb +8 -6
  226. data/test/controllers/status_controller_test.rb +1 -0
  227. data/test/controllers/tasks_controller_test.rb +13 -5
  228. data/test/controllers/webhooks_controller_test.rb +10 -9
  229. data/test/dummy/config/application.rb +2 -1
  230. data/test/dummy/config/initializers/0_load_development_secrets.rb +2 -2
  231. data/test/dummy/config/secrets.development.json +3 -0
  232. data/test/dummy/config/secrets.test.json +21 -0
  233. data/test/dummy/db/schema.rb +33 -6
  234. data/test/fixtures/shipit/commits.yml +7 -7
  235. data/test/fixtures/shipit/stacks.yml +4 -10
  236. data/test/fixtures/shipit/tasks.yml +3 -3
  237. data/test/helpers/api_helper.rb +2 -3
  238. data/test/helpers/fixture_aliases_helper.rb +1 -0
  239. data/test/helpers/hooks_helper.rb +1 -0
  240. data/test/helpers/json_helper.rb +4 -3
  241. data/test/helpers/links_helper.rb +2 -1
  242. data/test/helpers/payloads_helper.rb +1 -0
  243. data/test/helpers/queries_helper.rb +4 -3
  244. data/test/jobs/cache_deploy_spec_job_test.rb +3 -2
  245. data/test/jobs/chunk_rollup_job_test.rb +3 -2
  246. data/test/jobs/deliver_hook_job_test.rb +1 -0
  247. data/test/jobs/destroy_repository_job_test.rb +1 -0
  248. data/test/jobs/destroy_stack_job_test.rb +12 -0
  249. data/test/jobs/emit_event_job_test.rb +1 -0
  250. data/test/jobs/fetch_commit_stats_job_test.rb +1 -0
  251. data/test/jobs/fetch_deployed_revision_job_test.rb +1 -0
  252. data/test/jobs/github_sync_job_test.rb +22 -21
  253. data/test/jobs/mark_deploy_healthy_job_test.rb +1 -0
  254. data/test/jobs/perform_task_job_test.rb +3 -3
  255. data/test/jobs/process_merge_requests_job_test.rb +7 -6
  256. data/test/jobs/purge_old_deliveries_job_test.rb +1 -0
  257. data/test/jobs/reap_dead_tasks_job_test.rb +1 -0
  258. data/test/jobs/refresh_github_user_job_test.rb +1 -0
  259. data/test/jobs/refresh_status_job_test.rb +1 -0
  260. data/test/jobs/shipit/background_job_test.rb +35 -0
  261. data/test/jobs/shipit/continuous_delivery_job_test.rb +31 -0
  262. data/test/jobs/unique_job_test.rb +3 -1
  263. data/test/jobs/update_github_last_deployed_ref_job_test.rb +1 -0
  264. data/test/middleware/same_site_cookie_middleware_test.rb +2 -2
  265. data/test/models/api_client_test.rb +1 -0
  266. data/test/models/commit_checks_test.rb +2 -1
  267. data/test/models/commit_deployment_status_test.rb +2 -2
  268. data/test/models/commit_deployment_test.rb +4 -3
  269. data/test/models/commits_test.rb +72 -70
  270. data/test/models/delivery_test.rb +3 -2
  271. data/test/models/deploy_spec_test.rb +113 -109
  272. data/test/models/deploy_stats_test.rb +1 -0
  273. data/test/models/deploys_test.rb +65 -56
  274. data/test/models/duration_test.rb +1 -1
  275. data/test/models/github_hook_test.rb +1 -0
  276. data/test/models/hook_test.rb +7 -4
  277. data/test/models/membership_test.rb +1 -0
  278. data/test/models/merge_request_test.rb +26 -20
  279. data/test/models/release_statuses_test.rb +2 -1
  280. data/test/models/rollbacks_test.rb +4 -3
  281. data/test/models/shipit/check_run_test.rb +16 -15
  282. data/test/models/shipit/continuous_delivery_schedule_test.rb +109 -0
  283. data/test/models/shipit/deploy_spec/file_system_test.rb +54 -10
  284. data/test/models/shipit/pull_request_test.rb +9 -9
  285. data/test/models/shipit/repository_test.rb +3 -2
  286. data/test/models/shipit/review_stack_provisioning_queue_test.rb +2 -2
  287. data/test/models/shipit/{stacks_test.rb → stack_test.rb} +48 -34
  288. data/test/models/shipit/webhooks/handlers/pull_request/closed_handler_test.rb +36 -34
  289. data/test/models/shipit/webhooks/handlers/pull_request/label_capturing_handler_test.rb +28 -28
  290. data/test/models/shipit/webhooks/handlers/pull_request/labeled_handler_test.rb +42 -42
  291. data/test/models/shipit/webhooks/handlers/pull_request/opened_handler_test.rb +33 -33
  292. data/test/models/shipit/webhooks/handlers/pull_request/reopened_handler_test.rb +37 -37
  293. data/test/models/shipit/webhooks/handlers/pull_request/review_stack_adapter_test.rb +1 -1
  294. data/test/models/shipit/webhooks/handlers/pull_request/unlabeled_handler_test.rb +44 -42
  295. data/test/models/shipit/webhooks/handlers_test.rb +1 -0
  296. data/test/models/status/group_test.rb +3 -2
  297. data/test/models/status/missing_test.rb +1 -0
  298. data/test/models/status_test.rb +2 -1
  299. data/test/models/task_definitions_test.rb +7 -6
  300. data/test/models/tasks_test.rb +5 -4
  301. data/test/models/team_test.rb +5 -4
  302. data/test/models/undeployed_commits_test.rb +10 -9
  303. data/test/models/users_test.rb +29 -20
  304. data/test/test_command_integration.rb +1 -1
  305. data/test/test_helper.rb +12 -10
  306. data/test/unit/anonymous_user_serializer_test.rb +1 -0
  307. data/test/unit/command_test.rb +10 -1
  308. data/test/unit/commands_test.rb +1 -0
  309. data/test/unit/commit_serializer_test.rb +1 -0
  310. data/test/unit/csv_serializer_test.rb +3 -2
  311. data/test/unit/deploy_commands_test.rb +33 -23
  312. data/test/unit/deploy_serializer_test.rb +1 -0
  313. data/test/unit/environment_variables_test.rb +2 -1
  314. data/test/unit/github_app_test.rb +11 -10
  315. data/test/unit/github_apps_test.rb +19 -18
  316. data/test/unit/github_url_helper_test.rb +1 -0
  317. data/test/unit/line_buffer_test.rb +1 -1
  318. data/test/unit/rollback_commands_test.rb +2 -1
  319. data/test/unit/shipit_helper_test.rb +1 -0
  320. data/test/unit/shipit_test.rb +47 -1
  321. data/test/unit/user_serializer_test.rb +1 -0
  322. data/test/unit/variable_definition_test.rb +4 -3
  323. metadata +61 -47
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class GithubAuthenticationController < ActionController::Base
4
5
  include Shipit::Engine.routes.url_helpers
@@ -11,6 +12,11 @@ module Shipit
11
12
 
12
13
  session[:user_id] = sign_in_github(auth)
13
14
 
15
+ # We need to set this so that the /events and /sidekiq endpoint
16
+ # which leverage `UserRequiredMiddleware` will recognize the user
17
+ # is authenticated.
18
+ session[:authenticated] = true
19
+
14
20
  redirect_to(return_url)
15
21
  end
16
22
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class MergeRequestsController < ShipitController
4
5
  def index
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class MergeStatusController < ShipitController
4
- skip_authentication only: %i(check show)
5
+ skip_authentication only: %i[check show]
5
6
 
6
7
  etag { cache_seed }
7
8
  layout 'merge_status'
@@ -12,6 +13,7 @@ module Shipit
12
13
 
13
14
  if stack
14
15
  return render('logged_out') unless current_user.logged_in?
16
+
15
17
  if stale?(last_modified: [stack.updated_at, merge_request.updated_at].max, template: false)
16
18
  render(stack_status, layout: !request.xhr?)
17
19
  end
@@ -28,8 +30,8 @@ module Shipit
28
30
  end
29
31
 
30
32
  def dequeue
31
- if merge_request = stack.merge_requests.find_by_number(params[:number])
32
- merge_request.cancel! if merge_request.waiting?
33
+ if (merge_request = stack.merge_requests.find_by_number(params[:number])) && merge_request.waiting?
34
+ merge_request.cancel!
33
35
  end
34
36
  render(stack_status, layout: !request.xhr?)
35
37
  end
@@ -43,7 +45,7 @@ module Shipit
43
45
  render(plain: stack_status, status: 503)
44
46
  end
45
47
  end
46
- format.json { render(json: { stack_status: stack_status }) }
48
+ format.json { render(json: { stack_status: }) }
47
49
  end
48
50
  end
49
51
 
@@ -59,23 +61,23 @@ module Shipit
59
61
 
60
62
  def stack
61
63
  @stack ||= if params[:stack_id]
62
- Stack.from_param!(params[:stack_id])
63
- else
64
- # Null ordering is inconsistent across DBMS's, this case statement is ugly but supported universally
65
- scope = Stack.order(Arel.sql('CASE WHEN locked_since IS NULL THEN 1 ELSE 0 END, locked_since'))
66
- .order(merge_queue_enabled: :desc, id: :asc).includes(:repository).where(
67
- repositories: {
68
- owner: referrer_parser.repo_owner,
69
- name: referrer_parser.repo_name,
70
- },
71
- )
72
- scope = if params[:branch]
73
- scope.where(branch: params[:branch])
74
- else
75
- scope.where(environment: 'production')
76
- end
77
- scope.first
78
- end
64
+ Stack.from_param!(params[:stack_id])
65
+ else
66
+ # Null ordering is inconsistent across DBMS's, this case statement is ugly but supported universally
67
+ scope = Stack.order(Arel.sql('CASE WHEN locked_since IS NULL THEN 1 ELSE 0 END, locked_since'))
68
+ .order(merge_queue_enabled: :desc, id: :asc).includes(:repository).where(
69
+ repositories: {
70
+ owner: referrer_parser.repo_owner,
71
+ name: referrer_parser.repo_name
72
+ }
73
+ )
74
+ scope = if params[:branch]
75
+ scope.where(branch: params[:branch])
76
+ else
77
+ scope.where(environment: 'production')
78
+ end
79
+ scope.first
80
+ end
79
81
  end
80
82
 
81
83
  def referrer_parser
@@ -84,12 +86,14 @@ module Shipit
84
86
 
85
87
  def merge_request
86
88
  return @merge_request if defined?(@merge_request)
89
+
87
90
  @merge_request = pull_request_number && stack.merge_requests.find_by_number(pull_request_number)
88
91
  @merge_request ||= UnknownMergeRequest.new
89
92
  end
90
93
 
91
94
  def pull_request_number
92
95
  return @pull_request_number if defined?(@pull_request_number)
96
+
93
97
  @pull_request_number = referrer_parser.pull_request_number
94
98
  end
95
99
 
@@ -113,13 +117,13 @@ module Shipit
113
117
  attr_reader :repo_owner, :repo_name, :pull_request_number
114
118
 
115
119
  def initialize(referrer)
116
- if (match_info = URL_PATTERN.match(referrer.to_s))
117
- @repo_owner = match_info[1].downcase
118
- @repo_name = match_info[2].downcase
119
- @pull_request_number = match_info[3].to_i
120
- else
120
+ unless (match_info = URL_PATTERN.match(referrer.to_s))
121
121
  raise ArgumentError, "Invalid referrer: #{referrer.inspect}"
122
122
  end
123
+
124
+ @repo_owner = match_info[1].downcase
125
+ @repo_name = match_info[2].downcase
126
+ @pull_request_number = match_info[3].to_i
123
127
  end
124
128
  end
125
129
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class ReleaseStatusesController < ShipitController
4
5
  before_action :load_stack
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Shipit
4
4
  class RepositoriesController < ShipitController
5
- before_action :load_repository, only: %i(destroy settings update new_stack)
5
+ before_action :load_repository, only: %i[destroy settings update new_stack]
6
6
 
7
7
  def index
8
8
  @user_repositories = current_user.repositories_contributed_to
@@ -21,9 +21,7 @@ module Shipit
21
21
 
22
22
  def create
23
23
  @repository = Repository.new(create_params)
24
- unless @repository.save
25
- flash[:warning] = @repository.errors.full_messages.to_sentence
26
- end
24
+ flash[:warning] = @repository.errors.full_messages.to_sentence unless @repository.save
27
25
  respond_with(@repository)
28
26
  end
29
27
 
@@ -45,8 +43,7 @@ module Shipit
45
43
  redirect_to(params[:return_to].presence || repository_settings_path(@repository), options)
46
44
  end
47
45
 
48
- def settings
49
- end
46
+ def settings; end
50
47
 
51
48
  def new_stack
52
49
  @stack = @repository.stacks.new
@@ -63,7 +60,7 @@ module Shipit
63
60
  params.require(:repository).permit(
64
61
  :review_stacks_enabled,
65
62
  :provisioning_behavior,
66
- :provisioning_label_name,
63
+ :provisioning_label_name
67
64
  )
68
65
  end
69
66
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class RollbacksController < ShipitController
4
5
  before_action :load_stack
@@ -8,7 +9,7 @@ module Shipit
8
9
  @rollback = @deploy.trigger_rollback(
9
10
  current_user,
10
11
  env: rollback_params[:env]&.to_unsafe_hash,
11
- force: params[:force].present?,
12
+ force: params[:force].present?
12
13
  )
13
14
  redirect_to(stack_deploy_path(@stack, @rollback))
14
15
  rescue Task::ConcurrentTaskRunning
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class ShipitController < ApplicationController
4
5
  layout 'shipit'
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class StacksController < ShipitController
4
- before_action :load_stack, only: %i(update destroy settings statistics clear_git_cache refresh)
5
+ before_action :load_stack, only: %i[update destroy settings statistics clear_git_cache refresh]
5
6
 
6
7
  def new
7
8
  @stack = Stack.new
@@ -13,10 +14,10 @@ module Shipit
13
14
  @stacks = Stack.all
14
15
  if params[:repo]
15
16
  @stacks = if (repository = Repository.from_github_repo_name(params[:repo]))
16
- repository.stacks
17
- else
18
- Stack.none
19
- end
17
+ repository.stacks
18
+ else
19
+ Stack.none
20
+ end
20
21
  end
21
22
 
22
23
  @stacks = @stacks.order(Arel.sql('(undeployed_commits_count > 0) desc'), tasks_count: :desc)
@@ -37,7 +38,7 @@ module Shipit
37
38
  scope.preload(:author, :statuses, :check_runs, :lock_author)
38
39
  end
39
40
 
40
- next_expected_commit_to_deploy = @stack.next_expected_commit_to_deploy(commits: commits)
41
+ next_expected_commit_to_deploy = @stack.next_expected_commit_to_deploy(commits:)
41
42
 
42
43
  @active_commits = []
43
44
  @undeployed_commits = []
@@ -48,11 +49,11 @@ module Shipit
48
49
 
49
50
  @active_commits = map_to_undeployed_commit(
50
51
  @active_commits,
51
- next_expected_commit_to_deploy: next_expected_commit_to_deploy,
52
+ next_expected_commit_to_deploy:
52
53
  )
53
54
  @undeployed_commits = map_to_undeployed_commit(
54
55
  @undeployed_commits,
55
- next_expected_commit_to_deploy: next_expected_commit_to_deploy,
56
+ next_expected_commit_to_deploy:
56
57
  )
57
58
  end
58
59
 
@@ -64,9 +65,7 @@ module Shipit
64
65
  def create
65
66
  @stack = Stack.new(create_params)
66
67
  @stack.repository = repository
67
- unless @stack.save
68
- flash[:warning] = @stack.errors.full_messages.to_sentence
69
- end
68
+ flash[:warning] = @stack.errors.full_messages.to_sentence unless @stack.save
70
69
  respond_with(@stack)
71
70
  end
72
71
 
@@ -75,8 +74,7 @@ module Shipit
75
74
  redirect_to(stacks_url)
76
75
  end
77
76
 
78
- def settings
79
- end
77
+ def settings; end
80
78
 
81
79
  def all_tasks
82
80
  @stack = Stack.from_param!(params[:id])
@@ -103,9 +101,7 @@ module Shipit
103
101
 
104
102
  def update
105
103
  options = {}
106
- unless @stack.update(update_params)
107
- options = { flash: { warning: @stack.errors.full_messages.to_sentence } }
108
- end
104
+ options = { flash: { warning: @stack.errors.full_messages.to_sentence } } unless @stack.update(update_params)
109
105
 
110
106
  update_lock
111
107
  update_archived
@@ -122,30 +118,30 @@ module Shipit
122
118
  private
123
119
 
124
120
  def update_lock
125
- if params[:stack].key?(:lock_reason)
126
- reason = params[:stack][:lock_reason]
127
- if reason.present?
128
- @stack.lock(reason, current_user)
129
- elsif @stack.locked?
130
- @stack.unlock
131
- end
121
+ return unless params[:stack].key?(:lock_reason)
122
+
123
+ reason = params[:stack][:lock_reason]
124
+ if reason.present?
125
+ @stack.lock(reason, current_user)
126
+ elsif @stack.locked?
127
+ @stack.unlock
132
128
  end
133
129
  end
134
130
 
135
131
  def update_archived
136
- if params[:stack][:archived].present?
137
- if params[:stack][:archived] == "true"
138
- @stack.archive!(current_user)
139
- elsif @stack.archived?
140
- @stack.unarchive!
141
- end
132
+ return unless params[:stack][:archived].present?
133
+
134
+ if params[:stack][:archived] == "true"
135
+ @stack.archive!(current_user)
136
+ elsif @stack.archived?
137
+ @stack.unarchive!
142
138
  end
143
139
  end
144
140
 
145
141
  def map_to_undeployed_commit(commits, next_expected_commit_to_deploy:)
146
142
  commits.map.with_index do |c, i|
147
143
  index = commits.size - i - 1
148
- UndeployedCommit.new(c, index: index, next_expected_commit_to_deploy: next_expected_commit_to_deploy)
144
+ UndeployedCommit.new(c, index:, next_expected_commit_to_deploy:)
149
145
  end
150
146
  end
151
147
 
@@ -163,7 +159,7 @@ module Shipit
163
159
  :environment,
164
160
  :continuous_deployment,
165
161
  :ignore_ci,
166
- :merge_queue_enabled,
162
+ :merge_queue_enabled
167
163
  )
168
164
  end
169
165
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class StatusController < ActionController::Base
4
5
  def version
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class TasksController < ShipitController
4
5
  include Pagination
@@ -34,7 +35,7 @@ module Shipit
34
35
  params[:definition_id],
35
36
  current_user,
36
37
  env: task_params[:env],
37
- force: params[:force].present?,
38
+ force: params[:force].present?
38
39
  )
39
40
  redirect_to([stack, @task])
40
41
  rescue Task::ConcurrentTaskRunning
@@ -75,6 +76,7 @@ module Shipit
75
76
 
76
77
  def task_params
77
78
  return {} unless params[:task]
79
+
78
80
  @definition = stack.find_task_definition(params[:definition_id])
79
81
  @task_params ||= params.require(:task).permit(env: @definition.variables.map(&:name))
80
82
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class WebhooksController < ActionController::Base
4
5
  skip_before_action :verify_authenticity_token, raise: false
@@ -33,7 +34,7 @@ module Shipit
33
34
  "event=#{event}",
34
35
  "repository_owner=#{repository_owner}",
35
36
  "signature=#{request.headers['X-Hub-Signature']}",
36
- "status=#{status}",
37
+ "status=#{status}"
37
38
  ].join(' '))
38
39
  end
39
40
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module ApiClientsHelper
4
5
  def api_client_token(api_client)
@@ -1,9 +1,11 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module ChunksHelper
4
5
  def next_chunks_url(task, last_byte: 0)
5
6
  return if task.finished?
6
- tail_stack_task_path(task.stack, task, last_byte: last_byte)
7
+
8
+ tail_stack_task_path(task.stack, task, last_byte:)
7
9
  end
8
10
  end
9
11
  end
@@ -1,19 +1,23 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module DeploysHelper
4
5
  def render_checklist(checklist)
5
6
  return if checklist.blank?
6
- render('shipit/deploys/checklist', checklist: checklist)
7
+
8
+ render('shipit/deploys/checklist', checklist:)
7
9
  end
8
10
 
9
11
  def render_monitoring(stack)
10
12
  return unless stack.monitoring?
11
- render('shipit/deploys/monitoring', stack: stack)
13
+
14
+ render('shipit/deploys/monitoring', stack:)
12
15
  end
13
16
 
14
17
  def render_checks(commit)
15
18
  return unless commit.stack.checks?
16
- render('shipit/commit_checks/checks', commit: commit)
19
+
20
+ render('shipit/commit_checks/checks', commit:)
17
21
  end
18
22
 
19
23
  def render_monitoring_panel(panel_spec)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module GithubUrlHelper
4
5
  private
@@ -44,10 +45,10 @@ module Shipit
44
45
  def github_pull_request_url(pull_request_or_commit)
45
46
  stack = pull_request_or_commit.stack
46
47
  number = if pull_request_or_commit.respond_to?(:pull_request_number)
47
- pull_request_or_commit.pull_request_number
48
- else
49
- pull_request_or_commit.number
50
- end
48
+ pull_request_or_commit.pull_request_number
49
+ else
50
+ pull_request_or_commit.number
51
+ end
51
52
  github_repo_url(stack.repo_owner, stack.repo_name, 'pull', number)
52
53
  end
53
54
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module MergeStatusHelper
4
5
  def display_commit_count_warning?(commits)
@@ -1,20 +1,22 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module ShipitHelper
4
5
  def subscribe(url, *selectors)
5
6
  content_for(:update_subscription) do
6
7
  [
7
8
  tag('meta', name: 'subscription-channel', content: url),
8
- *selectors.map { |s| tag('meta', name: 'subscription-selector', content: s) },
9
+ *selectors.map { |s| tag('meta', name: 'subscription-selector', content: s) }
9
10
  ].join("\n").html_safe
10
11
  end
11
12
  end
12
13
 
13
14
  def emojify(content)
14
- if content.present?
15
- h(content).to_str.gsub(/:([\w+-]+):/) do |match|
16
- if emoji = Emoji.find_by_alias($1)
17
- %(
15
+ return unless content.present?
16
+
17
+ h(content).to_str.gsub(/:([\w+-]+):/) do |match|
18
+ if emoji = Emoji.find_by_alias($1)
19
+ %(
18
20
  <img
19
21
  alt="##{$1}"
20
22
  src="#{image_path("emoji/#{emoji.image_filename}")}"
@@ -23,11 +25,10 @@ module Shipit
23
25
  height="20"
24
26
  />
25
27
  )
26
- else
27
- match
28
- end
29
- end.html_safe
30
- end
28
+ else
29
+ match
30
+ end
31
+ end.html_safe
31
32
  end
32
33
 
33
34
  def include_plugins(stack)
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module StacksHelper
4
5
  def redeploy_button(deployed_commit)
5
6
  commit = UndeployedCommit.new(deployed_commit, index: 0)
6
7
  url = new_stack_deploy_path(commit.stack, sha: commit.sha)
7
- classes = %W(btn btn--primary deploy-action #{commit.state})
8
+ classes = %W[btn btn--primary deploy-action #{commit.state}]
8
9
 
9
10
  unless commit.stack.deployable?
10
11
  classes.push(bypass_safeties? ? 'btn--warning' : 'btn--disabled')
@@ -19,21 +20,19 @@ module Shipit
19
20
 
20
21
  def deploy_button(commit)
21
22
  url = new_stack_deploy_path(commit.stack, sha: commit.sha)
22
- classes = %W(btn btn--primary deploy-action #{commit.state})
23
+ classes = %W[btn btn--primary deploy-action #{commit.state}]
23
24
  deploy_state = commit.deploy_state(bypass_safeties?)
24
25
  data = {}
25
26
 
26
27
  if commit.deploy_disallowed?
27
28
  classes.push(bypass_safeties? ? 'btn--warning' : 'btn--disabled')
28
- if deploy_state == 'blocked'
29
- data[:tooltip] = t('deploy_button.hint.blocked')
30
- end
29
+ data[:tooltip] = t('deploy_button.hint.blocked') if deploy_state == 'blocked'
31
30
  elsif commit.deploy_discouraged?
32
31
  classes.push('btn--warning')
33
32
  data[:tooltip] = t('deploy_button.hint.max_commits', maximum: commit.stack.maximum_commits_per_deploy)
34
33
  end
35
34
 
36
- link_to(t("deploy_button.caption.#{deploy_state}"), url, class: classes, data: data)
35
+ link_to(t("deploy_button.caption.#{deploy_state}"), url, class: classes, data:)
37
36
  end
38
37
 
39
38
  def rollback_button(deploy)
@@ -41,7 +40,7 @@ module Shipit
41
40
  link_to('Deploy in progress...', '#', class: 'btn disabled deploy-action')
42
41
  else
43
42
  url = rollback_stack_deploy_path(deploy.stack, deploy)
44
- classes = %w(btn btn--delete deploy-action rollback-action)
43
+ classes = %w[btn btn--delete deploy-action rollback-action]
45
44
 
46
45
  link_to('Rollback to this deploy...', url, class: classes)
47
46
  end
@@ -80,10 +79,10 @@ module Shipit
80
79
 
81
80
  def pull_request_link(pull_request_or_commit)
82
81
  number = if pull_request_or_commit.respond_to?(:pull_request_number)
83
- pull_request_or_commit.pull_request_number
84
- else
85
- pull_request_or_commit.number
86
- end
82
+ pull_request_or_commit.pull_request_number
83
+ else
84
+ pull_request_or_commit.number
85
+ end
87
86
  link_to("##{number}", github_pull_request_url(pull_request_or_commit), target: '_blank', class: 'number')
88
87
  end
89
88
 
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module TasksHelper
4
5
  def task_description(task)
5
- if task.class == Task
6
+ if task.instance_of?(Task)
6
7
  task.definition.action
7
8
  else
8
9
  t("#{task.class.name.demodulize.underscore.pluralize}.description", sha: task.until_commit.short_sha)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class BackgroundJob
4
5
  module Unique
@@ -18,7 +19,7 @@ module Shipit
18
19
  lock_key(*arguments),
19
20
  Shipit.redis,
20
21
  expiration: self.class.timeout || DEFAULT_TIMEOUT,
21
- timeout: self.class.lock_timeout || 0,
22
+ timeout: self.class.lock_timeout || 0
22
23
  )
23
24
  mutex.lock(&block)
24
25
  rescue Redis::Lock::LockTimeout
@@ -30,7 +31,7 @@ module Shipit
30
31
  end
31
32
 
32
33
  module ClassMethods
33
- ACTIONS = %i(retry drop).freeze
34
+ ACTIONS = %i[retry drop].freeze
34
35
  ACTIONS_LIST = ACTIONS.map(&:inspect).join(', ').freeze
35
36
  def on_duplicate(action)
36
37
  unless ACTIONS.include?(action)
@@ -1,12 +1,19 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class BackgroundJob < ActiveJob::Base
4
5
  class << self
5
6
  attr_accessor :timeout
6
7
  end
7
8
 
9
+ DEFAULT_RETRY_TIME_IN_SECONDS = 30
10
+
8
11
  # Write actions can sometimes fail intermittently, particulary for large and/or busy repositories
9
- retry_on(Octokit::BadGateway, Octokit::InternalServerError)
12
+ retry_on(Octokit::ServerError)
13
+
14
+ rescue_from(Octokit::TooManyRequests, Octokit::AbuseDetected) do |exception|
15
+ retry_job wait: exception.response_headers.fetch("Retry-After", DEFAULT_RETRY_TIME_IN_SECONDS).to_i.seconds
16
+ end
10
17
 
11
18
  def perform(*)
12
19
  with_timeout do
@@ -18,6 +25,7 @@ module Shipit
18
25
 
19
26
  def with_timeout(&block)
20
27
  return yield unless timeout
28
+
21
29
  Timeout.timeout(timeout, &block)
22
30
  end
23
31
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class CacheDeploySpecJob < BackgroundJob
4
5
  include BackgroundJob::Unique
@@ -11,7 +12,7 @@ module Shipit
11
12
 
12
13
  commands = Commands.for(stack)
13
14
  commands.with_temporary_working_directory(commit: stack.commits.reachable.last) do |path|
14
- stack.update!(cached_deploy_spec: DeploySpec::FileSystem.new(path, stack.environment))
15
+ stack.update!(cached_deploy_spec: DeploySpec::FileSystem.new(path, stack))
15
16
  end
16
17
  end
17
18
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class ChunkRollupJob < BackgroundJob
4
5
  include BackgroundJob::Unique
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class ClearGitCacheJob < BackgroundJob
4
5
  queue_as :deploys