shipit-engine 0.39.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 (315) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +40 -1
  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 +10 -8
  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 +2 -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 +4 -2
  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 -2
  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 +4 -3
  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 +35 -16
  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 +8 -6
  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 +1 -1
  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 +59 -56
  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 +33 -28
  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 +21 -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/ccmenu/project.xml.builder +2 -1
  162. data/app/views/shipit/continuous_delivery_schedules/show.html.erb +59 -0
  163. data/app/views/shipit/stacks/_settings_form.erb +1 -0
  164. data/config/initializers/inflections.rb +1 -0
  165. data/config/locales/en.yml +1 -0
  166. data/config/routes.rb +21 -18
  167. data/db/migrate/20240821003007_add_continuous_delivery_schedules.rb +13 -0
  168. data/db/migrate/20250207203053_embiggen_github_ids.rb +8 -0
  169. data/lib/shipit/cast_value.rb +1 -0
  170. data/lib/shipit/command.rb +29 -9
  171. data/lib/shipit/commands.rb +4 -2
  172. data/lib/shipit/csv_serializer.rb +3 -0
  173. data/lib/shipit/deploy_commands.rb +2 -1
  174. data/lib/shipit/engine.rb +5 -4
  175. data/lib/shipit/environment_variables.rb +2 -0
  176. data/lib/shipit/first_parent_commits_iterator.rb +2 -3
  177. data/lib/shipit/flock.rb +11 -9
  178. data/lib/shipit/github_app.rb +14 -15
  179. data/lib/shipit/github_http_cache_middleware.rb +1 -0
  180. data/lib/shipit/null_serializer.rb +1 -0
  181. data/lib/shipit/octokit_check_runs.rb +1 -0
  182. data/lib/shipit/octokit_iterator.rb +2 -0
  183. data/lib/shipit/paginator.rb +1 -0
  184. data/lib/shipit/rollback_commands.rb +2 -1
  185. data/lib/shipit/same_site_cookie_middleware.rb +1 -0
  186. data/lib/shipit/simple_message_verifier.rb +1 -0
  187. data/lib/shipit/stack_commands.rb +34 -26
  188. data/lib/shipit/stat.rb +1 -0
  189. data/lib/shipit/task_commands.rb +7 -6
  190. data/lib/shipit/version.rb +2 -1
  191. data/lib/shipit.rb +29 -16
  192. data/lib/tasks/cron.rake +2 -1
  193. data/lib/tasks/dev.rake +3 -2
  194. data/lib/tasks/shipit.rake +3 -2
  195. data/lib/tasks/teams.rake +3 -2
  196. data/test/controllers/api/base_controller_test.rb +1 -0
  197. data/test/controllers/api/ccmenu_controller_test.rb +4 -3
  198. data/test/controllers/api/commits_controller_test.rb +1 -0
  199. data/test/controllers/api/deploys_controller_test.rb +2 -1
  200. data/test/controllers/api/hooks_controller_test.rb +6 -5
  201. data/test/controllers/api/locks_controller_test.rb +1 -0
  202. data/test/controllers/api/merge_requests_controller_test.rb +1 -0
  203. data/test/controllers/api/outputs_controller_test.rb +1 -0
  204. data/test/controllers/api/release_statuses_controller_test.rb +4 -3
  205. data/test/controllers/api/rollback_controller_test.rb +3 -2
  206. data/test/controllers/api/stacks_controller_test.rb +13 -12
  207. data/test/controllers/api/tasks_controller_test.rb +7 -6
  208. data/test/controllers/api_clients_controller_test.rb +10 -10
  209. data/test/controllers/ccmenu_controller_test.rb +1 -0
  210. data/test/controllers/commit_checks_controller_test.rb +1 -0
  211. data/test/controllers/commits_controller_test.rb +9 -8
  212. data/test/controllers/continuous_delivery_schedules_controller_test.rb +66 -0
  213. data/test/controllers/deploys_controller_test.rb +4 -2
  214. data/test/controllers/github_authentication_controller_test.rb +6 -4
  215. data/test/controllers/merge_requests_controller_test.rb +1 -0
  216. data/test/controllers/merge_status_controller_test.rb +5 -4
  217. data/test/controllers/release_statuses_controller_test.rb +1 -0
  218. data/test/controllers/repositories_controller_test.rb +6 -5
  219. data/test/controllers/rollbacks_controller_test.rb +3 -2
  220. data/test/controllers/stacks_controller_test.rb +7 -5
  221. data/test/controllers/status_controller_test.rb +1 -0
  222. data/test/controllers/tasks_controller_test.rb +5 -4
  223. data/test/controllers/webhooks_controller_test.rb +10 -9
  224. data/test/dummy/config/application.rb +1 -1
  225. data/test/dummy/db/schema.rb +33 -6
  226. data/test/fixtures/shipit/commits.yml +7 -7
  227. data/test/fixtures/shipit/stacks.yml +4 -10
  228. data/test/fixtures/shipit/tasks.yml +3 -3
  229. data/test/helpers/api_helper.rb +2 -3
  230. data/test/helpers/fixture_aliases_helper.rb +1 -0
  231. data/test/helpers/hooks_helper.rb +1 -0
  232. data/test/helpers/json_helper.rb +4 -3
  233. data/test/helpers/links_helper.rb +2 -1
  234. data/test/helpers/payloads_helper.rb +1 -0
  235. data/test/helpers/queries_helper.rb +4 -3
  236. data/test/jobs/cache_deploy_spec_job_test.rb +3 -2
  237. data/test/jobs/chunk_rollup_job_test.rb +3 -2
  238. data/test/jobs/deliver_hook_job_test.rb +1 -0
  239. data/test/jobs/destroy_repository_job_test.rb +1 -0
  240. data/test/jobs/destroy_stack_job_test.rb +12 -0
  241. data/test/jobs/emit_event_job_test.rb +1 -0
  242. data/test/jobs/fetch_commit_stats_job_test.rb +1 -0
  243. data/test/jobs/fetch_deployed_revision_job_test.rb +1 -0
  244. data/test/jobs/github_sync_job_test.rb +22 -21
  245. data/test/jobs/mark_deploy_healthy_job_test.rb +1 -0
  246. data/test/jobs/perform_task_job_test.rb +3 -3
  247. data/test/jobs/process_merge_requests_job_test.rb +7 -6
  248. data/test/jobs/purge_old_deliveries_job_test.rb +1 -0
  249. data/test/jobs/reap_dead_tasks_job_test.rb +1 -0
  250. data/test/jobs/refresh_github_user_job_test.rb +1 -0
  251. data/test/jobs/refresh_status_job_test.rb +1 -0
  252. data/test/jobs/shipit/background_job_test.rb +35 -0
  253. data/test/jobs/shipit/continuous_delivery_job_test.rb +31 -0
  254. data/test/jobs/unique_job_test.rb +3 -1
  255. data/test/jobs/update_github_last_deployed_ref_job_test.rb +1 -0
  256. data/test/middleware/same_site_cookie_middleware_test.rb +2 -2
  257. data/test/models/api_client_test.rb +1 -0
  258. data/test/models/commit_checks_test.rb +2 -1
  259. data/test/models/commit_deployment_status_test.rb +2 -1
  260. data/test/models/commit_deployment_test.rb +4 -3
  261. data/test/models/commits_test.rb +72 -70
  262. data/test/models/delivery_test.rb +3 -2
  263. data/test/models/deploy_spec_test.rb +113 -109
  264. data/test/models/deploy_stats_test.rb +1 -0
  265. data/test/models/deploys_test.rb +65 -56
  266. data/test/models/duration_test.rb +1 -1
  267. data/test/models/github_hook_test.rb +1 -0
  268. data/test/models/hook_test.rb +7 -4
  269. data/test/models/membership_test.rb +1 -0
  270. data/test/models/merge_request_test.rb +23 -20
  271. data/test/models/release_statuses_test.rb +2 -1
  272. data/test/models/rollbacks_test.rb +4 -3
  273. data/test/models/shipit/check_run_test.rb +16 -15
  274. data/test/models/shipit/continuous_delivery_schedule_test.rb +109 -0
  275. data/test/models/shipit/deploy_spec/file_system_test.rb +54 -10
  276. data/test/models/shipit/pull_request_test.rb +9 -9
  277. data/test/models/shipit/repository_test.rb +3 -2
  278. data/test/models/shipit/review_stack_provisioning_queue_test.rb +2 -2
  279. data/test/models/shipit/stack_test.rb +30 -29
  280. data/test/models/shipit/webhooks/handlers/pull_request/closed_handler_test.rb +36 -34
  281. data/test/models/shipit/webhooks/handlers/pull_request/label_capturing_handler_test.rb +28 -28
  282. data/test/models/shipit/webhooks/handlers/pull_request/labeled_handler_test.rb +42 -42
  283. data/test/models/shipit/webhooks/handlers/pull_request/opened_handler_test.rb +33 -33
  284. data/test/models/shipit/webhooks/handlers/pull_request/reopened_handler_test.rb +37 -37
  285. data/test/models/shipit/webhooks/handlers/pull_request/review_stack_adapter_test.rb +1 -1
  286. data/test/models/shipit/webhooks/handlers/pull_request/unlabeled_handler_test.rb +44 -42
  287. data/test/models/shipit/webhooks/handlers_test.rb +1 -0
  288. data/test/models/status/group_test.rb +3 -2
  289. data/test/models/status/missing_test.rb +1 -0
  290. data/test/models/status_test.rb +2 -1
  291. data/test/models/task_definitions_test.rb +7 -6
  292. data/test/models/tasks_test.rb +5 -4
  293. data/test/models/team_test.rb +5 -4
  294. data/test/models/undeployed_commits_test.rb +10 -9
  295. data/test/models/users_test.rb +21 -20
  296. data/test/test_command_integration.rb +1 -1
  297. data/test/test_helper.rb +11 -9
  298. data/test/unit/anonymous_user_serializer_test.rb +1 -0
  299. data/test/unit/command_test.rb +10 -1
  300. data/test/unit/commands_test.rb +1 -0
  301. data/test/unit/commit_serializer_test.rb +1 -0
  302. data/test/unit/csv_serializer_test.rb +3 -2
  303. data/test/unit/deploy_commands_test.rb +33 -23
  304. data/test/unit/deploy_serializer_test.rb +1 -0
  305. data/test/unit/environment_variables_test.rb +2 -1
  306. data/test/unit/github_app_test.rb +10 -9
  307. data/test/unit/github_apps_test.rb +19 -18
  308. data/test/unit/github_url_helper_test.rb +1 -0
  309. data/test/unit/line_buffer_test.rb +1 -1
  310. data/test/unit/rollback_commands_test.rb +2 -1
  311. data/test/unit/shipit_helper_test.rb +1 -0
  312. data/test/unit/shipit_test.rb +47 -1
  313. data/test/unit/user_serializer_test.rb +1 -0
  314. data/test/unit/variable_definition_test.rb +4 -3
  315. metadata +53 -43
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class DeferredTouchJob < BackgroundJob
4
5
  include BackgroundJob::Unique
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class DeliverHookJob < BackgroundJob
4
5
  queue_as :hooks
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class DestroyJob < BackgroundJob
4
5
  queue_as :default
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class DestroyRepositoryJob < BackgroundJob
4
5
  queue_as :default
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class DestroyStackJob < BackgroundJob
4
5
  queue_as :default
