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,11 +1,12 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class Status < Record
4
5
  include Common
5
6
  include DeferredTouch
6
7
 
7
- STATES = %w(pending success failure error).freeze
8
- enum state: STATES.zip(STATES).to_h
8
+ STATES = %w[pending success failure error].freeze
9
+ enum :state, STATES.zip(STATES).to_h
9
10
 
10
11
  belongs_to :stack, required: true
11
12
  belongs_to :commit, required: true
@@ -22,12 +23,12 @@ module Shipit
22
23
  class << self
23
24
  def replicate_from_github!(stack_id, github_status)
24
25
  find_or_create_by!(
25
- stack_id: stack_id,
26
+ stack_id:,
26
27
  state: github_status.state,
27
28
  description: github_status.description,
28
29
  target_url: github_status.target_url,
29
30
  context: github_status.context,
30
- created_at: github_status.created_at,
31
+ created_at: github_status.created_at
31
32
  )
32
33
  end
33
34
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class Task < Record
4
5
  include DeferredTouch
@@ -10,12 +11,12 @@ module Shipit
10
11
  end
11
12
 
12
13
  PRESENCE_CHECK_TIMEOUT = 30
13
- ACTIVE_STATUSES = %w(pending running aborting).freeze
14
- COMPLETED_STATUSES = %w(success flapping faulty validating).freeze
15
- UNSUCCESSFUL_STATUSES = %w(error failed aborted flapping timedout faulty).freeze
14
+ ACTIVE_STATUSES = %w[pending running aborting].freeze
15
+ COMPLETED_STATUSES = %w[success flapping faulty validating].freeze
16
+ UNSUCCESSFUL_STATUSES = %w[error failed aborted flapping timedout faulty].freeze
16
17
  OUTPUT_SIZE_LIMIT = 16.megabytes # A MySQL mediumblob
17
18
  HUMAN_READABLE_OUTPUT_LIMIT = ActionController::Base.helpers.number_to_human_size(OUTPUT_SIZE_LIMIT)
18
- OUTPUT_TRUNCATED_MESSAGE = "Output exceeded the limit of #{HUMAN_READABLE_OUTPUT_LIMIT} and was truncated\n"
19
+ OUTPUT_TRUNCATED_MESSAGE = "Output exceeded the limit of #{HUMAN_READABLE_OUTPUT_LIMIT} and was truncated\n".freeze
19
20
 
20
21
  attr_accessor :pid
21
22
 
@@ -35,6 +36,7 @@ module Shipit
35
36
  class << self
36
37
  def dump(hash)
37
38
  raise TypeError, "Task#env should be a Hash[String => String]" unless hash.is_a?(Hash)
39
+
38
40
  hash = hash.to_h.stringify_keys
39
41
  hash.transform_values! do |value|
40
42
  case value
@@ -49,7 +51,7 @@ module Shipit
49
51
  end
50
52
 
51
53
  def load(hash)
52
- hash&.to_h || {} # cast back to a real hash
54
+ hash.to_h # cast back to a real hash
53
55
  end
54
56
 
55
57
  def new
@@ -104,11 +106,11 @@ module Shipit
104
106
  task.ended_at ||= Time.now.utc
105
107
  end
106
108
 
107
- after_transition any => %i(success failed error timedout) do |task|
109
+ after_transition any => %i[success failed error timedout] do |task|
108
110
  task.async_refresh_deployed_revision
109
111
  end
110
112
 
111
- after_transition any => %i(aborted success failed error timedout) do |task|
113
+ after_transition any => %i[aborted success failed error timedout] do |task|
112
114
  task.schedule_rollup_chunks
113
115
  end
114
116
 
@@ -120,7 +122,7 @@ module Shipit
120
122
  task.async_update_estimated_deploy_duration
121
123
  end
122
124
 
123
- after_transition any => %i(failed error timedout) do |task|
125
+ after_transition any => %i[failed error timedout] do |task|
124
126
  task.retry_if_necessary
125
127
  end
126
128
 
@@ -129,19 +131,19 @@ module Shipit
129
131
  end
