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
@@ -55,7 +55,7 @@ module Shipit
55
55
  def stack
56
56
  @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 pull_request
@@ -13,7 +13,7 @@ module Shipit
13
13
  end
14
14
 
15
15
  def stack
16
- @stack ||= scope.find_by(environment: environment)
16
+ @stack ||= scope.find_by(environment:)
17
17
  end
18
18
 
19
19
  def find_or_create!
@@ -87,9 +87,9 @@ module Shipit
87
87
  def stack_attributes
88
88
  {
89
89
  branch: params.pull_request.head.ref,
90
- environment: environment,
90
+ environment:,
91
91
  ignore_ci: false,
92
- continuous_deployment: false,
92
+ continuous_deployment: false
93
93
  }
94
94
  end
95
95
 
@@ -65,7 +65,7 @@ module Shipit
65
65
  def stack
66
66
  @stack ||=
67
67
  Shipit::Webhooks::Handlers::PullRequest::ReviewStackAdapter
68
- .new(params, scope: repository.review_stacks)
68
+ .new(params, scope: repository.review_stacks)
69
69
  end
70
70
 
71
71
  def pull_request
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module Webhooks
4
5
  module Handlers
@@ -9,7 +10,7 @@ module Shipit
9
10
  def process
10
11
  stacks
11
12
  .not_archived
12
- .where(branch: branch)
13
+ .where(branch:)
13
14
  .find_each(&:sync_github)
14
15
  end
15
16
 
@@ -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
  class << self
@@ -13,11 +14,11 @@ module Shipit
13
14
  Handlers::PullRequest::AssignedHandler,
14
15
  Handlers::PullRequest::LabeledHandler,
15
16
  Handlers::PullRequest::UnlabeledHandler,
16
- Handlers::PullRequest::LabelCapturingHandler,
17
+ Handlers::PullRequest::LabelCapturingHandler
17
18
  ],
18
19
  'status' => [Handlers::StatusHandler],
19
20
  'membership' => [Handlers::MembershipHandler],
20
- 'check_suite' => [Handlers::CheckSuiteHandler],
21
+ 'check_suite' => [Handlers::CheckSuiteHandler]
21
22
  }
22
23
  end
23
24
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module ConditionalAttributes
4
5
  extend ActiveSupport::Concern
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class AnonymousUserSerializer < UserSerializer
4
5
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class CommandLineUserSerializer < UserSerializer
4
5
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class CommitSerializer < ShortCommitSerializer
4
5
  include GithubUrlHelper
@@ -24,7 +25,7 @@ module Shipit
24
25
  def pull_request
25
26
  {
26
27
  number: object.pull_request_number,
27
- html_url: github_pull_request_url(object),
28
+ html_url: github_pull_request_url(object)
28
29
  }
29
30
  end
30
31
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class DeploySerializer < TaskSerializer
4
5
  include GithubUrlHelper
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class HookSerializer < ActiveModel::Serializer
4
5
  include ConditionalAttributes
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class MergeRequestSerializer < ActiveModel::Serializer
4
5
  include GithubUrlHelper
@@ -8,7 +9,7 @@ module Shipit
8
9
  has_one :head, serializer: ShortCommitSerializer
9
10
 
10
11
  attributes :id, :number, :title, :github_id, :additions, :deletions, :state, :merge_status, :mergeable,
11
- :merge_requested_at, :rejection_reason, :html_url, :branch, :base_ref
12
+ :merge_requested_at, :rejection_reason, :html_url, :branch, :base_ref
12
13
 
13
14
  def html_url
14
15
  github_pull_request_url(object)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class RollbackSerializer < DeploySerializer
4
5
  def type
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class ShortCommitSerializer < ActiveModel::Serializer
4
5
  attributes :sha, :message
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class StackSerializer < ActiveModel::Serializer
4
5
  include ConditionalAttributes
@@ -6,9 +7,9 @@ module Shipit
6
7
  has_one :lock_author
7
8
 
8
9
  attributes :id, :repo_owner, :repo_name, :environment, :html_url, :url, :tasks_url, :deploy_url,
9
- :merge_requests_url, :deploy_spec, :undeployed_commits_count, :is_locked, :lock_reason, :continuous_deployment,
10
- :created_at, :updated_at, :locked_since, :last_deployed_at, :branch, :merge_queue_enabled, :is_archived,
11
- :archived_since, :ignore_ci
10
+ :merge_requests_url, :deploy_spec, :undeployed_commits_count, :is_locked, :lock_reason,
11
+ :continuous_deployment, :created_at, :updated_at, :locked_since, :last_deployed_at, :branch,
12
+ :merge_queue_enabled, :is_archived, :archived_since, :ignore_ci
12
13
 