@@ -16,22 +17,42 @@ module Shipit
16
17
  # +-- chunks
17
18
 
18
19
  def perform(stack)
19
- Shipit::ApiClient.where(stack_id: stack.id).delete_all
20
- commits_ids = Shipit::Commit.where(stack_id: stack.id).pluck(:id)
21
- tasks_ids = Shipit::Task.where(stack_id: stack.id).pluck(:id)
22
- commit_deployments_ids = Shipit::CommitDeployment.where(task_id: tasks_ids).pluck(:id)
23
- Shipit::CommitDeploymentStatus.where(commit_deployment_id: commit_deployments_ids).delete_all
24
- Shipit::CommitDeployment.where(id: commit_deployments_ids).delete_all
25
- Shipit::Status.where(commit_id: commits_ids).delete_all
26
- Shipit::Commit.where(id: commits_ids).delete_all
27
- Shipit::GithubHook.where(stack_id: stack.id).destroy_all
28
- Shipit::Hook.where(stack_id: stack.id).delete_all
29
- Shipit::MergeRequest.where(stack_id: stack.id).delete_all
30
- tasks_ids.each_slice(100) do |ids|
31
- Shipit::OutputChunk.where(task_id: ids).delete_all
32
- Shipit::Task.where(id: ids).delete_all
33
- end
20
+ delete(Shipit::ApiClient.where(stack_id: stack.id))
21
+
22
+ delete(
23
+ Shipit::CommitDeploymentStatus
24
+ .joins(commit_deployment: [:task])
25
+ .where(commit_deployment: { tasks: { stack_id: stack.id } })
26
+ )
27
+
28
+ delete(Shipit::CommitDeployment.joins(:task).where(task: { stack_id: stack.id }))
29
+ delete(Shipit::Status.joins(:commit).where(commit: { stack_id: stack.id }))
30
+ delete(Shipit::GithubHook.where(stack_id: stack.id))
31
+ delete(Shipit::Hook.where(stack_id: stack.id))
32
+ delete(Shipit::MergeRequest.where(stack_id: stack.id))
33
+
34
+ delete(Shipit::OutputChunk.joins(:task).where(task: { stack_id: stack.id }))
35
+ delete(Shipit::Task.where(stack_id: stack.id))
36
+
37
+ delete(Shipit::Commit.where(stack_id: stack.id))
38
+
34
39
  stack.destroy!