130
132
 
131
133
  event :failure do
132
- transition %i(running flapping) => :failed
134
+ transition %i[running flapping] => :failed
133
135
  end
134
136
 
135
137
  event :complete do
136
- transition %i(running flapping validating faulty) => :success
138
+ transition %i[running flapping validating faulty] => :success
137
139
  end
138
140
 
139
141
  event :enter_validation do
140
- transition %i(running flapping) => :validating
142
+ transition %i[running flapping] => :validating
141
143
  end
142
144
 
143
145
  event :mark_faulty do
144
- transition %i(validating success) => :faulty
146
+ transition %i[validating success] => :faulty
145
147
  end
146
148
 
147
149
  event :error do
@@ -153,7 +155,7 @@ module Shipit
153
155
  end
154
156
 
155
157
  event :aborting do
156
- transition all - %i(aborted) => :aborting
158
+ transition all - %i[aborted] => :aborting
157
159
  end
158
160
 
159
161
  event :aborted do
@@ -161,7 +163,7 @@ module Shipit
161
163
  end
162
164
 
163
165
  event :flap do
164
- transition %i(failed error timedout success) => :flapping
166
+ transition %i[failed error timedout success] => :flapping
165
167
  end
166
168
 
167
169
  state :pending
@@ -206,7 +208,7 @@ module Shipit
206
208
  end
207
209
 
208
210
  delegate :acquire_git_cache_lock, :async_refresh_deployed_revision, :async_update_estimated_deploy_duration,
209
- to: :stack
211
+ to: :stack
210
212
 
211
213
  delegate :checklist, to: :definition
212
214
 
@@ -219,16 +221,18 @@ module Shipit
219
221
  end
220
222
 
221
223
  def spec
222
- @spec ||= DeploySpec::FileSystem.new(working_directory, stack.environment)
224
+ @spec ||= DeploySpec::FileSystem.new(working_directory, stack)
223
225
  end
224
226
 
225
227
  def enqueue
226
228
  raise "only persisted jobs can be enqueued" unless persisted?
229
+
227
230
  PerformTaskJob.perform_later(self)
228
231
  end
229
232
 
230
233
  def run_now!
231
234
  raise "only persisted jobs can be run" unless persisted?
235
+
232
236
  PerformTaskJob.perform_now(self)
233
237
  end
234
238
 
@@ -350,10 +354,10 @@ module Shipit
350
354
  end
351
355
  end
352
356
 
353
- def abort!(rollback_once_aborted: false, rollback_once_aborted_to: nil, aborted_by:)
357
+ def abort!(aborted_by:, rollback_once_aborted: false, rollback_once_aborted_to: nil)
354
358
  update!(
355
- rollback_once_aborted: rollback_once_aborted,
356
- rollback_once_aborted_to: rollback_once_aborted_to,
359
+ rollback_once_aborted:,
360
+ rollback_once_aborted_to:,
357
361
  aborted_by_id: aborted_by.id
358
362
  )
359
363
 
@@ -383,12 +387,13 @@ module Shipit
383
387
 
384
388
  def emit_hooks_if_status_changed
385
389
  return unless @status_changed
390
+
386
391
  @status_changed = nil
387
392
  emit_hooks
388
393
  end
389
394
 
390
395
  def emit_hooks
391
- Hook.emit(hook_event, stack, hook_event => self, status: status, stack: stack)
396
+ Hook.emit(hook_event, stack, hook_event => self, status:, stack:)
392
397
  end
393
398
 
394
399
  def hook_event
@@ -427,13 +432,13 @@ module Shipit
427
432
  5.minutes.ago
428
433
  end
429
434
 
430
- ZOMBIE_STATES = %w(running aborting).freeze
435
+ ZOMBIE_STATES = %w[running aborting].freeze
431
436
  private_constant :ZOMBIE_STATES
432
437
  def self.zombies
433
438
  where(status: ZOMBIE_STATES)
434
439
  .where(
435
440
  "created_at <= :recently",
436
- recently: recently_created_at,
441
+ recently: recently_created_at
437
442
  )
