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
@@ -9,7 +9,7 @@
9
9
  <% if variable.select %>
10
10
  <%= field.select variable.name, options_for_select([["Please select...", { disabled: "disabled" }]] + variable.select, variable.default || "Please select...") %>
11
11
  <% else %>
12
- <%= field.text_field variable.name, value: variable.default %>
12
+ <%= field.text_field variable.name, value: params[variable.name].presence || variable.default %>
13
13
  <% end %>
14
14
  <%= field.label variable.name, variable.title || variable.name %>
15
15
  </p>
@@ -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>
@@ -15,7 +15,7 @@
15
15
  </h4>
16
16
  <span class="status-meta">
17
17
  <%= link_to @stack.to_param, stack_url(@stack), target: '_blank', rel: 'noopener' %>
18
- <strong>master branch is failing!</strong>
18
+ <strong>main branch is failing!</strong>
19
19
  </span>
20
20
  <%= render 'commit_count_warning' if display_commit_count_warning?(params[:commits].to_i) %>
21
21
  </div>
@@ -22,7 +22,7 @@
22
22
 
23
23
  <p id="github_app">
24
24
  Config:
25
- <% if Rails.application.secrets.github.present? %>
25
+ <% if Rails.application.credentials.github.present? %>
26
26
  Success!
27
27
  <% else %>
28
28
  <span class="missing">
@@ -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
 
@@ -1,7 +1,7 @@
1
1
  host: 'localhost:3000'
2
2
  redis_url: 'redis://127.0.0.1:6379/0'
3
3
 
4
- # For creating an app see: https://github.com/Shopify/shipit-engine/blob/master/docs/setup.md#creating-the-github-app
4
+ # For creating an app see: https://github.com/Shopify/shipit-engine/blob/main/docs/setup.md#creating-the-github-app
5
5
  # Can be obtained there: https://github.com/settings/apps
6
6
  # Set the "Authorization callback URL" as `<host>/github/auth/github/callback`
7
7
 
@@ -1,7 +1,7 @@
1
1
  host: 'shipit-engine.myshopify.io'
2
2
  redis_url: 'redis://shipit-engine.railgun:6379'
3
3
 
4
- # For creating an app see: https://github.com/Shopify/shipit-engine/blob/master/docs/setup.md#creating-the-github-app
4
+ # For creating an app see: https://github.com/Shopify/shipit-engine/blob/main/docs/setup.md#creating-the-github-app
5
5
 
6
6
  github:
7
7
  somegithuborg:
@@ -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
 
data/lib/shipit/engine.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class Engine < ::Rails::Engine
4
5
  isolate_namespace Shipit
@@ -11,7 +12,7 @@ module Shipit
11
12
  # But if AR Encryption is already configured, we just use that
12
13
  app.credentials[:active_record_encryption] = {
13
14
  primary_key: Shipit.user_access_tokens_key,
14
- key_derivation_salt: Digest::SHA256.digest("salt:".b + Shipit.user_access_tokens_key),
15
+ key_derivation_salt: Digest::SHA256.digest("salt:".b + Shipit.user_access_tokens_key)
15
16
  }
16
17
  end
17
18
  end
@@ -21,19 +22,19 @@ module Shipit
21
22
  Shipit::Engine.routes.default_url_options[:host] = Shipit.host
22
23
  Pubsubstub.redis_url = Shipit.redis_url.to_s
23
24
 
24
- Rails.application.secrets.deep_symbolize_keys!
25
+ Rails.application.credentials.deep_symbolize_keys!
25
26
 
26
27
  app.config.assets.paths << Emoji.images_path
27
- app.config.assets.precompile += %w(
28
+ app.config.assets.precompile += %w[
28
29
  favicon.ico
29
30
  task.js
30
31
  shipit.js
31
32
  shipit.css
32
33
  merge_status.js
33
34
  merge_status.css
34
- )
35
+ ]
35
36
  app.config.assets.precompile << proc do |path|
36
- path =~ %r{\Aplugins/[\-\w]+\.(js|css)\Z}
37
+ path =~ %r{\Aplugins/[-\w]+\.(js|css)\Z}
37
38
  end
38
39
  app.config.assets.precompile << proc do |path|
39
40
  path.end_with?('.svg') || (path.start_with?('emoji/') && path.end_with?('.png'))
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class EnvironmentVariables
4
5
  NotPermitted = Class.new(StandardError)
@@ -12,6 +13,7 @@ module Shipit
12
13
  def permit(variable_definitions)
13
14
  return {} unless @env
14
15
  raise "A whitelist is required to sanitize environment variables" unless variable_definitions
16
+
15
17
  sanitize_env_vars(variable_definitions)
16
18
  end
17
19
 
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class FirstParentCommitsIterator < OctokitIterator
4
5
  def each
@@ -9,9 +10,7 @@ module Shipit
9
10
  next
10
11
  end
11
12
 
12
- if last_ancestor.parents.empty? || last_ancestor.parents.first.sha == commit.sha
13
- yield last_ancestor = commit
14
- end
13
+ yield last_ancestor = commit if last_ancestor.parents.empty? || last_ancestor.parents.first.sha == commit.sha
15
14
  end
16
15
  end
17
16
  end