35
40
  end
41
+
42
+ private
43
+
44
+ BATCH_SIZE = 1000
45
+
46
+ def delete(relation)
47
+ if relation.connection.adapter_name.match?(/(mysql|trilogy)/i)
48
+ while relation.limit(BATCH_SIZE).delete_all == BATCH_SIZE
49
+ true # loop
50
+ end
51
+ else
52
+ while relation.model.where(id: relation.select(:id).limit(BATCH_SIZE)).delete_all == BATCH_SIZE
53
+ true # loop
54
+ end
55
+ end
56
+ end
36
57
  end
37
58
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class EmitEventJob < BackgroundJob
4
5
  queue_as :hooks
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class FetchCommitStatsJob < BackgroundJob
4
5
  queue_as :default
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class FetchDeployedRevisionJob < BackgroundJob
4
5
  queue_as :deploys
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class GithubSyncJob < BackgroundJob
4
5
  include BackgroundJob::Unique
@@ -36,13 +37,14 @@ module Shipit
36
37
  def fetch_missing_commits(&block)
37
38
  commits = []
38
39
  github_api = stack&.github_api
39
- iterator = Shipit::FirstParentCommitsIterator.new(github_api: github_api, &block)
40
+ iterator = Shipit::FirstParentCommitsIterator.new(github_api:, &block)
40
41
  iterator.each_with_index do |commit, index|