438
443
  .reject(&:alive?)
439
444
  end
@@ -441,13 +446,13 @@ module Shipit
441
446
  def retry_if_necessary
442
447
  return unless retries_configured? && !stack.reload.locked?
443
448
 
444
- if retry_attempt < max_retries
445
- retry_task = duplicate_task
446
- retry_task.retry_attempt = duplicate_task.retry_attempt + 1
447
- retry_task.save!
449
+ return unless retry_attempt < max_retries
448
450
 
449
- retry_task.enqueue
450
- end
451
+ retry_task = duplicate_task
452
+ retry_task.retry_attempt = duplicate_task.retry_attempt + 1
453
+ retry_task.save!
454
+
455
+ retry_task.enqueue
451
456
  end
452
457
 
453
458
  def retries_configured?
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class TaskDefinition
4
5
  NotFound = Class.new(StandardError)
@@ -6,18 +7,20 @@ module Shipit
6
7
  class << self
7
8
  def load(payload)
8
9
  return if payload.blank?
10
+
9
11
  json = JSON.parse(payload)
10
12
  new(json.delete('id'), json)
11
13
  end
12
14
 
13
15
  def dump(definition)
14
16
  return if definition.blank?
17
+
15
18
  JSON.dump(definition.as_json)
16
19
  end
17
20
  end
18
21
 
19
22
  attr_reader :id, :action, :description, :steps, :checklist, :variables
20
- alias_method :to_param, :id
23
+ alias to_param id
21
24
 
22
25
  def initialize(id, config)
23
26
  @id = id
@@ -46,14 +49,14 @@ module Shipit
46
49
 
47
50
  def as_json
48
51
  {
49
- id: id,
50
- action: action,
52
+ id:,
53
+ action:,
51
54
  title: @title,
52
- description: description,
53
- steps: steps,
55
+ description:,
56
+ steps:,
54
57
  variables: variables.map(&:to_h),
55
- checklist: checklist,
56
- allow_concurrency: allow_concurrency?,
58
+ checklist:,
59
+ allow_concurrency: allow_concurrency?
57
60
  }
58
61
  end
59
62
 
@@ -21,16 +21,16 @@ module Shipit
21
21
  perform_task
22
22
  @task.write("\nCompleted successfully\n")
23
23
  @task.report_complete!
24
- rescue Command::TimedOut => error
25
- @task.write("\n#{error.message}\n")
26
- @task.report_timeout!(error)
27
- rescue Command::Error => error
28
- @task.write("\n#{error.message}\n")
29
- @task.report_failure!(error)
30
- rescue StandardError => error
31
- @task.report_error!(error)
32
- rescue Exception => error
33
- @task.report_error!(error)
24
+ rescue Command::TimedOut => e
25
+ @task.write("\n#{e.message}\n")
26
+ @task.report_timeout!(e)
27
+ rescue Command::Error => e
28
+ @task.write("\n#{e.message}\n")
29
+ @task.report_failure!(e)
30
+ rescue StandardError => e
31
+ @task.report_error!(e)
32
+ rescue Exception => e
33
+ @task.report_error!(e)
34
34
  raise
35
35
  end
36
36
 
@@ -42,8 +42,8 @@ module Shipit
42
42
  else
43
43
  @task.write("Can't abort, no recorded pid, WTF?\n")
44
44
  end
45
- rescue SystemCallError => error
46
- @task.write("kill: (#{pid}) - #{error.message}\n")
45
+ rescue SystemCallError => e
46
+ @task.write("kill: (#{pid}) - #{e.message}\n")
47
47
  end
48
48
 
49
49
  def check_for_abort
@@ -94,7 +94,7 @@ module Shipit
94
94
  @task.write(line)
95
95
  end
96
96
  finished_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
97
- @task.write("pid: #{command.pid} finished in: #{finished_at - started_at} seconds\n")
97
+ @task.write("pid: #{command.pid} finished in: #{(finished_at - started_at).round(3)} seconds\n")
98
98
  command.success?
99
99
  end
100
100
 
