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
  require 'fileutils'
3
4
 
4
5
  module Shipit
@@ -24,7 +25,7 @@ module Shipit
24
25
  end
25
26
 
26
27
  ENVIRONMENT_MAX_SIZE = 50
27
- REQUIRED_HOOKS = %i(push status).freeze
28
+ REQUIRED_HOOKS = %i[push status].freeze
28
29
 
29
30
  has_many :commits, dependent: :destroy
30
31
  has_many :merge_requests, dependent: :destroy
@@ -32,12 +33,13 @@ module Shipit
32
33
  has_many :deploys
33
34
  has_many :rollbacks
34
35
  has_many :deploys_and_rollbacks,
35
- -> { where(type: %w(Shipit::Deploy Shipit::Rollback)) },
36
- class_name: 'Task',
37
- inverse_of: :stack
36
+ -> { where(type: %w[Shipit::Deploy Shipit::Rollback]) },
37
+ class_name: 'Task',
38
+ inverse_of: :stack
38
39
  has_many :github_hooks, dependent: :destroy, class_name: 'Shipit::GithubHook::Repo'
39
40
  has_many :hooks, dependent: :destroy
40
41
  has_many :api_clients, dependent: :destroy
42
+ has_one :continuous_delivery_schedule, dependent: :destroy
41
43
  belongs_to :lock_author, class_name: :User, optional: true
42
44
  belongs_to :repository
43
45
  validates_associated :repository
@@ -56,7 +58,7 @@ module Shipit
56
58
  'GITHUB_REPO_OWNER' => repository.owner,
57
59
  'GITHUB_REPO_NAME' => repository.name,
58
60
  'DEPLOY_URL' => deploy_url,
59
- 'BRANCH' => branch,
61
+ 'BRANCH' => branch
60
62
  }
61
63
  end
62
64
 
@@ -86,22 +88,22 @@ module Shipit
86
88
  after_commit :sync_github_if_necessary, on: :update
87
89
 
88
90
  def sync_github_if_necessary
89
- if (archived_since_previously_changed? && archived_since.nil?) || branch_previously_changed?
90
- sync_github
91
- end
91
+ return unless (archived_since_previously_changed? && archived_since.nil?) || branch_previously_changed?
92
+
93
+ sync_github
92
94
  end
93
95
 
94
96
  validates :repository, uniqueness: {
95
- scope: %i(environment), case_sensitive: false,
96
- message: 'cannot be used more than once with this environment. Check archived stacks.',
97
+ scope: %i[environment], case_sensitive: false,
98
+ message: 'cannot be used more than once with this environment. Check archived stacks.'
97
99
  }
98
- validates :environment, format: { with: /\A[a-z0-9\-_\:]+\z/ }, length: { maximum: ENVIRONMENT_MAX_SIZE }
99
- validates :deploy_url, format: { with: URI.regexp(%w(http https ssh)) }, allow_blank: true
100
+ validates :environment, format: { with: /\A[a-z0-9\-_:]+\z/ }, length: { maximum: ENVIRONMENT_MAX_SIZE }
101
+ validates :deploy_url, format: { with: URI::DEFAULT_PARSER.make_regexp(%w[http https ssh]) }, allow_blank: true
100
102
  validates :branch, presence: true
101
103
 
102
104
  validates :lock_reason, length: { maximum: 4096 }
103
105
 