41
42
  break if index >= MAX_FETCHED_COMMITS
42
43
 
43
44
  if shared_parent = lookup_commit(commit.sha)
44
45
  return commits, shared_parent
45
46
  end
47
+
46
48
  commits.unshift(commit)
47
49
  end
48
50
  [commits, nil]
@@ -59,7 +61,7 @@ module Shipit
59
61
  end
60
62
 
61
63
  def lookup_commit(sha)
62
- stack.commits.find_by(sha: sha)
64
+ stack.commits.find_by(sha:)
63
65
  end
64
66
  end
65
67
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class MarkDeployHealthyJob < BackgroundJob
4
5
  include BackgroundJob::Unique
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class PerformCommitChecksJob < BackgroundJob
4
5
  include BackgroundJob::Unique
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class PerformTaskJob < BackgroundJob
4
5
  queue_as :deploys
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class ProcessMergeRequestsJob < BackgroundJob
4
5
  include BackgroundJob::Unique
@@ -20,6 +21,7 @@ module Shipit
20
21
  merge_requests.select(&:pending?).each do |merge_request|
21
22
  merge_request.refresh!
22
23
  next unless merge_request.all_status_checks_passed?
24
+
23
25
  begin
24
26
  merge_request.merge!
25
27
  rescue MergeRequest::NotReady
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class PurgeOldDeliveriesJob < BackgroundJob
4
5
  include BackgroundJob::Unique
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class ReapDeadTasksJob < BackgroundJob
4
5
  include BackgroundJob::Unique
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class RefreshCheckRunsJob < BackgroundJob
4
5
  queue_as :default
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class RefreshGithubUserJob < BackgroundJob
4
5
  queue_as :default
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class RefreshMergeRequestJob < BackgroundJob
4
5
  queue_as :default
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class RefreshStatusesJob < BackgroundJob
4
5
  queue_as :default
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class SetupGithubHookJob < BackgroundJob
4
5
  queue_as :default
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class UpdateEstimatedDeployDurationJob < BackgroundJob
4
5
  queue_as :default
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class UpdateGithubLastDeployedRefJob < BackgroundJob
4
5
  queue_as :default