13
14
  def url
14
15
  api_stack_url(object)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class TailTaskSerializer < ActiveModel::Serializer
4
5
  include ChunksHelper
@@ -8,6 +9,7 @@ module Shipit
8
9
 
9
10
  def url
10
11
  return @url if defined? @url
12
+
11
13
  @url = next_chunks_url(task, last_byte: next_offset)
12
14
  end
13
15
 
@@ -29,7 +31,7 @@ module Shipit
29
31
 
30
32
  private
31
33
 
32
- alias_method :task, :object
34
+ alias task object
33
35
  delegate :stack, to: :object
34
36
 
35
37
  def next_offset
@@ -42,6 +44,7 @@ module Shipit
42
44
 
43
45
  def rollback
44
46
  return @rollback if defined? @rollback
47
+
45
48
  @rollback = stack.rollbacks.where(parent_id: task.id).last
46
49
  end
47
50
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class TaskSerializer < ActiveModel::Serializer
4
5
  include ConditionalAttributes
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class UserSerializer < ActiveModel::Serializer
4
5
  attributes :id, :name, :email, :login, :avatar_url, :created_at, :updated_at, :github_id, :anonymous
@@ -1,8 +1,9 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class AsciiOnlyValidator < ActiveModel::EachValidator
3
4
  def validate_each(record, attribute, value)
4
- if value && !value.ascii_only?
5
- record.errors.add(attribute, :ascii)
6
- end
5
+ return unless value && !value.ascii_only?
6
+
7
+ record.errors.add(attribute, :ascii)
7
8
  end
8
9
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  class SubsetValidator < ActiveModel::EachValidator
3
4
  def validate_each(record, attribute, value)
4
5
  superset = options[:of]
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  # Derived from http://timnew.me/blog/2013/04/07/multiple-project-summary-reporting-standard-cctray-xml-feed/
3
4
  status_map = { 'backlogged' => 'failure', 'locked' => 'failure' }
4
5
  xml.instruct!
@@ -10,6 +11,6 @@ xml.Projects do
10
11
  activity: deploy.running? ? 'Building' : 'Sleeping',
11
12
  lastBuildTime: deploy.ended_at || deploy.started_at || deploy.created_at,
12
13
  lastBuildLabel: deploy.id,
13
- webUrl: stack_url(stack),
14
+ webUrl: stack_url(stack)
14
15
  )
15
16
  end