104
- serialize :cached_deploy_spec, DeploySpec
106
+ serialize :cached_deploy_spec, coder: DeploySpec
105
107
  delegate(
106
108
  :provisioning_handler_name,
107
109
  :find_task_definition,
@@ -130,7 +132,7 @@ module Shipit
130
132
 
131
133
  def trigger_task(definition_id, user, env: nil, force: false)
132
134
  definition = find_task_definition(definition_id)
133
- env = env&.to_h || {}
135
+ env = env.to_h
134
136
 
135
137
  definition.variables_with_defaults.each do |variable|
136
138
  env[variable.name] ||= variable.default
@@ -139,27 +141,27 @@ module Shipit
139
141
  commit = last_deployed_commit.presence || commits.first
140
142
  task = tasks.create(
141
143
  user_id: user.id,
142
- definition: definition,
144
+ definition:,
143
145
  until_commit_id: commit.id,
144
146
  since_commit_id: commit.id,
145
147
  env: definition.filter_envs(env),
146
148
  allow_concurrency: definition.allow_concurrency? || force,
147
- ignored_safeties: force,
149
+ ignored_safeties: force
148
150
  )
149
151
  task.enqueue
150
152
  task
151
153
  end
152
154
 
153
- def build_deploy(until_commit, user, env: nil, force: false)
155
+ def build_deploy(until_commit, user, env: nil, force: false, allow_concurrency: force)
154
156
  since_commit = last_deployed_commit.presence || commits.first
155
157
  deploys.build(
156
158
  user_id: user.id,
157
- until_commit: until_commit,
158
- since_commit: since_commit,
159
- env: filter_deploy_envs(env&.to_h || {}),
160
- allow_concurrency: force,
159
+ until_commit:,
160
+ since_commit:,
161
+ env: filter_deploy_envs(env.to_h),
162
+ allow_concurrency:,
161
163
  ignored_safeties: force || !until_commit.deployable?,
162
- max_retries: retries_on_deploy,
164
+ max_retries: retries_on_deploy
163
165
  )
164
166
  end
165
167
 
@@ -226,22 +228,25 @@ module Shipit
226
228
 
227
229
  def next_commit_to_deploy
228
230
  commits_to_deploy = commits.order(id: :asc).newer_than(last_deployed_commit).reachable.preload(:statuses)
229
- commits_to_deploy = commits_to_deploy.limit(maximum_commits_per_deploy) if maximum_commits_per_deploy
230
- commits_to_deploy.to_a.reverse.find(&:deployable?)
231
+ if maximum_commits_per_deploy
232
+ commits_with_max_applied = commits_to_deploy.limit(maximum_commits_per_deploy)
233
+ deployable_commits(commits_with_max_applied) || deployable_commits(commits_to_deploy)
234
+ else
235
+ deployable_commits(commits_to_deploy)
236
+ end
231
237
  end
232
238
 
233
239
  def deployed_too_recently?
234
- if task = last_active_task
235
- return true if task.validating?
240
+ return unless task = last_active_task
241
+ return true if task.validating?
236
242
 
237
- task.ended_at? && (task.ended_at + pause_between_deploys).future?
238
- end
243
+ task.ended_at? && (task.ended_at + pause_between_deploys).future?
239
244
  end
240
245
 
241
246
  def async_refresh_deployed_revision
242
247
  async_refresh_deployed_revision!
243
- rescue => error
244
- logger.warn("Failed to dispatch FetchDeployedRevisionJob: [#{error.class.name}] #{error.message}")
248
+ rescue StandardError => e
249
+ logger.warn("Failed to dispatch FetchDeployedRevisionJob: [#{e.class.name}] #{e.message}")
245
250
  end
246
251
 
247
252
  def async_refresh_deployed_revision!
@@ -263,7 +268,7 @@ module Shipit
263
268
  deploys.create!(
264
269
  until_commit: actual_deployed_commit,
265
270
  since_commit: last_deployed_commit.presence || commits.first,
266
- status: 'success',
271
+ status: 'success'
267
272
  )
268
273
  end
269
274
  end
@@ -274,8 +279,9 @@ module Shipit
274
279
 
275
280
  def merge_status(backlog_leniency_factor: 2.0)
276
281
  return 'locked' if locked?
277
- return 'failure' if %w(failure error).freeze.include?(branch_status)
278
- return 'backlogged' if backlogged?(backlog_leniency_factor: backlog_leniency_factor)
282
+ return 'failure' if %w[failure error].freeze.include?(branch_status)
283
+ return 'backlogged' if backlogged?(backlog_leniency_factor:)
284
+
279
285
  'success'
280
286
  end
281
287
 
@@ -286,13 +292,14 @@ module Shipit
286
292
  def branch_status
287
293
  undeployed_commits.each do |commit|
288
294
  state = commit.status.simple_state
289
- return state unless %w(pending unknown missing).freeze.include?(state)
295
+ return state unless %w[pending unknown missing].freeze.include?(state)
290
296
  end
291
297
  'pending'
292
298
  end
293
299
 
294
300
  def status
295
301
  return :deploying if active_task?
302
+
296
303
  :default
297
304
  end
298
305
 
@@ -309,8 +316,8 @@ module Shipit
309
316
  next if commits_to_lock.empty?
310
317
 
311
318
  affected_rows += commits
312
- .where(id: commits_to_lock.map(&:id).uniq)
313
- .lock_all(revert.author)
319
+ .where(id: commits_to_lock.map(&:id).uniq)
320
+ .lock_all(revert.author)
314
321
  end
315
322
 
316
323
  touch if affected_rows > 1
@@ -392,13 +399,14 @@ module Shipit
392
399
  end
393
400
 
394
401
  def acquire_git_cache_lock(timeout: 15, &block)
395
- @git_cache_lock ||= Flock.new(git_path.to_s + '.lock')
396
- @git_cache_lock.lock(timeout: timeout, &block)
402
+ @git_cache_lock ||= Flock.new("#{git_path}.lock")
403
+ @git_cache_lock.lock(timeout:, &block)
397
404
  end
398
405
 
399
406
  def clear_git_cache!
400
407
  tmp_path = "#{git_path}-#{SecureRandom.hex}"
401
408
  return unless git_path.exist?
409
+
402
410
  acquire_git_cache_lock do
403
411
  git_path.rename(tmp_path)
404
412
  end
@@ -438,9 +446,7 @@ module Shipit
438
446
 
439
447
  def refresh_repository!
440
448
  resource = github_api.repo(github_repo_name)
441
- if resource.try(:message) == 'Moved Permanently'
442
- resource = github_api.get(resource.url)
443
- end
449
+ resource = github_api.get(resource.url) if resource.try(:message) == 'Moved Permanently'
444
450
  repository.update!(owner: resource.owner.login, name: resource.name)
445
451
  end
446
452
 
@@ -450,6 +456,7 @@ module Shipit
450
456
 
451
457
  def active_task
452
458
  return @active_task if defined?(@active_task)
459
+
453
460
  @active_task ||= tasks.current
454
461
  end
455
462
 
@@ -496,7 +503,7 @@ module Shipit
496
503
  env = stack.cached_deploy_spec.default_deploy_env
497
504
  current_user = Shipit::CommandLineUser.new
498
505
 
499
- stack.trigger_deploy(until_commit, current_user, env: env, force: true, run_now: true)
506
+ stack.trigger_deploy(until_commit, current_user, env:, force: true, run_now: true)
500
507
  end
501
508
 
502
509
  def self.from_param!(param)
@@ -505,16 +512,16 @@ module Shipit
505
512
  .where(
506
513
  repositories: {
507
514
  owner: repo_owner.downcase,
508
- name: repo_name.downcase,
515
+ name: repo_name.downcase
509
516
  },
510
- environment: environment,
517
+ environment:
511
518
  ).first!
512
519
  end
513
520
 
514
521
  delegate :plugins, :task_definitions, :hidden_statuses, :required_statuses, :soft_failing_statuses,
515
- :blocking_statuses, :deploy_variables, :filter_task_envs, :filter_deploy_envs,
516
- :maximum_commits_per_deploy, :pause_between_deploys, :retries_on_deploy, :retries_on_rollback,
517
- to: :cached_deploy_spec
522
+ :blocking_statuses, :deploy_variables, :filter_task_envs, :filter_deploy_envs,
523
+ :maximum_commits_per_deploy, :pause_between_deploys, :retries_on_deploy, :retries_on_rollback,
524
+ to: :cached_deploy_spec
518
525
 
519
526
  def monitoring?
520
527
  monitoring.present?
@@ -539,16 +546,16 @@ module Shipit
539
546
  end
540
547
 
541
548
  def update_latest_deployed_ref
542
- if Shipit.update_latest_deployed_ref
543
- UpdateGithubLastDeployedRefJob.perform_later(self)
544
- end
549
+ return unless Shipit.update_latest_deployed_ref
550
+
551
+ UpdateGithubLastDeployedRefJob.perform_later(self)
545
552
  end
546
553
 
547
554
  def broadcast_update
548
555
  Pubsubstub.publish(
549
556
  "stack.#{id}",
550
- { id: id, updated_at: updated_at }.to_json,
551
- name: 'update',
557
+ { id:, updated_at: }.to_json,
558
+ name: 'update'
552
559
  )
553
560
  end
554
561
 
@@ -620,14 +627,18 @@ module Shipit
620
627
  return unless previous_changes.include?('lock_reason')
621
628
 
622
629
  lock_details = if previous_changes['lock_reason'].last.blank?
623
- { from: previous_changes['locked_since'].first, until: Time.zone.now }
624
- end
630
+ { from: previous_changes['locked_since'].first, until: Time.zone.now }
631
+ end
625
632
 
626
- Hook.emit(:lock, self, locked: locked?, lock_details: lock_details, stack: self)
633
+ Hook.emit(:lock, self, locked: locked?, lock_details:, stack: self)
627
634
  end
628
635
 
629
636
  private
630
637
 
638
+ def deployable_commits(commits)
639
+ commits.to_a.reverse.find(&:deployable?)
640
+ end
641
+
631
642
  def clear_cache
632
643
  remove_instance_variable(:@active_task) if defined?(@active_task)
633
644
  end
@@ -654,9 +665,9 @@ module Shipit
654
665
  end
655
666
 
656
667
  def schedule_merges_if_necessary
657
- if lock_reason_previously_changed? && lock_reason.blank?
658
- schedule_merges
659
- end
668
+ return unless lock_reason_previously_changed? && lock_reason.blank?
669
+
670
+ schedule_merges
660
671
  end
661
672
 
662
673
  def emit_added_hooks
@@ -664,7 +675,7 @@ module Shipit
664
675
  end
665
676
 
666
677
  def emit_updated_hooks
667
- changed = !(previous_changes.keys - %w(updated_at)).empty?
678
+ changed = !(previous_changes.keys - %w[updated_at]).empty?
668
679
  Hook.emit(:stack, self, action: :updated, stack: self) if changed
669
680
  end
670
681
 
@@ -673,7 +684,7 @@ module Shipit
673
684
  end
674
685
 
675
686
  def emit_merge_status_hooks
676
- Hook.emit(:merge_status, self, merge_status: merge_status, stack: self)
687
+ Hook.emit(:merge_status, self, merge_status:, stack: self)
677
688
  end
678
689
 
679
690
  def ci_enabled_cache_key
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class Status
4
5
  module Common
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class Status
4
5
  class Group
@@ -31,7 +32,7 @@ module Shipit
31
32
  end
32
33
 
33
34
  delegate :pending?, :success?, :error?, :failure?, :unknown?, :missing?, :state, :simple_state,
34
- to: :significant_status
35
+ to: :significant_status
35
36
  delegate :each, :size, :map, to: :statuses
36
37
  delegate :required_statuses, to: :commit
37
38
 
@@ -43,8 +44,7 @@ module Shipit
43
44
  "#{success_count} / #{statuses.count} checks OK"
44
45
  end
45
46
 
46
- def target_url
47
- end
47
+ def target_url; end
48
48
 
49
49
  def to_partial_path
50
50
  'statuses/group'
@@ -75,8 +75,10 @@ module Shipit
75
75
  def select_significant_status(statuses)
76
76
  statuses = reject_allowed_to_fail(statuses)
77
77
  return Status::Unknown.new(commit) if statuses.empty?
78
+
78
79
  non_success_statuses = statuses.reject(&:success?)
79
80
  return statuses.first if non_success_statuses.empty?
81
+
80
82
  non_success_statuses.reject(&:pending?).first || non_success_statuses.first || Status::Unknown.new(commit)
81
83
  end
82
84
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class Status
4
5
  class Missing
@@ -24,7 +25,7 @@ module Shipit
24
25
  end
25
26
 
26
27
  def description
27
- I18n.t('missing_status.description', context: context)
28
+ I18n.t('missing_status.description', context:)
28
29
  end
29
30
 
30
31
  def to_partial_path
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class Status
4
5
  class Unknown
@@ -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,17 +1,22 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class Task < Record
4
5
  include DeferredTouch
5
6
 
6
- ConcurrentTaskRunning = Class.new(StandardError)
7
+ class ConcurrentTaskRunning < StandardError
8
+ def message
9
+ "A task is already running."
10
+ end
11
+ end
7
12
 
8
13
  PRESENCE_CHECK_TIMEOUT = 30
9
- ACTIVE_STATUSES = %w(pending running aborting).freeze
10
- COMPLETED_STATUSES = %w(success flapping faulty validating).freeze
11
- 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
12
17
  OUTPUT_SIZE_LIMIT = 16.megabytes # A MySQL mediumblob
13
18
  HUMAN_READABLE_OUTPUT_LIMIT = ActionController::Base.helpers.number_to_human_size(OUTPUT_SIZE_LIMIT)
14
- 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
15
20
 
16
21
  attr_accessor :pid
17
22
 
@@ -31,6 +36,7 @@ module Shipit
31
36
  class << self
32
37
  def dump(hash)
33
38
  raise TypeError, "Task#env should be a Hash[String => String]" unless hash.is_a?(Hash)
39
+
34
40
  hash = hash.to_h.stringify_keys
35
41
  hash.transform_values! do |value|
36
42
  case value
@@ -45,7 +51,7 @@ module Shipit
45
51
  end
46
52
 
47
53
  def load(hash)
48
- hash&.to_h || {} # cast back to a real hash
54
+ hash.to_h # cast back to a real hash
49
55
  end
50
56
 
51
57
  def new
@@ -54,8 +60,8 @@ module Shipit
54
60
  end
55
61
  end
56
62
 
57
- serialize :definition, TaskDefinition
58
- serialize :env, Shipit.serialized_column(:env, coder: EnvHash)
63
+ serialize :definition, coder: TaskDefinition
64
+ serialize :env, coder: Shipit.serialized_column(:env, coder: EnvHash)
59
65
 
60
66
  scope :success, -> { where(status: 'success') }
61
67
  scope :completed, -> { where(status: COMPLETED_STATUSES) }
@@ -100,11 +106,11 @@ module Shipit
100
106
  task.ended_at ||= Time.now.utc
101
107
  end
102
108
 
103
- after_transition any => %i(success failed error timedout) do |task|
109
+ after_transition any => %i[success failed error timedout] do |task|
104
110
  task.async_refresh_deployed_revision
105
111
  end
106
112
 
107
- after_transition any => %i(aborted success failed error timedout) do |task|
113
+ after_transition any => %i[aborted success failed error timedout] do |task|
108
114
  task.schedule_rollup_chunks
109
115
  end
110
116
 
@@ -116,7 +122,7 @@ module Shipit
116
122
  task.async_update_estimated_deploy_duration
117
123
  end
118
124
 
119
- after_transition any => %i(failed error timedout) do |task|
125
+ after_transition any => %i[failed error timedout] do |task|
120
126
  task.retry_if_necessary
121
127
  end
122
128
 
@@ -125,19 +131,19 @@ module Shipit
125
131
  end
126
132
 
127
133
  event :failure do
128
- transition %i(running flapping) => :failed
134
+ transition %i[running flapping] => :failed
129
135
  end
130
136
 
131
137
  event :complete do
132
- transition %i(running flapping validating faulty) => :success
138
+ transition %i[running flapping validating faulty] => :success
133
139
  end
134
140
 
135
141
  event :enter_validation do
136
- transition %i(running flapping) => :validating
142
+ transition %i[running flapping] => :validating
137
143
  end
138
144
 
139
145
  event :mark_faulty do
140
- transition %i(validating success) => :faulty
146
+ transition %i[validating success] => :faulty
141
147
  end
142
148
 
143
149
  event :error do
@@ -149,7 +155,7 @@ module Shipit
149
155
  end
150
156
 
151
157
  event :aborting do
152
- transition all - %i(aborted) => :aborting
158
+ transition all - %i[aborted] => :aborting
153
159
  end
154
160
 
155
161
  event :aborted do
@@ -157,7 +163,7 @@ module Shipit
157
163
  end
158
164
 
159
165
  event :flap do
160
- transition %i(failed error timedout success) => :flapping
166
+ transition %i[failed error timedout success] => :flapping
161
167
  end
162
168
 
163
169
  state :pending
@@ -202,7 +208,7 @@ module Shipit
202
208
  end
203
209
 
204
210
  delegate :acquire_git_cache_lock, :async_refresh_deployed_revision, :async_update_estimated_deploy_duration,
205
- to: :stack
211
+ to: :stack
206
212
 
207
213
  delegate :checklist, to: :definition
208
214
 
@@ -215,16 +221,18 @@ module Shipit
215
221
  end
216
222
 
217
223
  def spec
218
- @spec ||= DeploySpec::FileSystem.new(working_directory, stack.environment)
224
+ @spec ||= DeploySpec::FileSystem.new(working_directory, stack)
219
225
  end
220
226
 
221
227
  def enqueue
222
228
  raise "only persisted jobs can be enqueued" unless persisted?
229
+
223
230
  PerformTaskJob.perform_later(self)
224
231
  end
225
232
 
226
233
  def run_now!
227
234
  raise "only persisted jobs can be run" unless persisted?
235
+
228
236
  PerformTaskJob.perform_now(self)
229
237
  end
230
238
 
@@ -346,10 +354,10 @@ module Shipit
346
354
  end
347
355
  end
348
356
 
349
- 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)
350
358
  update!(
351
- rollback_once_aborted: rollback_once_aborted,
352
- rollback_once_aborted_to: rollback_once_aborted_to,
359
+ rollback_once_aborted:,
360
+ rollback_once_aborted_to:,
353
361
  aborted_by_id: aborted_by.id
354
362
  )