5
6
 
6
7
  # We do not prefix 'refs/' because Octokit methods will do this automatically.
7
8
  BRANCH_REF_PREFIX = 'heads'
8
- DEPLOY_PREFIX = "#{Shipit.app_name.downcase}-deploy"
9
+ DEPLOY_PREFIX = "#{Shipit.app_name.downcase}-deploy".freeze
9
10
 
10
11
  def perform(stack)
11
12
  stack_sha = stack.last_successful_deploy_commit&.sha
@@ -17,7 +18,7 @@ module Shipit
17
18
 
18
19
  full_repo_name = stack.github_repo_name
19
20
 
20
- update_or_create_ref(client: client, repo_name: full_repo_name, ref: stack_ref, new_sha: stack_sha)
21
+ update_or_create_ref(client:, repo_name: full_repo_name, ref: stack_ref, new_sha: stack_sha)
21
22
  end
22
23
 
23
24
  private
@@ -34,11 +35,9 @@ module Shipit
34
35
  client.update_ref(repo_name, ref, new_sha)
35
36
  rescue Octokit::UnprocessableEntity => e
36
37
  error_msg = e.message
37
- if error_msg.include?("Reference does not exist")
38
- create_ref(client: client, repo_name: repo_name, ref: ref, sha: new_sha)
39
- else
40
- raise
41
- end
38
+ raise unless error_msg.include?("Reference does not exist")
39
+
40
+ create_ref(client:, repo_name:, ref:, sha: new_sha)
42
41
  end
43
42
  end
44
43
  end
@@ -1,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module DeferredTouch
4
5
  extend ActiveSupport::Concern
5
6
 
6
7
  SET_KEY = 'shipit:deferred_touches'
7
- TMP_KEY = "#{SET_KEY}:updating"
8
- CACHE_KEY = "#{SET_KEY}:scheduled"
8
+ TMP_KEY = "#{SET_KEY}:updating".freeze
9
+ CACHE_KEY = "#{SET_KEY}:scheduled".freeze
9
10
  THROTTLE_TTL = 1.second
10
11
 
11
12
  included do
@@ -39,6 +40,7 @@ module Shipit
39
40
  def fetch
40
41
  fetch_members do |records|
41
42
  return if records.empty?
43
+
42
44
  records = records.each_with_object({}) do |(model, id, attribute), hash|
43
45
  attributes = (hash[model] ||= {})
44
46
  ids = (attributes[attribute] ||= [])
@@ -78,6 +80,7 @@ module Shipit
78
80
 
79
81
  def schedule_touches
80
82
  return unless self.class.deferred_touches
83
+
81
84
  deferred_touches = self.class.deferred_touches.reject do |m, _fk, _a|
82
85
  ActiveRecord::NoTouching.applied_to?(m.constantize)
83
86
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class AnonymousUser
4
5
  def blank?
@@ -21,11 +22,9 @@ module Shipit
21
22
  'https://github.com/images/error/octocat_happy.gif'
22
23
  end
23
24
 
24
- def id
25
- end
25
+ def id; end
26
26
 
27
- def github_id
28
- end
27
+ def github_id; end
29
28
 
30
29
  def logged_in?
31
30
  false
@@ -54,7 +53,7 @@ module Shipit
54
53
  def created_at
55
54
  Time.at(0).utc