@@ -0,0 +1,59 @@
1
+ <%= render partial: 'shipit/stacks/header', locals: { stack: @stack } %>
2
+
3
+ <div class="wrapper continuous-delivery-schedule">
4
+ <section>
5
+ <header class="section-header">
6
+ <h2>Continuous Delivery Schedule (Stack #<%= @stack.id %>)</h2>
7
+ </header>
8
+ </section>
9
+ <div class="setting-section">
10
+ <% if @continuous_delivery_schedule.errors.any? %>
11
+ <div class="validation-errors">
12
+ <p>Validation errors prevented your schedule from being saved</p>
13
+ <ul>
14
+ <% @continuous_delivery_schedule.errors.full_messages.each do |full_message| %>
15
+ <li><%= full_message %></li>
16
+ <% end %>
17
+ </ul>
18
+ </div>
19
+ <% end %>
20
+ <%= form_for(@continuous_delivery_schedule, url: stack_continuous_delivery_schedule_path, method: :patch) do |f| %>
21
+ <table class="field-wrapper">
22
+ <tbody>
23
+ <% Shipit::ContinuousDeliverySchedule::DAYS.rotate.each do |day| %>
24
+ <tr>
25
+ <td>
26
+ <%= f.check_box("#{day}_enabled") %>
27
+ </td>
28
+ <td>
29
+ <%= f.label("#{day}_enabled", day.titlecase) %>
30
+ </td>
31
+ <td>
32
+ <%= f.time_field("#{day}_start", include_seconds: false) %>
33
+ </td>
34
+ <td>&rarr;</td>
35
+ <td>
36
+ <%= f.time_field("#{day}_end", include_seconds: false) %>
37
+ </td>
38
+ <td>
39
+ <% if day == "monday" %>
40
+ <button data-action="copy-to-all" type="button">Copy to all &darr;</button>
41
+ <% end %>
42
+ </td>
43
+ </tr>
44
+ <% end %>
45
+ </tbody>
46
+ </table>
47
+
48
+ <p>
49
+ &#x2139;&#xFE0F;
50
+ All times are in <%= Time.zone.name %>
51
+ (the <a href="https://guides.rubyonrails.org/configuring.html#config-time-zone">default time zone</a>).
52
+ </p>
53
+
54
+ <div class="field-wrapper">
55
+ <%= f.submit("Save", class: "btn") %>
56
+ </div>
57
+ <% end %>
58
+ </div>
59
+ </div>
@@ -17,6 +17,7 @@
17
17
  <div class="field-wrapper">
18
18
  <%= f.check_box :continuous_deployment %>
19
19
  <%= f.label :continuous_deployment, 'Enable continuous deployment' %>
20
+ (<%= link_to("Edit schedule", stack_continuous_delivery_schedule_path) %>)
20
21
  </div>
21
22
 
22
23
  <div class="field-wrapper">
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  ActiveSupport::Inflector.inflections(:en) do |inflect|
3
4
  inflect.acronym('CCMenu')
4
5
  end
@@ -81,6 +81,7 @@ en:
81
81
  messages:
82
82
  subset: "is not a strict subset of %{of}"
83
83
  ascii: "contains non-ASCII characters"
84
+ must_be_after_start: "must be after start (%{start})"
84
85
  deployment_description:
85
86
  deploy:
86
87
  in_progress: "%{author} triggered the deploy of %{stack} to %{sha}"
data/config/routes.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  Shipit::Engine.routes.draw do
3
4
  stack_id_format = %r{[^/]+/[^/]+/[^/]+}
4
5
  repository_id_format = %r{[^/]+/[^/]+}
@@ -15,7 +16,7 @@ Shipit::Engine.routes.draw do
15
16
  # API
16
17
  namespace :api do
17
18
  root to: 'base#index'
18
- resources :stacks, only: %i(index create)
19
+ resources :stacks, only: %i[index create]
19
20
  scope '/stacks/*id', id: stack_id_format, as: :stack do
20
21
  get '/' => 'stacks#show'
21
22
  delete '/' => 'stacks#destroy'
@@ -25,24 +26,24 @@ Shipit::Engine.routes.draw do
25
26
 
26
27
  scope '/stacks/*stack_id', stack_id: stack_id_format, as: :stack do
27
28
  get '/ccmenu' => 'ccmenu#show', as: :ccmenu
28
- resource :lock, only: %i(create update destroy)
29
- resources :tasks, only: %i(index show) do
29
+ resource :lock, only: %i[create update destroy]
30
+ resources :tasks, only: %i[index show] do
30
31
  resource :output, only: :show
31
32
  member do
32
33
  put :abort
33
34
  end
34
35
  end
35
- resources :deploys, only: %i(index create) do
36
- resources :release_statuses, only: %i(create)
36
+ resources :deploys, only: %i[index create] do
37
+ resources :release_statuses, only: %i[create]
37
38
  end
38
- resources :rollbacks, only: %i(create)
39
- resources :commits, only: %i(index)
40
- resources :merge_requests, only: %i(index show update destroy)
39
+ resources :rollbacks, only: %i[create]
40
+ resources :commits, only: %i[index]
41
+ resources :merge_requests, only: %i[index show update destroy]
41
42
  post '/task/:task_name' => 'tasks#trigger', as: :trigger_task
42
- resources :hooks, only: %i(index create show update destroy)
43
+ resources :hooks, only: %i[index create show update destroy]
43
44
  end
44
45
 
45
- resources :hooks, only: %i(index create show update destroy)
46
+ resources :hooks, only: %i[index create show update destroy]
46
47
  end
47
48
 
48
49
  scope '/ccmenu/*stack_id', stack_id: stack_id_format, as: :ccmenu_url do
@@ -57,7 +58,7 @@ Shipit::Engine.routes.draw do
57
58
  # Humans
58
59
  resources :api_clients
59
60
 
60
- resources :repositories, only: %i(new index create)
61
+ resources :repositories, only: %i[new index create]
61
62
  scope '/repositories/*id', id: repository_id_format, as: :repository do
62
63
  get '/' => 'repositories#show'
63
64
  patch '/' => 'repositories#update'
@@ -73,7 +74,7 @@ Shipit::Engine.routes.draw do
73
74
  get :logout
74
75
  end
75
76
 
76
- resources :stacks, only: %i(new create index)
77
+ resources :stacks, only: %i[new create index]
77
78
  scope '/*id', id: stack_id_format, as: :stack do
78
79
  get '/' => 'stacks#show'
79
80
  patch '/' => 'stacks#update'
@@ -84,6 +85,8 @@ Shipit::Engine.routes.draw do
84
85
  post :refresh, controller: :stacks
85
86
  get :refresh, controller: :stacks # For easier design, sorry :/
86
87
  post :clear_git_cache, controller: :stacks
88
+
89
+ resource :continuous_delivery_schedule, only: %i[show update]
87
90
  end
88
91
 
89
92
  scope '/task/:id', controller: :tasks do
@@ -96,9 +99,9 @@ Shipit::Engine.routes.draw do
96
99
 
97
100
  get '/stats' => 'stats#show', as: :stats
98
101
 
99
- resources :rollbacks, only: %i(create)
100
- resources :commits, only: %i(update)
101
- resources :tasks, only: %i(show) do
102
+ resources :rollbacks, only: %i[create]
103
+ resources :commits, only: %i[update]
104
+ resources :tasks, only: %i[show] do
102
105
  collection do
103
106
  get '' => 'tasks#index', as: :index
104
107
  get ':definition_id/new' => 'tasks#new', as: :new
@@ -111,17 +114,17 @@ Shipit::Engine.routes.draw do
111
114
  end
112
115
  end
113
116
 
114
- resources :deploys, only: %i(show create) do
117
+ resources :deploys, only: %i[show create] do
115
118
  get ':sha', sha: sha_format, on: :new, action: :new, as: ''
116
119
  member do
117
120
  get :rollback
118
121
  get :revert
119
122
  end
120
123
 
121
- resources :release_statuses, only: %i(create)
124
+ resources :release_statuses, only: %i[create]
122
125
  end
123
126
 
124
- resources :merge_requests, only: %i(index destroy create)
127
+ resources :merge_requests, only: %i[index destroy create]
125
128
  end
126
129
  get '/stacks/:id' => 'stacks#lookup'
127
130
 
@@ -0,0 +1,13 @@
1
+ class AddContinuousDeliverySchedules < ActiveRecord::Migration[7.1]
2
+ def change
3
+ create_table(:continuous_delivery_schedules) do |t|
4
+ t.references(:stack, null: false, index: { unique: true })
5
+ %w[sunday monday tuesday wednesday thursday friday saturday].each do |day|
6
+ t.boolean("#{day}_enabled", null: false, default: true)
7
+ t.time("#{day}_start", null: false, default: "00:00")
8
+ t.time("#{day}_end", null: false, default: "23:59")
9
+ end
10
+ t.timestamps
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ class EmbiggenGithubIds < ActiveRecord::Migration[7.2]
2
+ def change
3
+ change_column(:commit_deployments, :github_id, :bigint)
4
+ change_column(:github_hooks, :github_id, :bigint)
5
+ change_column(:teams, :github_id, :bigint)
6
+ change_column(:users, :github_id, :bigint)
7
+ end
8
+ end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module CastValue
4
5
  def to_boolean(value)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'pty'
3
4
  require 'shellwords'
4
5
  require 'fileutils'
@@ -27,9 +28,9 @@ module Shipit
27
28
 
28
29
  attr_reader :out, :chdir, :env, :args, :pid, :timeout
29
30
 
30
- def initialize(*args, default_timeout: Shipit.default_inactivity_timeout, env: {}, chdir:)
31
+ def initialize(*args, chdir:, default_timeout: Shipit.default_inactivity_timeout, env: {})
31
32
  @args, options = parse_arguments(args)
32
- @timeout = options['timeout'] || options[:timeout] || default_timeout
33
+ @timeout = parse_timeout(options['timeout'] || options[:timeout]) || default_timeout
33
34
  @env = env.transform_values { |v| v&.to_s }
34
35
  @chdir = chdir.to_s
35
36
  @timed_out = false
@@ -83,6 +84,7 @@ module Shipit
83
84
 
84
85
  def start(&block)
85
86
  return if @started
87
+
86
88
  @control_block = block
87
89
  @out = @pid = nil
88
90
  FileUtils.mkdir_p(@chdir)
@@ -106,10 +108,10 @@ module Shipit
106
108
  start
107
109
  begin
108
110
  read_stream(@out, &block)
109
- rescue TimedOut => error
110
- yield red("No output received in the last #{timeout} seconds.") + "\n"
111
+ rescue TimedOut => e
112
+ yield "#{red("No output received in the last #{timeout} seconds.")}\n"
111
113
  terminate!(&block)
112
- raise error
114
+ raise e
113
115
  rescue Errno::EIO # Somewhat expected on Linux: http://stackoverflow.com/a/10306782
114
116
  end
115
117
 
@@ -125,6 +127,7 @@ module Shipit
125
127
  def stream!(&block)
126
128
  stream(&block)
127
129
  raise Failed.new(exit_message, code) unless success?
130
+
128
131
  self
129
132
  end
130
133
 
@@ -173,7 +176,7 @@ module Shipit
173
176
  ensure
174
177
  begin
175
178
  read_stream(@out, &block)
176
- rescue
179
+ rescue StandardError
177
180
  end
178
181
  end
179
182
 
@@ -187,9 +190,8 @@ module Shipit
187
190
  rescue TimedOut
188
191
  rescue Errno::EIO # EIO is somewhat expected on Linux: http://stackoverflow.com/a/10306782
189
192
  # If we try to read the stream right after sending a signal, we often get an Errno::EIO.
190
- if reap_child!(block: false)
191
- return true
192
- end
193
+ return true if reap_child!(block: false)
194
+
193
195
  # If we let the child a little bit of time, it solves it.
194
196
  retry_count -= 1
195
197
  if retry_count > 0
@@ -206,6 +208,22 @@ module Shipit
206
208
  Process.kill(sig, @pid)
207
209
  end
208
210
 
211
+ def parse_timeout(timeout)
212
+ case timeout
213
+ when String
214
+ begin
215
+ Duration.parse(timeout).to_i
216
+ rescue Duration::ParseError
217
+ # If given garbage we fallback to the default.
218
+ # It's not ideal but we don't have a good way to notify about
219
+ # syntax errors.
220
+ nil
221
+ end
222
+ else
223
+ timeout
224
+ end
225
+ end
226
+
209
227
  def parse_arguments(arguments)
210
228
  options = {}
211
229
  args = arguments.flatten.map do |argument|
@@ -217,6 +235,7 @@ module Shipit
217
235
  argument
218
236
  end
219
237
  end
238
+
220
239
  [args.map(&:to_s), options]
221
240
  end
222
241
 
@@ -235,6 +254,7 @@ module Shipit
235
254
  def reap_child!(block: true)
236
255
  return @status if @status
237
256
  return unless running? # Command was never started e.g. permission denied, not found etc
257
+
238
258
  if block
239
259
  _, @status = Process.waitpid2(@pid)
240
260
  elsif res = Process.waitpid2(@pid, Process::WNOHANG)
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class Commands
4
5
  class << self
@@ -7,12 +8,13 @@ module Shipit
7
8
  end
8
9
 
9
10
  def git_version
10
- @git_version ||= parse_git_version(%x(git --version))
11
+ @git_version ||= parse_git_version(`git --version`)
11
12
  end
12
13
 
13
14
  def parse_git_version(raw_git_version)
14
15
  match_info = raw_git_version.match(/(\d+\.\d+\.\d+)/)
15
16
  raise 'git command not found' unless match_info
17
+
16
18
  Gem::Version.new(match_info[1])
17
19
  end
18
20
  end
@@ -36,7 +38,7 @@ module Shipit
36
38
  @base_env ||= Shipit.env.merge(
37
39
  'GITHUB_DOMAIN' => github.domain,
38
40
  'GITHUB_TOKEN' => github.token,
39
- 'GIT_ASKPASS' => Shipit::Engine.root.join('lib', 'snippets', 'git-askpass').realpath.to_s,
41
+ 'GIT_ASKPASS' => Shipit::Engine.root.join('lib', 'snippets', 'git-askpass').realpath.to_s
40
42
  )
41
43
  end
42
44
 
@@ -1,15 +1,18 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  module CSVSerializer
4
5
  extend self
5
6
 
6
7
  def load(payload)
7
8
  return [] if payload.blank?
9
+
8
10
  payload.split(',')
9
11
  end
10
12
 
11
13
  def dump(array)
12
14
  return nil if array.blank?
15
+
13
16
  Array.wrap(array).join(',')
14
17
  end
15
18
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class DeployCommands < TaskCommands
4
5
  def steps
@@ -10,7 +11,7 @@ module Shipit
10
11
  super.merge(
11
12
  'SHA' => commit.sha,
12
13
  'REVISION' => commit.sha,
13
- 'DIFF_LINK' => diff_url,
14
+ 'DIFF_LINK' => diff_url
14
15
  )
15
16
  end
16
17