@@ -1,32 +1,33 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class Team < Record
4
- REQUIRED_HOOKS = %i(membership).freeze
5
+ REQUIRED_HOOKS = %i[membership].freeze
5
6
 
6
7
  has_many :memberships
7
8
  has_many :members, class_name: :User, through: :memberships, source: :user
8
9
 
9
10
  has_many :github_hooks,
10
- -> { where(event: REQUIRED_HOOKS) },
11
- foreign_key: :organization,
12
- primary_key: :organization,
13
- class_name: 'GithubHook::Organization',
14
- inverse_of: false
11
+ -> { where(event: REQUIRED_HOOKS) },
12
+ foreign_key: :organization,
13
+ primary_key: :organization,
14
+ class_name: 'GithubHook::Organization',
15
+ inverse_of: false
15
16
 
16
17
  class << self
17
18
  def find_or_create_by_handle(handle)
18
19
  organization, slug = handle.split('/').map(&:downcase)
19
- find_by(organization: organization, slug: slug) || fetch_and_create_from_github(organization, slug)
20
+ find_by(organization:, slug:) || fetch_and_create_from_github(organization, slug)
20
21
  end
21
22
 
22
23
  def fetch_and_create_from_github(organization, slug)
23
- if github_team = find_team_on_github(organization, slug)
24
- create!(github_team: github_team, organization: organization)
25
- end
24
+ return unless github_team = find_team_on_github(organization, slug)
25
+
26
+ create!(github_team:, organization:)
26
27
  end
27
28
 
28
29
  def find_team_on_github(organization, slug)
29
- gh_api = Shipit.github(organization: organization).api
30
+ gh_api = Shipit.github(organization:).api
30
31
  teams = Shipit::OctokitIterator.new(github_api: gh_api) { gh_api.org_teams(organization, per_page: 100) }
31
32
  teams.find { |t| t.slug == slug }
32
33
  rescue Octokit::NotFound
@@ -42,7 +43,7 @@ module Shipit
42
43
  end
43
44
 
44
45
  def refresh_members!
45
- github_api = Shipit.github(organization: organization).api
46
+ github_api = Shipit.github(organization:).api
46
47
  github_members = Shipit::OctokitIterator.new(github_api.get(api_url).rels[:members])
47
48
  members = github_members.map { |u| User.find_or_create_from_github(u) }
48
49
  self.members = members
@@ -1,4 +1,10 @@
1
1
  # frozen_string_literal: true
2
+
3
+ # rubocop:disable Lint/MissingCopEnableDirective, Style/OptionalBooleanParameter
4
+ # Disabling for now because we need to support the `bypass_safeties` parameter
5
+ # in the `deploy_state` and `redeploy_state` methods. We can revisit this later.
6
+
7
+ require 'delegate'
2
8
  module Shipit
3
9
  class UndeployedCommit < DelegateClass(Commit)
4
10
  attr_reader :index
@@ -26,9 +32,7 @@ module Shipit
26
32
 
27
33
  def redeploy_state(bypass_safeties = false)
28
34
  state = 'allowed'
29
- unless bypass_safeties
30
- state = 'deploying' if stack.active_task?
31
- end
35
+ state = 'deploying' if !bypass_safeties && stack.active_task?
32
36
  state
33
37
  end
34
38
 
@@ -50,6 +54,7 @@ module Shipit
50
54
 
51
55
  def blocked?
52
56
  return @blocked if defined?(@blocked)
57
+
53
58
  @blocked = super
54
59
  end
55
60
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class UnlimitedApiClient
4
5
  def stack_id?
5
6
  false
6
7
  end
7
8
 
8
- def check_permissions!(*)
9
- end
9
+ def check_permissions!(*); end
10
10
  end
11
11
  end
@@ -1,9 +1,10 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class User < Record
4
5
  DEFAULT_AVATAR = URI.parse('https://avatars.githubusercontent.com/u/583231?')
5
6
 
6
- self.ignored_columns = %w(encrypted_github_access_token_iv)
7
+ self.ignored_columns = %w[encrypted_github_access_token_iv]
7
8
 