56
55
  end
57
- alias_method :updated_at, :created_at
56
+ alias updated_at created_at
58
57
 
59
58
  def read_attribute_for_serialization(attr)
60
59
  public_send(attr)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class ApiClient < Record
4
5
  InsufficientPermission = Class.new(StandardError)
@@ -9,14 +10,14 @@ module Shipit
9
10
  validates :creator, :name, presence: true
10
11
 
11
12
  serialize :permissions, coder: Shipit.serialized_column(:permissions, type: Array)
12
- PERMISSIONS = %w(
13
+ PERMISSIONS = %w[
13
14
  read:stack
14
15
  write:stack
15
16
  deploy:stack
16
17
  lock:stack
17
18
  read:hook
18
19
  write:hook
19
- ).freeze
20
+ ].freeze
20
21
  validates :permissions, subset: { of: PERMISSIONS }
21
22
 
22
23
  class << self
@@ -39,6 +40,7 @@ module Shipit
39
40
  unless permissions.include?(required_permission)
40
41
  raise InsufficientPermission, "This operation requires the `#{required_permission}` permission"
41
42
  end
43
+
42
44
  true
43
45
  end
44
46
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class ApplicationRecord < Record
4
5
  self.abstract_class = true
@@ -1,7 +1,8 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class CheckRun < ApplicationRecord
4
- CONCLUSIONS = %w(success failure neutral cancelled timed_out action_required stale skipped).freeze
5
+ CONCLUSIONS = %w[success failure neutral cancelled timed_out action_required stale skipped].freeze
5
6
  include DeferredTouch
6
7
  include Status::Common
7
8
 
@@ -41,23 +42,23 @@ module Shipit
41
42
 
42
43
  unless checkrun_date
43
44
  Rails.logger.warn("No valid timestamp found in checkrun data. Checkrun id: #{github_check_run.id}.")
44
- RefreshCheckRunsJob.set(wait: CHECK_RUN_REFRESH_DELAY).perform_later(stack_id: stack_id)
45
+ RefreshCheckRunsJob.set(wait: CHECK_RUN_REFRESH_DELAY).perform_later(stack_id:)
45
46
  return
46
47
  end
47
48
 
48
49
  create_or_update_by!(
49
50
  selector: {
50
- github_id: github_check_run.id,
51
+ github_id: github_check_run.id
51
52
  },
52
53
  attributes: {
53
- stack_id: stack_id,
54
+ stack_id:,
54
55
  name: github_check_run.name,
55
56
  conclusion: github_check_run.conclusion,
56
57
  title: github_check_run.output.title.to_s.truncate(1_000),
57
58
  details_url: github_check_run.details_url,
58
59
  html_url: github_check_run.html_url,
59
- github_updated_at: checkrun_date,
60
- },
60
+ github_updated_at: checkrun_date
61
+ }
61
62
  )
62
63
  end
63
64
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class CommandLineUser
4
5
  def present?
@@ -21,11 +22,9 @@ module Shipit
21
22
  'https://github.com/images/error/octocat_happy.gif'
22
23
  end
23
24
 
24
- def id
25
- end
25
+ def id; end
26
26
 
27
- def github_id
28
- end
27
+ def github_id; end
29
28
 
30
29
  def logged_in?
31
30
  false
@@ -50,7 +49,7 @@ module Shipit
50
49
  def created_at
51
50
  Time.at(0).utc
52
51
  end
53
- alias_method :updated_at, :created_at
52
+ alias updated_at created_at
54
53
 
55
54
  def read_attribute_for_serialization(attr)
56
55
  public_send(attr)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class Commit < Record
4
5
  include DeferredTouch
@@ -21,7 +22,7 @@ module Shipit
21
22
  after_create { stack.update_undeployed_commits_count }
22
23
 
23
24
  after_commit :schedule_refresh_statuses!, :schedule_refresh_check_runs!, :schedule_fetch_stats!,
24
- :schedule_continuous_delivery, on: :create
25
+ :schedule_continuous_delivery, on: :create
25
26
 
26
27
  belongs_to :author, class_name: 'User', optional: true, inverse_of: :authored_commits