data/lib/shipit/flock.rb CHANGED
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require 'English'
3
4
  require 'timeout'
4
5
  require 'pathname'
@@ -16,19 +17,20 @@ module Shipit
16
17
 
17
18
  def lock(timeout:)
18
19
  return yield if @acquired
20
+
19
21
  path.parent.mkpath
20
22
  path.open('w') do |file|
21
- if retrying(timeout: timeout) { file.flock(File::LOCK_EX | File::LOCK_NB) }
22
- file.write($PROCESS_ID.to_s)
23
- @acquired = true
24
- begin
25
- yield
26
- ensure
27
- @acquired = false
28
- end
29
- else
23
+ unless retrying(timeout:) { file.flock(File::LOCK_EX | File::LOCK_NB) }
30
24
  raise TimeoutError, "Couldn't acquire lock for #{path} in #{timeout} seconds"
31
25
  end
26
+
27
+ file.write($PROCESS_ID.to_s)
28
+ @acquired = true
29
+ begin
30
+ yield
31
+ ensure
32
+ @acquired = false
33
+ end
32
34
  end
33
35
  end
34
36
 
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module Shipit
3
4
  class GitHubApp
4
- include Mutex_m
5
-
6
5
  class Token
7
6
  class << self
8
7
  def from_github(github_response)
@@ -44,6 +43,7 @@ module Shipit
44
43
 
45
44
  def initialize(organization, config)
46
45
  super()
46
+ @mutex = Mutex.new
47
47
  @organization = organization
48
48
  @config = (config || {}).with_indifferent_access
49
49
  @domain = @config[:domain] || DOMAIN
@@ -62,9 +62,7 @@ module Shipit
62
62
 
63
63
  def api
64
64
  client = (Thread.current[:github_client] ||= new_client(access_token: token))
65
- if client.access_token != token
66
- client.access_token = token
67
- end
65
+ client.access_token = token if client.access_token != token
68
66
  client
69
67
  end
70
68
 
@@ -88,7 +86,7 @@ module Shipit
88
86
  return 't0kEn' if Rails.env.test? # TODO: figure out something cleaner
89
87
  return unless private_key && app_id && installation_id
90
88
 
91
- @token = @token.presence || synchronize { @token.presence || fetch_new_token }
89
+ @token = @token.presence || @mutex.synchronize { @token.presence || fetch_new_token }
92
90
  @token.to_s
93
91
  end
94
92
 
@@ -99,15 +97,15 @@ module Shipit
99
97
  Rails.cache.fetch(
100
98
  "github:integration:#{cache_key}access-token",
101
99
  expires_in: GITHUB_TOKEN_RAILS_CACHE_LIFETIME,
102
- race_condition_ttl: 4.minutes,
100
+ race_condition_ttl: 4.minutes
103
101
  ) do
104
102
  response = new_client(bearer_token: authentication_payload).create_app_installation_access_token(
105
- installation_id,
106
- accept: 'application/vnd.github.machine-man-preview+json',
103
+ installation_id
107
104
  )
108
105
  token = Token.from_github(response)
109
106
  raise AuthenticationFailed if token.blank?
110
- Rails.logger.info("Created GitHub access token ending #{token.to_s[-5..-1]}, expires at #{token.expires_at}"\
107
+
108
+ Rails.logger.info("Created GitHub access token ending #{token.to_s[-5..]}, expires at #{token.expires_at}"\
111
109
  " and will be refreshed at #{token&.refresh_at}")
112
110
  token
113
111
  end
@@ -123,14 +121,14 @@ module Shipit
123
121
  options = {
124
122
  site: api_endpoint,
125
123
  authorize_url: url('/login/oauth/authorize'),
126
- token_url: url('/login/oauth/access_token'),
124
+ token_url: url('/login/oauth/access_token')
127
125
  }
128
126
  end
129
127
 
130
128
  [
131
129
  oauth_id,
132
130
  oauth_secret,
133
- client_options: options,
131
+ { client_options: options }
134
132
  ]
135
133
  end
136
134
 
@@ -154,8 +152,8 @@ module Shipit
154
152
  def new_client(options = {})
155
153
  if enterprise?
156
154
  options = options.reverse_merge(
157
- api_endpoint: api_endpoint,
158
- web_endpoint: web_endpoint,
155
+ api_endpoint:,
156
+ web_endpoint:
159
157
  )
160
158
  end
161
159
  client = Octokit::Client.new(options)
@@ -174,7 +172,7 @@ module Shipit
174
172
  shared_cache: false,
175
173
  store: Rails.cache,
176
174
  logger: Rails.logger,
177
- serializer: NullSerializer,
175
+ serializer: NullSerializer
178
176
  )
179
177
  builder.use(GitHubHTTPCacheMiddleware)
180
178
  builder.use(Octokit::Response::RaiseError)
@@ -198,7 +196,7 @@ module Shipit
198
196
  payload = {
199
197
  iat: Time.now.to_i,
200
198
  exp: 10.minutes.from_now.to_i,
201
- iss: app_id,
199
+ iss: app_id
202
200
  }
203
201
  key = OpenSSL::PKey::RSA.new(private_key)
204
202
  JWT.encode(payload, key, 'RS256')