8
9
  has_many :memberships
9
10
  has_many :teams, through: :memberships
@@ -19,7 +20,7 @@ module Shipit
19
20
  after_find :discard_outdated_credentials!
20
21
 
21
22
  def self.find_or_create_by_login!(login)
22
- find_or_create_by!(login: login) do |user|
23
+ find_or_create_by!(login:) do |user|
23
24
  # Users are global, any app can be used
24
25
  # This will not work for users that only exist in an Enterprise install
25
26
  user.github_user = Shipit.github.api.user(login)
@@ -31,7 +32,7 @@ module Shipit
31
32
  end
32
33
 
33
34
  def self.find_or_create_author_from_github_commit(github_commit)
34
- if (match_info = github_commit.commit.message.match(/^#{MergeRequest::MERGE_REQUEST_FIELD}: ([\w\-\.]+)$/))
35
+ if (match_info = github_commit.commit.message.match(/^#{MergeRequest::MERGE_REQUEST_FIELD}: ([\w\-.]+)$/))
35
36
  begin
36
37
  return find_or_create_by_login!(match_info[1])
37
38
  rescue Octokit::NotFound
@@ -48,11 +49,12 @@ module Shipit
48
49
 
49
50
  def self.find_from_github(github_user)
50
51
  return unless github_user.id
52
+
51
53
  find_by(github_id: github_user.id)
52
54
  end
53
55
 
54
56
  def self.create_from_github(github_user)
55
- create(github_user: github_user)
57
+ create(github_user:)
56
58
  end
57
59
 
58
60
  def self.refresh_shard(shard_index, shards_count)
@@ -68,7 +70,7 @@ module Shipit
68
70
  end
69
71
 
70
72
  def identifiers_for_ping
71
- { github_id: github_id, name: name, email: email, github_login: login }
73
+ { github_id:, name:, email:, github_login: login }
72
74
  end
73
75
 
74
76
  def logged_in?
@@ -81,12 +83,14 @@ module Shipit
81
83
 
82
84
  def repositories_contributed_to
83
85
  return [] unless id
86
+
84
87
  Stack.where(id: stacks_contributed_to).distinct.pluck(:repository_id)
85
88
  end
86
89
 
87
90
  def stacks_contributed_to
88
91
  return [] unless id
89
- Commit.where('author_id = :id or committer_id = :id', id: id).distinct.pluck(:stack_id)
92
+
93
+ Commit.where('author_id = :id or committer_id = :id', id:).distinct.pluck(:stack_id)
90
94
  end
91
95
 
92
96
  def refresh_from_github!
@@ -112,7 +116,7 @@ module Shipit
112
116
  email: appropriate_email_for(github_user),
113
117
  login: github_user.login,
114
118
  avatar_url: github_user.avatar_url,
115
- api_url: github_user.url,
119
+ api_url: github_user.url
116
120
  )
117
121
  end
118
122
 
@@ -132,18 +136,19 @@ module Shipit
132
136
  private
133
137
 
134
138
  def discard_outdated_credentials!
135
- if encrypted_github_access_token_before_type_cast.present?
136
- begin
137
- encrypted_github_access_token
138
- rescue ActiveRecord::Encryption::Errors::Decryption
139
- update_column(:encrypted_github_access_token, nil)
140
- end
139
+ return unless encrypted_github_access_token_before_type_cast.present?
140
+
141
+ begin
142
+ encrypted_github_access_token
143
+ rescue ActiveRecord::Encryption::Errors::Decryption
144
+ update_column(:encrypted_github_access_token, nil)
141
145
  end
142
146
  end
143
147
 
144
148
  def identify_renamed_user!
145
149
  last_commit = commits.last
146
150
  return unless last_commit
151
+
147
152
  github_author = last_commit.github_commit.author
148
153
  update!(github_user: github_author)
149
154
  rescue Octokit::NotFound
@@ -163,9 +168,9 @@ module Shipit
163
168
 
164
169
  begin
165
170
  github_api.emails
166
- .sort_by { |e| e.primary ? 0 : 1 }
167
- .map(&:email)
168
- .find { |e| email_valid_and_preferred?(e) }
171
+ .sort_by { |e| e.primary ? 0 : 1 }
172
+ .map(&:email)
173
+ .find { |e| email_valid_and_preferred?(e) }
169
174
  rescue Octokit::NotFound, Octokit::Forbidden, Octokit::Unauthorized
170
175
  # If the user hasn't agreed to the necessary permission, we can't access their private emails.
171
176
  Rails.logger.warn("Failed to retrieve emails for user '#{github_user.name || github_user.login}'")
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class VariableDefinition
4
5
  attr_reader :name, :title, :default, :select
@@ -20,7 +21,7 @@ module Shipit
20
21
  'name' => @name,
21
22
  'title' => @title,
22
23
  'default' => @default,
23
- 'select' => @select,
24
+ 'select' => @select
24
25
  }
25
26
  end
26
27
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module Webhooks
4
5
  module Handlers
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module Webhooks
4
5
  module Handlers
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module Webhooks
4
5
  module Handlers
@@ -52,16 +52,16 @@ module Shipit
52
52
 
53
53
  def pull_request
54
54
  @pull_request ||= Shipit::PullRequest
55
- .joins(:stack, stack: :repository)
56
- .find_by(
57
- number: params.number,
58
- stacks: {
59
- repositories:
60
- {
61
- id: repository.id,
62
- },
63
- }
64
- )
55
+ .joins(:stack, stack: :repository)
56
+ .find_by(
57
+ number: params.number,
58
+ stacks: {
59
+ repositories:
60
+ {
61
+ id: repository.id
62
+ }
63
+ }
64
+ )
65
65
  end
66
66
 
67
67
  def repository
@@ -55,7 +55,7 @@ module Shipit
55
55
  def review_stack
56
56
  @review_stack ||=
57
57
  Shipit::Webhooks::Handlers::PullRequest::ReviewStackAdapter
58
- .new(params, scope: repository.review_stacks)
58
+ .new(params, scope: repository.review_stacks)
59
59
  end
60
60
 
61
61
  def respond_to_pull_request_closed?
@@ -48,16 +48,16 @@ module Shipit
48
48
 
49
49
  def pull_request
50
50
  @pull_request ||= Shipit::PullRequest
51
- .joins(:stack, stack: :repository)
52
- .find_by(
53
- number: params.number,
54
- stacks: {
55
- repositories:
56
- {
57
- id: repository.id,
58
- },
59
- }
60
- )
51
+ .joins(:stack, stack: :repository)
52
+ .find_by(
53
+ number: params.number,
54
+ stacks: {
55
+ repositories:
56
+ {
57
+ id: repository.id
58
+ }
59
+ }
60
+ )
61
61
  end
62
62
 
63
63
  def repository
@@ -104,13 +104,13 @@ module Shipit
104
104
  def review_stack
105
105
  @review_stack ||=
106
106
  Shipit::Webhooks::Handlers::PullRequest::ReviewStackAdapter
107
- .new(params, scope: repository.review_stacks)
107
+ .new(params, scope: repository.review_stacks)
108
108
  end
109
109
 
110
110
  def repository
111
111
  @repository ||=
112
112
  Shipit::Repository
113
- .from_github_repo_name(params.repository.full_name) || NullRepository.new
113
+ .from_github_repo_name(params.repository.full_name) || NullRepository.new
114
114
  end
115
115
 
116
116
  def stack
@@ -59,12 +59,12 @@ module Shipit
59
59
  def stack
60
60
  @stack ||=
61
61
  Shipit::Webhooks::Handlers::PullRequest::ReviewStackAdapter
62
- .new(params, scope: repository.review_stacks)
62
+ .new(params, scope: repository.review_stacks)
63
63
  end
64
64
 
65
65
  def repository
66
66
  @repository ||= Shipit::Repository.from_github_repo_name(params.repository.full_name) ||
67
- Shipit::NullRepository.new
67
+ Shipit::NullRepository.new
68
68
  end
69
69
 
70
70
  def pull_request