27
28
  belongs_to :committer, class_name: 'User', optional: true, inverse_of: :commits
@@ -54,25 +55,29 @@ module Shipit
54
55
  scope :reachable, -> { where(detached: false) }
55
56
 
56
57
  delegate :broadcast_update, :github_repo_name, :hidden_statuses, :required_statuses, :blocking_statuses,
57
- :soft_failing_statuses, to: :stack
58
+ :soft_failing_statuses, to: :stack
58
59
 
59
60
  def self.newer_than(commit)
60
61
  return all unless commit
62
+
61
63
  where('id > ?', commit.try(:id) || commit)
62
64
  end
63
65
 
64
66
  def self.older_than(commit)
65
67
  return all unless commit
68
+
66
69
  where('id < ?', commit.try(:id) || commit)
67
70
  end
68
71
 
69
72
  def self.since(commit)
70
73
  return all unless commit
74
+
71
75
  where('id >= ?', commit.try(:id) || commit)
72
76
  end
73
77
 
74
78
  def self.until(commit)
75
79
  return all unless commit
80
+
76
81
  where('id <= ?', commit.try(:id) || commit)
77
82
  end
78
83
 
@@ -85,12 +90,11 @@ module Shipit
85
90
  end
86
91
 
87
92
  def self.by_sha(sha)
88
- if sha.to_s.size < 6
89
- raise AmbiguousRevision, "Short SHA1 #{sha} is ambiguous (too short)"
90
- end
93
+ raise AmbiguousRevision, "Short SHA1 #{sha} is ambiguous (too short)" if sha.to_s.size < 6
91
94
 
92
95
  commits = where('sha like ?', "#{sha}%").take(2)
93
96
  raise AmbiguousRevision, "Short SHA1 #{sha} is ambiguous (matches multiple commits)" if commits.size > 1
97
+
94
98
  commits.first
95
99
  end
96
100
 
@@ -107,26 +111,22 @@ module Shipit
107
111
  record = new(
108
112
  sha: commit.sha,
109
113
  message: commit.commit.message,
110
- author: author,
111
- committer: committer,
114
+ author:,
115
+ committer:,
112
116
  committed_at: commit.commit.committer.date,
113
117
  authored_at: commit.commit.author.date,
114
118
  additions: commit.stats&.additions,
115
- deletions: commit.stats&.deletions,
119
+ deletions: commit.stats&.deletions
116
120
  )
117
121
 
118
- if record.pull_request?
119
- record.pull_request_head_sha = commit.parents.last.sha
120
- end
122
+ record.pull_request_head_sha = commit.parents.last.sha if record.pull_request?
121
123
 
122
124
  record
123
125
  end
124
126
 
125
127
  def message=(message)
126
128
  limit = self.class.columns_hash['message'].limit
127
- if limit && message && message.bytesize > limit
128
- message = message.truncate_bytes(limit)
129
- end
129
+ message = message.truncate_bytes(limit) if limit && message && message.bytesize > limit
130
130
  super(message)
131
131
  end
132
132
 
@@ -168,10 +168,26 @@ module Shipit
168
168
  end
169
169
  end
170
170
 
171
- def refresh_check_runs!
171
+ def paginated_check_runs
172
172
  response = stack.handle_github_redirections do
173
- stack.github_api.check_runs(github_repo_name, sha)
173
+ stack.github_api.check_runs(github_repo_name, sha, per_page: 100)
174
+ end
175
+
176
+ return response if stack.github_api.last_response.rels[:next].nil?
177
+
178
+ loop do
179
+ page = stack.handle_github_redirections do
180
+ stack.github_api.get(stack.github_api.last_response.rels[:next].href)
181
+ end
182
+ response.check_runs.concat(page.check_runs)
183
+ break if stack.github_api.last_response.rels[:next].nil?
174
184
  end
185
+
186
+ response
187
+ end
188
+
189
+ def refresh_check_runs!
190
+ response = paginated_check_runs
175
191
  response.check_runs.each do |check_run|
176
192
  create_or_update_check_run_from_github!(check_run)
177
193
  end
@@ -190,11 +206,11 @@ module Shipit
190
206
 
191
207
  @last_release_status = nil