355
363
 
@@ -379,12 +387,13 @@ module Shipit
379
387
 
380
388
  def emit_hooks_if_status_changed
381
389
  return unless @status_changed
390
+
382
391
  @status_changed = nil
383
392
  emit_hooks
384
393
  end
385
394
 
386
395
  def emit_hooks
387
- Hook.emit(hook_event, stack, hook_event => self, status: status, stack: stack)
396
+ Hook.emit(hook_event, stack, hook_event => self, status:, stack:)
388
397
  end
389
398
 
390
399
  def hook_event
@@ -423,13 +432,13 @@ module Shipit
423
432
  5.minutes.ago
424
433
  end
425
434
 
426
- ZOMBIE_STATES = %w(running aborting).freeze
435
+ ZOMBIE_STATES = %w[running aborting].freeze
427
436
  private_constant :ZOMBIE_STATES
428
437
  def self.zombies
429
438
  where(status: ZOMBIE_STATES)
430
439
  .where(
431
440
  "created_at <= :recently",
432
- recently: recently_created_at,
441
+ recently: recently_created_at
433
442
  )
434
443
  .reject(&:alive?)
435
444
  end
@@ -437,13 +446,13 @@ module Shipit
437
446
  def retry_if_necessary
438
447
  return unless retries_configured? && !stack.reload.locked?
439
448
 
440
- if retry_attempt < max_retries
441
- retry_task = duplicate_task
442
- retry_task.retry_attempt = duplicate_task.retry_attempt + 1
443
- retry_task.save!
449
+ return unless retry_attempt < max_retries
444
450
 
445
- retry_task.enqueue
446
- 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
447
456
  end
448
457
 
449
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