192
208
  release_statuses.create!(
193
- stack: stack,
194
- user: user,
195
- state: state,
196
- target_url: target_url,
197
- description: description,
209
+ stack:,
210
+ user:,
211
+ state:,
212
+ target_url:,
213
+ description:
198
214
  )
199
215
  end
200
216
 
@@ -223,7 +239,7 @@ module Shipit
223
239
  end
224
240
 
225
241
  def children
226
- self.class.where(stack_id: stack_id).newer_than(self)
242
+ self.class.where(stack_id:).newer_than(self)
227
243
  end
228
244
 
229
245
  def detach_children!
@@ -266,6 +282,7 @@ module Shipit
266
282
 
267
283
  def schedule_continuous_delivery
268
284
  return unless deployable? && stack.continuous_deployment? && stack.deployable?
285
+
269
286
  # This buffer is to allow for statuses and checks to be refreshed before evaluating if the commit is deployable
270
287
  # - e.g. if the commit was fast-forwarded with already passing CI.
271
288
  ContinuousDeliveryJob.set(wait: RECENT_COMMIT_THRESHOLD).perform_later(stack)
@@ -282,7 +299,7 @@ module Shipit
282
299
  def fetch_stats!
283
300
  update!(
284
301
  additions: github_commit.stats&.additions,
285
- deletions: github_commit.stats&.deletions,
302
+ deletions: github_commit.stats&.deletions
286
303
  )
287
304
  end
288
305
 
@@ -300,6 +317,7 @@ module Shipit
300
317
 
301
318
  def identify_merge_request
302
319
  return unless message_parser.pull_request?
320
+
303
321
  if merge_request = stack.merge_requests.find_by(number: message_parser.pull_request_number)
304
322
  self.merge_request = merge_request
305
323
  self.pull_request_number = merge_request.number
@@ -322,14 +340,14 @@ module Shipit
322
340
  def lock(user)
323
341
  update!(
324
342
  locked: true,
325
- lock_author_id: user.id,
343
+ lock_author_id: user.id
326
344
  )
327
345
  end
328
346
 
329
347
  def self.lock_all(user)
330
348
  update_all(
331
349
  locked: true,
332
- lock_author_id: user.id,
350
+ lock_author_id: user.id
333
351
  )
334
352
  end
335
353
 
@@ -356,19 +374,15 @@ module Shipit
356
374
  new_status = status
357
375
 
358
376
  unless already_deployed
359
- payload = { commit: self, stack: stack, status: new_status.state }
360
- if previous_status != new_status
361
- Hook.emit(:commit_status, stack, payload.merge(commit_status: new_status))
362
- end
377
+ payload = { commit: self, stack:, status: new_status.state }
378
+ Hook.emit(:commit_status, stack, payload.merge(commit_status: new_status)) if previous_status != new_status
363
379
  end
364
380
 
365
381
  if previous_status.simple_state != new_status.simple_state
366
382
  if !already_deployed && (!new_status.pending? || previous_status.unknown?)
367
383
  Hook.emit(:deployable_status, stack, payload.merge(deployable_status: new_status))
368
384
  end
369
- if new_status.pending? || new_status.success?
370
- stack.schedule_merges
371
- end
385
+ stack.schedule_merges if new_status.pending? || new_status.success?
372
386
  end
373
387
  new_status
374
388
  end
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class CommitChecks < EphemeralCommitChecks
4
5
  OUTPUT_TTL = 10.minutes.to_i
5
- FINAL_STATUSES = %w(failed error success).freeze
6
+ FINAL_STATUSES = %w[failed error success].freeze
6
7
 
7
8
  def initialize(commit)
8
9
  @commit = commit
@@ -16,12 +17,13 @@ module Shipit
16
17
 
17
18
  def schedule
18
19
  return false if Shipit.redis.get(key('status')).present?
20
+
19
21
  synchronize do
20
22
  return false if Shipit.redis.get(key('status')).present?
21
23
 
22
24
  initialize_redis_state
23
25
  end
24
- PerformCommitChecksJob.perform_later(commit: commit)
26
+ PerformCommitChecksJob.perform_later(commit:)
25
27
  true
26
28
  end
27
29