shipit-engine 0.31.0 → 0.35.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 (411) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +17 -4
  3. data/Rakefile +4 -2
  4. data/app/assets/images/magic-solid.svg +1 -0
  5. data/app/assets/javascripts/shipit/repositories_search.js.coffee +60 -0
  6. data/app/assets/javascripts/shipit/{search.js.coffee → stack_search.js.coffee} +0 -0
  7. data/app/assets/stylesheets/_pages/_deploy.scss +2 -3
  8. data/app/assets/stylesheets/_pages/_repositories.scss +148 -0
  9. data/app/assets/stylesheets/_pages/_stacks.scss +19 -3
  10. data/app/assets/stylesheets/merge_status.scss +0 -3
  11. data/app/assets/stylesheets/shipit.scss +1 -0
  12. data/app/controllers/concerns/shipit/active_model_serializers_patch.rb +1 -0
  13. data/app/controllers/concerns/shipit/api/cacheable.rb +1 -0
  14. data/app/controllers/concerns/shipit/api/paginable.rb +3 -2
  15. data/app/controllers/concerns/shipit/api/rendering.rb +5 -4
  16. data/app/controllers/concerns/shipit/authentication.rb +3 -2
  17. data/app/controllers/concerns/shipit/pagination.rb +2 -1
  18. data/app/controllers/shipit/api/base_controller.rb +11 -6
  19. data/app/controllers/shipit/api/ccmenu_controller.rb +2 -1
  20. data/app/controllers/shipit/api/commits_controller.rb +2 -1
  21. data/app/controllers/shipit/api/deploys_controller.rb +6 -3
  22. data/app/controllers/shipit/api/hooks_controller.rb +6 -5
  23. data/app/controllers/shipit/api/locks_controller.rb +5 -4
  24. data/app/controllers/shipit/api/merge_requests_controller.rb +37 -0
  25. data/app/controllers/shipit/api/outputs_controller.rb +2 -1
  26. data/app/controllers/shipit/api/release_statuses_controller.rb +3 -2
  27. data/app/controllers/shipit/api/rollbacks_controller.rb +34 -0
  28. data/app/controllers/shipit/api/stacks_controller.rb +32 -5
  29. data/app/controllers/shipit/api/tasks_controller.rb +6 -5
  30. data/app/controllers/shipit/api_clients_controller.rb +4 -3
  31. data/app/controllers/shipit/ccmenu_url_controller.rb +4 -3
  32. data/app/controllers/shipit/commit_checks_controller.rb +2 -1
  33. data/app/controllers/shipit/commits_controller.rb +2 -1
  34. data/app/controllers/shipit/deploys_controller.rb +4 -3
  35. data/app/controllers/shipit/github_authentication_controller.rb +4 -3
  36. data/app/controllers/shipit/merge_requests_controller.rb +31 -0
  37. data/app/controllers/shipit/merge_status_controller.rb +31 -30
  38. data/app/controllers/shipit/release_statuses_controller.rb +3 -2
  39. data/app/controllers/shipit/repositories_controller.rb +74 -0
  40. data/app/controllers/shipit/rollbacks_controller.rb +3 -2
  41. data/app/controllers/shipit/shipit_controller.rb +2 -1
  42. data/app/controllers/shipit/stacks_controller.rb +24 -9
  43. data/app/controllers/shipit/status_controller.rb +2 -1
  44. data/app/controllers/shipit/tasks_controller.rb +7 -6
  45. data/app/controllers/shipit/webhooks_controller.rb +26 -6
  46. data/app/helpers/shipit/chunks_helper.rb +3 -2
  47. data/app/helpers/shipit/deploys_helper.rb +4 -3
  48. data/app/helpers/shipit/github_url_helper.rb +9 -0
  49. data/app/helpers/shipit/merge_status_helper.rb +1 -0
  50. data/app/helpers/shipit/shipit_helper.rb +1 -1
  51. data/app/helpers/shipit/stacks_helper.rb +5 -0
  52. data/app/helpers/shipit/tasks_helper.rb +1 -0
  53. data/app/jobs/shipit/background_job/unique.rb +1 -0
  54. data/app/jobs/shipit/background_job.rb +4 -0
  55. data/app/jobs/shipit/cache_deploy_spec_job.rb +1 -0
  56. data/app/jobs/shipit/chunk_rollup_job.rb +4 -0
  57. data/app/jobs/shipit/clear_git_cache_job.rb +1 -0
  58. data/app/jobs/shipit/continuous_delivery_job.rb +2 -1
  59. data/app/jobs/shipit/create_on_github_job.rb +7 -1
  60. data/app/jobs/shipit/create_release_statuses_job.rb +1 -0
  61. data/app/jobs/shipit/deferred_touch_job.rb +4 -0
  62. data/app/jobs/shipit/deliver_hook_job.rb +2 -1
  63. data/app/jobs/shipit/destroy_job.rb +1 -0
  64. data/app/jobs/shipit/destroy_repository_job.rb +24 -0
  65. data/app/jobs/shipit/destroy_stack_job.rb +3 -2
  66. data/app/jobs/shipit/emit_event_job.rb +2 -1
  67. data/app/jobs/shipit/fetch_commit_stats_job.rb +1 -0
  68. data/app/jobs/shipit/fetch_deployed_revision_job.rb +1 -0
  69. data/app/jobs/shipit/github_sync_job.rb +15 -10
  70. data/app/jobs/shipit/mark_deploy_healthy_job.rb +1 -0
  71. data/app/jobs/shipit/perform_commit_checks_job.rb +1 -0
  72. data/app/jobs/shipit/perform_task_job.rb +5 -92
  73. data/app/jobs/shipit/process_merge_requests_job.rb +32 -0
  74. data/app/jobs/shipit/purge_old_deliveries_job.rb +1 -0
  75. data/app/jobs/shipit/reap_dead_tasks_job.rb +21 -0
  76. data/app/jobs/shipit/refresh_check_runs_job.rb +1 -0
  77. data/app/jobs/shipit/refresh_github_user_job.rb +1 -0
  78. data/app/jobs/shipit/refresh_merge_request_job.rb +11 -0
  79. data/app/jobs/shipit/refresh_statuses_job.rb +1 -0
  80. data/app/jobs/shipit/setup_github_hook_job.rb +1 -0
  81. data/app/jobs/shipit/update_estimated_deploy_duration_job.rb +1 -0
  82. data/app/jobs/shipit/update_github_last_deployed_ref_job.rb +5 -4
  83. data/app/models/concerns/shipit/deferred_touch.rb +4 -3
  84. data/app/models/shipit/anonymous_user.rb +15 -2
  85. data/app/models/shipit/api_client.rb +3 -2
  86. data/app/models/shipit/application_record.rb +2 -1
  87. data/app/models/shipit/check_run.rb +41 -4
  88. data/app/models/shipit/command_line_user.rb +5 -0
  89. data/app/models/shipit/commit.rb +42 -24
  90. data/app/models/shipit/commit_checks.rb +15 -13
  91. data/app/models/shipit/commit_deployment.rb +6 -5
  92. data/app/models/shipit/commit_deployment_status.rb +5 -4
  93. data/app/models/shipit/commit_message.rb +1 -0
  94. data/app/models/shipit/delivery.rb +4 -3
  95. data/app/models/shipit/deploy.rb +23 -28
  96. data/app/models/shipit/deploy_spec/bundler_discovery.rb +1 -0
  97. data/app/models/shipit/deploy_spec/capistrano_discovery.rb +1 -0
  98. data/app/models/shipit/deploy_spec/file_system.rb +20 -7
  99. data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +1 -0
  100. data/app/models/shipit/deploy_spec/lerna_discovery.rb +13 -4
  101. data/app/models/shipit/deploy_spec/npm_discovery.rb +5 -4
  102. data/app/models/shipit/deploy_spec/pypi_discovery.rb +1 -0
  103. data/app/models/shipit/deploy_spec/rubygems_discovery.rb +1 -0
  104. data/app/models/shipit/deploy_spec.rb +38 -7
  105. data/app/models/shipit/deploy_stats.rb +2 -1
  106. data/app/models/shipit/duration.rb +5 -2
  107. data/app/models/shipit/ephemeral_commit_checks.rb +1 -0
  108. data/app/models/shipit/github_hook.rb +2 -1
  109. data/app/models/shipit/github_status.rb +2 -1
  110. data/app/models/shipit/hook.rb +34 -7
  111. data/app/models/shipit/membership.rb +3 -2
  112. data/app/models/shipit/merge_request.rb +304 -0
  113. data/app/models/shipit/output_chunk.rb +7 -2
  114. data/app/models/shipit/provisioning_handler/base.rb +30 -0
  115. data/app/models/shipit/provisioning_handler/unregistered_provisioning_handler.rb +35 -0
  116. data/app/models/shipit/provisioning_handler.rb +32 -0
  117. data/app/models/shipit/pull_request.rb +28 -266
  118. data/app/models/shipit/pull_request_assignment.rb +10 -0
  119. data/app/models/shipit/record.rb +18 -0
  120. data/app/models/shipit/release_status.rb +4 -3
  121. data/app/models/shipit/repository.rb +71 -6
  122. data/app/models/shipit/review_stack.rb +130 -0
  123. data/app/models/shipit/review_stack_provisioning_queue.rb +39 -0
  124. data/app/models/shipit/rollback.rb +6 -0
  125. data/app/models/shipit/stack.rb +127 -45
  126. data/app/models/shipit/status/common.rb +7 -6
  127. data/app/models/shipit/status/group.rb +2 -1
  128. data/app/models/shipit/status/missing.rb +2 -1
  129. data/app/models/shipit/status/unknown.rb +2 -1
  130. data/app/models/shipit/status.rb +3 -2
  131. data/app/models/shipit/task.rb +98 -12
  132. data/app/models/shipit/task_definition.rb +1 -0
  133. data/app/models/shipit/task_execution_strategy/base.rb +20 -0
  134. data/app/models/shipit/task_execution_strategy/default.rb +109 -0
  135. data/app/models/shipit/team.rb +6 -3
  136. data/app/models/shipit/undeployed_commit.rb +1 -0
  137. data/app/models/shipit/unlimited_api_client.rb +1 -0
  138. data/app/models/shipit/user.rb +19 -8
  139. data/app/models/shipit/variable_definition.rb +1 -0
  140. data/app/models/shipit/webhooks/handlers/check_suite_handler.rb +1 -0
  141. data/app/models/shipit/webhooks/handlers/handler.rb +1 -0
  142. data/app/models/shipit/webhooks/handlers/membership_handler.rb +1 -0
  143. data/app/models/shipit/webhooks/handlers/pull_request/assigned_handler.rb +74 -0
  144. data/app/models/shipit/webhooks/handlers/pull_request/closed_handler.rb +68 -0
  145. data/app/models/shipit/webhooks/handlers/pull_request/edited_handler.rb +74 -0
  146. data/app/models/shipit/webhooks/handlers/pull_request/label_capturing_handler.rb +127 -0
  147. data/app/models/shipit/webhooks/handlers/pull_request/labeled_handler.rb +106 -0
  148. data/app/models/shipit/webhooks/handlers/pull_request/opened_handler.rb +83 -0
  149. data/app/models/shipit/webhooks/handlers/pull_request/reopened_handler.rb +88 -0
  150. data/app/models/shipit/webhooks/handlers/pull_request/review_stack_adapter.rb +103 -0
  151. data/app/models/shipit/webhooks/handlers/pull_request/unlabeled_handler.rb +107 -0
  152. data/app/models/shipit/webhooks/handlers/push_handler.rb +5 -1
  153. data/app/models/shipit/webhooks/handlers/status_handler.rb +1 -0
  154. data/app/models/shipit/webhooks.rb +11 -0
  155. data/app/serializers/concerns/shipit/conditional_attributes.rb +1 -0
  156. data/app/serializers/shipit/anonymous_user_serializer.rb +1 -0
  157. data/app/serializers/shipit/command_line_user_serializer.rb +1 -0
  158. data/app/serializers/shipit/commit_serializer.rb +1 -0
  159. data/app/serializers/shipit/deploy_serializer.rb +8 -1
  160. data/app/serializers/shipit/hook_serializer.rb +1 -0
  161. data/app/serializers/shipit/merge_request_serializer.rb +21 -0
  162. data/app/serializers/shipit/pull_request_serializer.rb +6 -8
  163. data/app/serializers/shipit/review_stack_serializer.rb +7 -0
  164. data/app/serializers/shipit/rollback_serializer.rb +1 -0
  165. data/app/serializers/shipit/short_commit_serializer.rb +1 -0
  166. data/app/serializers/shipit/stack_serializer.rb +8 -6
  167. data/app/serializers/shipit/tail_task_serializer.rb +11 -2
  168. data/app/serializers/shipit/task_serializer.rb +2 -17
  169. data/app/serializers/shipit/user_serializer.rb +6 -1
  170. data/app/validators/ascii_only_validator.rb +1 -0
  171. data/app/validators/subset_validator.rb +2 -1
  172. data/app/views/layouts/merge_status.html.erb +1 -1
  173. data/app/views/layouts/shipit.html.erb +1 -1
  174. data/app/views/shipit/_variables.html.erb +1 -1
  175. data/app/views/shipit/ccmenu/project.xml.builder +2 -1
  176. data/app/views/shipit/deploys/show.html.erb +2 -2
  177. data/app/views/shipit/merge_requests/_merge_request.html.erb +29 -0
  178. data/app/views/shipit/{pull_requests → merge_requests}/index.html.erb +2 -2
  179. data/app/views/shipit/merge_requests/merge_requests/_pull_request.html.erb +29 -0
  180. data/app/views/shipit/merge_requests/merge_requests/index.html.erb +20 -0
  181. data/app/views/shipit/merge_status/_merge_queue_button.html.erb +3 -3
  182. data/app/views/shipit/merge_status/backlogged.html.erb +1 -1
  183. data/app/views/shipit/merge_status/failure.html.erb +1 -1
  184. data/app/views/shipit/merge_status/locked.html.erb +1 -1
  185. data/app/views/shipit/merge_status/success.html.erb +2 -2
  186. data/app/views/shipit/repositories/_header.html.erb +19 -0
  187. data/app/views/shipit/repositories/index.html.erb +31 -0
  188. data/app/views/shipit/repositories/new.html.erb +23 -0
  189. data/app/views/shipit/repositories/settings.html.erb +53 -0
  190. data/app/views/shipit/repositories/show.html.erb +30 -0
  191. data/app/views/shipit/stacks/_banners.html.erb +15 -1
  192. data/app/views/shipit/stacks/_header.html.erb +8 -2
  193. data/app/views/shipit/stacks/_stack.html.erb +8 -0
  194. data/app/views/shipit/stacks/all_tasks.html.erb +28 -0
  195. data/app/views/shipit/stacks/index.html.erb +3 -2
  196. data/app/views/shipit/stacks/new.html.erb +1 -1
  197. data/app/views/shipit/stacks/settings.html.erb +5 -5
  198. data/app/views/shipit/stacks/show.html.erb +1 -1
  199. data/app/views/shipit/tasks/_task_output.html.erb +1 -1
  200. data/app/views/shipit/tasks/show.html.erb +1 -1
  201. data/config/initializers/inflections.rb +2 -1
  202. data/config/locales/en.yml +3 -3
  203. data/config/routes.rb +25 -7
  204. data/config/secrets.development.example.yml +24 -0
  205. data/config/secrets.development.shopify.yml +20 -9
  206. data/db/migrate/20200226211925_add_index_to_tasks_status.rb +5 -0
  207. data/db/migrate/20200427135152_add_pull_request_head_sha_to_commit.rb +5 -0
  208. data/db/migrate/20200615181558_add_rollback_once_aborted_to.rb +5 -0
  209. data/db/migrate/20200706145406_add_review_stacks.rb +12 -0
  210. data/db/migrate/20200804144639_rename_pull_request_to_merge_request.rb +7 -0
  211. data/db/migrate/20200804161512_rename_commits_pull_request_id_to_merge_request_id.rb +5 -0
  212. data/db/migrate/20200813134712_recreate_shipit_pull_requests.rb +22 -0
  213. data/db/migrate/20200813194056_create_pull_request_assignments.rb +8 -0
  214. data/db/migrate/20201001125502_add_provision_pr_stacks_flag_to_repositories.rb +7 -0
  215. data/db/migrate/20201008145809_add_retry_attempt_to_tasks.rb +5 -0
  216. data/db/migrate/20201008152744_add_max_retries_to_tasks.rb +5 -0
  217. data/db/migrate/20210325194053_remove_stacks_branch_default.rb +5 -0
  218. data/db/migrate/20210504200438_add_github_updated_at_to_check_runs.rb +5 -0
  219. data/db/migrate/20210823075617_change_check_runs_github_updated_at_default.rb +5 -0
  220. data/lib/shipit/cast_value.rb +1 -0
  221. data/lib/shipit/command.rb +19 -17
  222. data/lib/shipit/commands.rb +23 -9
  223. data/lib/shipit/csv_serializer.rb +1 -0
  224. data/lib/shipit/deploy_commands.rb +1 -0
  225. data/lib/shipit/engine.rb +9 -2
  226. data/lib/shipit/environment_variables.rb +2 -1
  227. data/lib/shipit/first_parent_commits_iterator.rb +1 -0
  228. data/lib/shipit/flock.rb +9 -1
  229. data/lib/shipit/github_app.rb +15 -12
  230. data/lib/shipit/github_http_cache_middleware.rb +1 -0
  231. data/lib/shipit/null_serializer.rb +1 -0
  232. data/lib/shipit/octokit_check_runs.rb +3 -2
  233. data/lib/shipit/octokit_iterator.rb +4 -3
  234. data/lib/shipit/paginator.rb +3 -2
  235. data/lib/shipit/review_stack_commands.rb +8 -0
  236. data/lib/shipit/rollback_commands.rb +1 -0
  237. data/lib/shipit/same_site_cookie_middleware.rb +29 -0
  238. data/lib/shipit/simple_message_verifier.rb +3 -2
  239. data/lib/shipit/stack_commands.rb +39 -9
  240. data/lib/shipit/stat.rb +1 -0
  241. data/lib/shipit/task_commands.rb +9 -0
  242. data/lib/shipit/version.rb +2 -1
  243. data/lib/shipit.rb +61 -17
  244. data/lib/snippets/publish-lerna-independent-packages +35 -34
  245. data/lib/snippets/publish-lerna-independent-packages-legacy +39 -0
  246. data/lib/snippets/release-gem +5 -1
  247. data/lib/tasks/cron.rake +13 -2
  248. data/lib/tasks/dev.rake +3 -2
  249. data/lib/tasks/shipit.rake +15 -14
  250. data/lib/tasks/teams.rake +1 -0
  251. data/test/controllers/api/base_controller_test.rb +3 -2
  252. data/test/controllers/api/ccmenu_controller_test.rb +9 -8
  253. data/test/controllers/api/commits_controller_test.rb +3 -2
  254. data/test/controllers/api/deploys_controller_test.rb +32 -14
  255. data/test/controllers/api/hooks_controller_test.rb +8 -7
  256. data/test/controllers/api/locks_controller_test.rb +7 -6
  257. data/test/controllers/api/{pull_requests_controller_test.rb → merge_requests_controller_test.rb} +17 -16
  258. data/test/controllers/api/outputs_controller_test.rb +3 -1
  259. data/test/controllers/api/release_statuses_controller_test.rb +2 -1
  260. data/test/controllers/api/rollback_controller_test.rb +113 -0
  261. data/test/controllers/api/stacks_controller_test.rb +71 -16
  262. data/test/controllers/api/tasks_controller_test.rb +13 -12
  263. data/test/controllers/api_clients_controller_test.rb +5 -4
  264. data/test/controllers/ccmenu_controller_test.rb +4 -3
  265. data/test/controllers/commit_checks_controller_test.rb +4 -3
  266. data/test/controllers/commits_controller_test.rb +3 -2
  267. data/test/controllers/deploys_controller_test.rb +32 -21
  268. data/test/controllers/github_authentication_controller_test.rb +1 -0
  269. data/test/controllers/merge_requests_controller_test.rb +32 -0
  270. data/test/controllers/merge_status_controller_test.rb +7 -6
  271. data/test/controllers/release_statuses_controller_test.rb +3 -2
  272. data/test/controllers/repositories_controller_test.rb +71 -0
  273. data/test/controllers/rollbacks_controller_test.rb +9 -8
  274. data/test/controllers/stacks_controller_test.rb +41 -19
  275. data/test/controllers/status_controller_test.rb +1 -0
  276. data/test/controllers/tasks_controller_test.rb +32 -19
  277. data/test/controllers/webhooks_controller_test.rb +33 -17
  278. data/test/dummy/app/assets/config/manifest.js +3 -0
  279. data/test/dummy/config/application.rb +7 -2
  280. data/test/dummy/config/database.yml +9 -0
  281. data/test/dummy/config/environments/development.rb +3 -4
  282. data/test/dummy/config/environments/test.rb +2 -5
  283. data/test/dummy/config/secrets_double_github_app.yml +79 -0
  284. data/test/dummy/db/schema.rb +59 -17
  285. data/test/dummy/db/seeds.rb +2 -1
  286. data/test/fixtures/payloads/check_suite_master.json +4 -32
  287. data/test/fixtures/payloads/invalid_pull_request.json +117 -0
  288. data/test/fixtures/payloads/provision_disabled_pull_request.json +454 -0
  289. data/test/fixtures/payloads/pull_request_assigned.json +480 -0
  290. data/test/fixtures/payloads/pull_request_closed.json +454 -0
  291. data/test/fixtures/payloads/pull_request_labeled.json +461 -0
  292. data/test/fixtures/payloads/pull_request_opened.json +454 -0
  293. data/test/fixtures/payloads/pull_request_reopened.json +454 -0
  294. data/test/fixtures/payloads/pull_request_unlabeled.json +454 -0
  295. data/test/fixtures/payloads/pull_request_with_no_repo.json +454 -0
  296. data/test/fixtures/payloads/push_master.json +1 -1
  297. data/test/fixtures/payloads/push_not_master.json +1 -1
  298. data/test/fixtures/shipit/commits.yml +31 -3
  299. data/test/fixtures/shipit/hooks.yml +1 -0
  300. data/test/fixtures/shipit/merge_requests.yml +141 -0
  301. data/test/fixtures/shipit/pull_request_assignments.yml +3 -0
  302. data/test/fixtures/shipit/pull_requests.yml +10 -131
  303. data/test/fixtures/shipit/repositories.yml +5 -0
  304. data/test/fixtures/shipit/stacks.yml +235 -14
  305. data/test/fixtures/shipit/statuses.yml +9 -0
  306. data/test/fixtures/shipit/tasks.yml +4 -1
  307. data/test/fixtures/shipit/users.yml +7 -0
  308. data/test/fixtures/timeout +2 -1
  309. data/test/helpers/api_helper.rb +1 -0
  310. data/test/helpers/fixture_aliases_helper.rb +1 -0
  311. data/test/helpers/hooks_helper.rb +2 -1
  312. data/test/helpers/json_helper.rb +20 -12
  313. data/test/helpers/links_helper.rb +4 -3
  314. data/test/helpers/payloads_helper.rb +5 -0
  315. data/test/helpers/queries_helper.rb +3 -2
  316. data/test/jobs/cache_deploy_spec_job_test.rb +2 -1
  317. data/test/jobs/chunk_rollup_job_test.rb +16 -1
  318. data/test/jobs/deliver_hook_job_test.rb +1 -0
  319. data/test/jobs/destroy_repository_job_test.rb +27 -0
  320. data/test/jobs/destroy_stack_job_test.rb +1 -0
  321. data/test/jobs/emit_event_job_test.rb +2 -1
  322. data/test/jobs/fetch_commit_stats_job_test.rb +1 -0
  323. data/test/jobs/fetch_deployed_revision_job_test.rb +1 -0
  324. data/test/jobs/github_sync_job_test.rb +3 -1
  325. data/test/jobs/mark_deploy_healthy_job_test.rb +1 -0
  326. data/test/jobs/perform_task_job_test.rb +12 -11
  327. data/test/jobs/{merge_pull_requests_job_test.rb → process_merge_requests_job_test.rb} +19 -18
  328. data/test/jobs/purge_old_deliveries_job_test.rb +1 -0
  329. data/test/jobs/reap_dead_tasks_job_test.rb +68 -0
  330. data/test/jobs/refresh_github_user_job_test.rb +1 -0
  331. data/test/jobs/refresh_status_job_test.rb +1 -0
  332. data/test/jobs/unique_job_test.rb +1 -0
  333. data/test/jobs/update_github_last_deployed_ref_job_test.rb +1 -0
  334. data/test/lib/shipit/deploy_commands_test.rb +16 -0
  335. data/test/lib/shipit/task_commands_test.rb +17 -0
  336. data/test/middleware/same_site_cookie_middleware_test.rb +52 -0
  337. data/test/models/api_client_test.rb +1 -0
  338. data/test/models/commit_checks_test.rb +1 -0
  339. data/test/models/commit_deployment_status_test.rb +4 -3
  340. data/test/models/commit_deployment_test.rb +2 -1
  341. data/test/models/commits_test.rb +96 -19
  342. data/test/models/delivery_test.rb +2 -1
  343. data/test/models/deploy_spec_test.rb +110 -65
  344. data/test/models/deploy_stats_test.rb +1 -0
  345. data/test/models/deploys_test.rb +219 -36
  346. data/test/models/duration_test.rb +1 -0
  347. data/test/models/github_hook_test.rb +1 -0
  348. data/test/models/hook_test.rb +47 -10
  349. data/test/models/membership_test.rb +1 -0
  350. data/test/models/{pull_request_test.rb → merge_request_test.rb} +53 -37
  351. data/test/models/pull_request_assignment_test.rb +16 -0
  352. data/test/models/release_statuses_test.rb +1 -0
  353. data/test/models/rollbacks_test.rb +1 -0
  354. data/test/models/shipit/check_run_test.rb +125 -5
  355. data/test/models/shipit/provisioning_handler/base_test.rb +33 -0
  356. data/test/models/shipit/provisioning_handler/unregistered_provisioning_handler_test.rb +49 -0
  357. data/test/models/shipit/provisioning_handler_test.rb +64 -0
  358. data/test/models/shipit/pull_request_test.rb +52 -0
  359. data/test/models/shipit/repository_test.rb +6 -1
  360. data/test/models/shipit/review_stack_provision_status_test.rb +77 -0
  361. data/test/models/shipit/review_stack_provisioning_queue_test.rb +63 -0
  362. data/test/models/shipit/review_stack_test.rb +91 -0
  363. data/test/models/{stacks_test.rb → shipit/stacks_test.rb} +82 -16
  364. data/test/models/shipit/webhooks/handlers/pull_request/assigned_handler_test.rb +45 -0
  365. data/test/models/shipit/webhooks/handlers/pull_request/closed_handler_test.rb +192 -0
  366. data/test/models/shipit/webhooks/handlers/pull_request/edited_handler_test.rb +47 -0
  367. data/test/models/shipit/webhooks/handlers/pull_request/label_capturing_handler_test.rb +209 -0
  368. data/test/models/shipit/webhooks/handlers/pull_request/labeled_handler_test.rb +332 -0
  369. data/test/models/shipit/webhooks/handlers/pull_request/opened_handler_test.rb +238 -0
  370. data/test/models/shipit/webhooks/handlers/pull_request/reopened_handler_test.rb +282 -0
  371. data/test/models/shipit/webhooks/handlers/pull_request/review_stack_adapter_test.rb +107 -0
  372. data/test/models/shipit/webhooks/handlers/pull_request/unlabeled_handler_test.rb +324 -0
  373. data/test/models/shipit/{wehbooks → webhooks}/handlers_test.rb +1 -0
  374. data/test/models/status/group_test.rb +1 -0
  375. data/test/models/status/missing_test.rb +1 -0
  376. data/test/models/status_test.rb +1 -0
  377. data/test/models/task_definitions_test.rb +9 -8
  378. data/test/models/tasks_test.rb +81 -1
  379. data/test/models/team_test.rb +4 -2
  380. data/test/models/undeployed_commits_test.rb +1 -0
  381. data/test/models/users_test.rb +13 -5
  382. data/test/serializers/shipit/pull_request_serializer_test.rb +29 -0
  383. data/test/test_command_integration.rb +3 -2
  384. data/test/test_helper.rb +49 -31
  385. data/test/unit/anonymous_user_serializer_test.rb +14 -0
  386. data/test/unit/command_test.rb +16 -10
  387. data/test/unit/commands_test.rb +1 -0
  388. data/test/unit/commit_serializer_test.rb +16 -0
  389. data/test/unit/csv_serializer_test.rb +3 -2
  390. data/test/unit/deploy_commands_test.rb +77 -20
  391. data/test/unit/deploy_serializer_test.rb +17 -0
  392. data/test/unit/environment_variables_test.rb +5 -4
  393. data/test/unit/github_app_test.rb +3 -3
  394. data/test/unit/github_apps_test.rb +416 -0
  395. data/test/unit/github_url_helper_test.rb +6 -0
  396. data/test/unit/rollback_commands_test.rb +2 -1
  397. data/test/unit/shipit_deployment_checks_test.rb +77 -0
  398. data/test/unit/shipit_helper_test.rb +17 -0
  399. data/test/unit/shipit_task_execution_strategy_test.rb +47 -0
  400. data/test/unit/shipit_test.rb +15 -0
  401. data/test/unit/user_serializer_test.rb +14 -0
  402. data/test/unit/variable_definition_test.rb +1 -0
  403. metadata +325 -182
  404. data/app/controllers/shipit/api/pull_requests_controller.rb +0 -36
  405. data/app/controllers/shipit/pull_requests_controller.rb +0 -30
  406. data/app/jobs/shipit/merge_pull_requests_job.rb +0 -31
  407. data/app/jobs/shipit/refresh_pull_request_job.rb +0 -10
  408. data/app/views/shipit/pull_requests/_pull_request.html.erb +0 -29
  409. data/test/controllers/pull_requests_controller_test.rb +0 -31
  410. data/test/fixtures/shipit/output_chunks.yml +0 -47
  411. data/test/models/output_chunk_test.rb +0 -20
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  module CSVSerializer
3
4
  extend self
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class DeployCommands < TaskCommands
3
4
  def steps
data/lib/shipit/engine.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class Engine < ::Rails::Engine
3
4
  isolate_namespace Shipit
@@ -9,6 +10,8 @@ module Shipit
9
10
  Shipit::Engine.routes.default_url_options[:host] = Shipit.host
10
11
  Pubsubstub.redis_url = Shipit.redis_url.to_s
11
12
 
13
+ Rails.application.secrets.deep_symbolize_keys!
14
+
12
15
  app.config.assets.paths << Emoji.images_path
13
16
  app.config.assets.precompile += %w(
14
17
  favicon.ico
@@ -32,12 +35,16 @@ module Shipit
32
35
  ActiveModel::Serializer.include(Engine.routes.url_helpers)
33
36
 
34
37
  if Shipit.github.oauth?
35
- OmniAuth::Strategies::GitHub.configure path_prefix: '/github/auth'
36
- app.middleware.use OmniAuth::Builder do
38
+ OmniAuth::Strategies::GitHub.configure(path_prefix: '/github/auth')
39
+ app.middleware.use(OmniAuth::Builder) do
37
40
  provider(:github, *Shipit.github.oauth_config)
38
41
  end
39
42
  end
40
43
 
44
+ if Shipit.enable_samesite_middleware?
45
+ app.config.middleware.insert_after(::Rack::Runtime, Shipit::SameSiteCookieMiddleware)
46
+ end
47
+
41
48
  app.config.after_initialize do
42
49
  ActionController::Base.include(Shipit::ActiveModelSerializersPatch)
43
50
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class EnvironmentVariables
3
4
  NotPermitted = Class.new(StandardError)
@@ -35,7 +36,7 @@ module Shipit
35
36
  allowed, disallowed = @env.partition { |k, _| allowed_variables.include?(k) }.map(&:to_h)
36
37
 
37
38
  error_message = "Variables #{disallowed.keys.to_sentence} have not been whitelisted"
38
- raise NotPermitted.new(error_message) unless disallowed.empty?
39
+ raise NotPermitted, error_message unless disallowed.empty?
39
40
 
40
41
  allowed
41
42
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class FirstParentCommitsIterator < OctokitIterator
3
4
  def each
data/lib/shipit/flock.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'English'
2
3
  require 'timeout'
3
4
  require 'pathname'
@@ -10,14 +11,21 @@ module Shipit
10
11
 
11
12
  def initialize(path)
12
13
  @path = Pathname.new(path)
14
+ @acquired = false
13
15
  end
14
16
 
15
17
  def lock(timeout:)
18
+ return yield if @acquired
16
19
  path.parent.mkpath
17
20
  path.open('w') do |file|
18
21
  if retrying(timeout: timeout) { file.flock(File::LOCK_EX | File::LOCK_NB) }
19
22
  file.write($PROCESS_ID.to_s)
20
- return yield
23
+ @acquired = true
24
+ begin
25
+ yield
26
+ ensure
27
+ @acquired = false
28
+ end
21
29
  else
22
30
  raise TimeoutError, "Couldn't acquire lock for #{path} in #{timeout} seconds"
23
31
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class GitHubApp
3
4
  include Mutex_m
@@ -31,9 +32,9 @@ module Shipit
31
32
  end
32
33
  end
33
34
 
34
- DOMAIN = 'github.com'.freeze
35
+ DOMAIN = 'github.com'
35
36
  AuthenticationFailed = Class.new(StandardError)
36
- API_STATUS_ID = 'brv1bkgrwx7q'.freeze
37
+ API_STATUS_ID = 'brv1bkgrwx7q'
37
38
 
38
39
  GITHUB_EXPECTED_TOKEN_LIFETIME = 60.minutes
39
40
  GITHUB_TOKEN_RAILS_CACHE_LIFETIME = 50.minutes
@@ -41,8 +42,9 @@ module Shipit
41
42
 
42
43
  attr_reader :oauth_teams, :domain, :bot_login
43
44
 
44
- def initialize(config)
45
+ def initialize(organization, config)
45
46
  super()
47
+ @organization = organization
46
48
  @config = (config || {}).with_indifferent_access
47
49
  @domain = @config[:domain] || DOMAIN
48
50
  @webhook_secret = @config[:webhook_secret].presence
@@ -51,7 +53,7 @@ module Shipit
51
53
  oauth = (@config[:oauth] || {}).with_indifferent_access
52
54
  @oauth_id = oauth[:id]
53
55
  @oauth_secret = oauth[:secret]
54
- @oauth_teams = Array.wrap(oauth[:teams] || oauth[:teams])
56
+ @oauth_teams = Array.wrap(oauth[:teams])
55
57
  end
56
58
 
57
59
  def login
@@ -91,10 +93,11 @@ module Shipit
91
93
  end
92
94
 
93
95
  def fetch_new_token
96
+ cache_key = @organization.nil? ? '' : "#{@organization.downcase}:"
94
97
  # Rails can add 5 minutes to the cache entry expiration time when any TTL is provided,
95
98
  # so our TTL setting can be lower, and TTL + expires_in should be lower than the GitHub token expiration.
96
99
  Rails.cache.fetch(
97
- 'github:integration:access-token',
100
+ "github:integration:#{cache_key}access-token",
98
101
  expires_in: GITHUB_TOKEN_RAILS_CACHE_LIFETIME,
99
102
  race_condition_ttl: 4.minutes,
100
103
  ) do
@@ -132,7 +135,7 @@ module Shipit
132
135
  end
133
136
 
134
137
  def url(*path)
135
- @url ||= "https://#{domain}".freeze
138
+ @url ||= "https://#{domain}"
136
139
  path.empty? ? @url : File.join(@url, *path.map(&:to_s))
137
140
  end
138
141
 
@@ -173,22 +176,22 @@ module Shipit
173
176
  logger: Rails.logger,
174
177
  serializer: NullSerializer,
175
178
  )
176
- builder.use GitHubHTTPCacheMiddleware
177
- builder.use Octokit::Response::RaiseError
178
- builder.adapter Faraday.default_adapter
179
+ builder.use(GitHubHTTPCacheMiddleware)
180
+ builder.use(Octokit::Response::RaiseError)
181
+ builder.adapter(Faraday.default_adapter)
179
182
  end
180
183
  end
181
184
 
182
185
  def app_id
183
- @app_id ||= @config.fetch(:app_id)
186
+ @config.fetch(:app_id)
184
187
  end
185
188
 
186
189
  def installation_id
187
- @installation_id ||= @config.fetch(:installation_id)
190
+ @config.fetch(:installation_id)
188
191
  end
189
192
 
190
193
  def private_key
191
- @private_key ||= @config.fetch(:private_key)
194
+ @config.fetch(:private_key)
192
195
  end
193
196
 
194
197
  def authentication_payload
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class GitHubHTTPCacheMiddleware < Faraday::Middleware
3
4
  def call(request_env)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  module NullSerializer
3
4
  extend self
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  module OctokitCheckRuns
2
3
  def check_runs(repo, sha, options = {})
3
- paginate "#{Octokit::Repository.path repo}/commits/#{sha}/check-runs", options.reverse_merge(
4
+ paginate("#{Octokit::Repository.path(repo)}/commits/#{sha}/check-runs", options.reverse_merge(
4
5
  accept: 'application/vnd.github.antiope-preview+json',
5
- )
6
+ ))
6
7
  end
7
8
  end
8
9
 
@@ -1,13 +1,14 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class OctokitIterator
3
4
  include Enumerable
4
5
 
5
- def initialize(relation = nil)
6
+ def initialize(relation = nil, github_api: nil)
6
7
  if relation
7
8
  @response = relation.get(per_page: 100)
8
9
  else
9
- yield Shipit.github.api
10
- @response = Shipit.github.api.last_response
10
+ data = yield github_api
11
+ @response = github_api.last_response if data.present?
11
12
  end
12
13
  end
13
14
 
@@ -1,6 +1,7 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class Paginator
3
- def initialize(resources, controller, order: {id: :desc}, max_page_size: 100, default_page_size: 30)
4
+ def initialize(resources, controller, order: { id: :desc }, max_page_size: 100, default_page_size: 30)
4
5
  @order = order
5
6
  @controller = controller
6
7
  @since = controller.params[:since].presence
@@ -15,7 +16,7 @@ module Shipit
15
16
  end
16
17
 
17
18
  def links
18
- links = {first: link_to(since: nil, page_size: (page_size if page_size != @default_page_size))}
19
+ links = { first: link_to(since: nil, page_size: (page_size if page_size != @default_page_size)) }
19
20
  links[:next] = link_to(since: to_a.last.id) unless last_page?
20
21
  links
21
22
  end
@@ -0,0 +1,8 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'shipit/stack_commands'
4
+
5
+ module Shipit
6
+ class ReviewStackCommands < Shipit::StackCommands
7
+ end
8
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class RollbackCommands < DeployCommands
3
4
  def steps
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+ module Shipit
3
+ class SameSiteCookieMiddleware
4
+ COOKIE_SEPARATOR = "\n"
5
+
6
+ def initialize(app)
7
+ @app = app
8
+ end
9
+
10
+ def call(env)
11
+ status, headers, body = @app.call(env)
12
+
13
+ if headers && headers['Set-Cookie'] &&
14
+ Rack::Request.new(env).ssl?
15
+
16
+ set_cookies = headers['Set-Cookie'].split(COOKIE_SEPARATOR).compact
17
+ set_cookies.map! do |cookie|
18
+ cookie << '; Secure' if cookie !~ /;\s*secure/i
19
+ cookie << '; SameSite=None' unless cookie.match?(/;\s*samesite=/i)
20
+ cookie
21
+ end
22
+
23
+ headers['Set-Cookie'] = set_cookies.join(COOKIE_SEPARATOR)
24
+ end
25
+
26
+ [status, headers, body]
27
+ end
28
+ end
29
+ end
@@ -1,8 +1,9 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class SimpleMessageVerifier < ActiveSupport::MessageVerifier
3
- def initialize(secret, options = {})
4
+ def initialize(secret, **options)
4
5
  options[:serializer] ||= ToS
5
- super(secret, options)
6
+ super(secret, **options)
6
7
  end
7
8
 
8
9
  private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:disable Lint/MissingSuper
1
3
  require 'pathname'
2
4
  require 'fileutils'
3
5
 
@@ -7,26 +9,36 @@ module Shipit
7
9
  @stack = stack
8
10
  end
9
11
 
12
+ def env
13
+ super.merge(@stack.env)
14
+ end
15
+
10
16
  def fetch
11
17
  create_directories
12
- if Dir.exist?(@stack.git_path)
18
+ if valid_git_repository?(@stack.git_path)
13
19
  git('fetch', 'origin', '--tags', @stack.branch, env: env, chdir: @stack.git_path)
14
20
  else
21
+ @stack.clear_git_cache!
15
22
  git_clone(@stack.repo_git_url, @stack.git_path, branch: @stack.branch, env: env, chdir: @stack.deploys_path)
16
23
  end
17
24
  end
18
25
 
19
26
  def fetched?(commit)
20
- git_dir = File.join(@stack.git_path, '.git')
21
- if Dir.exist?(git_dir)
27
+ if valid_git_repository?(@stack.git_path)
22
28
  git('rev-parse', '--quiet', '--verify', "#{commit.sha}^{commit}", env: env, chdir: @stack.git_path)
23
29
  else
24
- Command.new('test', '-d', git_dir, env: env, chdir: @stack.deploys_path)
30
+ # When the stack's git cache is not valid, the commit is
31
+ # NOT fetched. To keep the interface of this method
32
+ # consistent, we must return a Shipit::Command whose #success?
33
+ # method returns false - has a non-zero exit status. We utilize
34
+ # the POSIX 'test' command with no arguments which should
35
+ # always have an exit status of 1.
36
+ Command.new('test', env: env, chdir: @stack.deploys_path)
25
37
  end
26
38
  end
27
39
 
28
40
  def fetch_deployed_revision
29
- with_temporary_working_directory(commit: @stack.commits.last) do |dir|
41
+ with_temporary_working_directory(commit: @stack.commits.reachable.last) do |dir|
30
42
  spec = DeploySpec::FileSystem.new(dir, @stack.environment)
31
43
  outputs = spec.fetch_deployed_revision_steps!.map do |command_line|
32
44
  Command.new(command_line, env: env, chdir: dir).run
@@ -42,7 +54,7 @@ module Shipit
42
54
  end
43
55
 
44
56
  def with_temporary_working_directory(commit: nil)
45
- commit ||= @stack.last_deployed_commit.presence || @stack.commits.last
57
+ commit ||= @stack.last_deployed_commit.presence || @stack.commits.reachable.last
46
58
 
47
59
  if !commit || !fetched?(commit).tap(&:run).success?
48
60
  @stack.acquire_git_cache_lock do
@@ -55,18 +67,30 @@ module Shipit
55
67
  Dir.mktmpdir do |dir|
56
68
  git(
57
69
  'clone', @stack.git_path, @stack.repo_name,
58
- '--origin', 'cache',
70
+ '--recursive', '--origin', 'cache',
59
71
  chdir: dir
60
72
  ).run!
61
73
 
62
74
  git_dir = File.join(dir, @stack.repo_name)
63
- git('checkout', commit.sha, chdir: git_dir).run! if commit
75
+ git('checkout', '--config', 'advice.detachedHead=false', commit.sha, chdir: git_dir).run! if commit
64
76
  yield Pathname.new(git_dir)
65
77
  end
66
78
  end
67
79
 
80
+ def valid_git_repository?(path)
81
+ path.exist? &&
82
+ !path.empty? &&
83
+ git_cmd_succeeds?(path)
84
+ end
85
+
86
+ def git_cmd_succeeds?(path)
87
+ git("rev-parse", "--git-dir", chdir: path)
88
+ .tap(&:run)
89
+ .success?
90
+ end
91
+
68
92
  def git_clone(url, path, branch: 'master', **kwargs)
69
- git('clone', *modern_git_args, '--recursive', '--branch', branch, url, path, **kwargs)
93
+ git('clone', '--quiet', *modern_git_args, '--recursive', '--branch', branch, url, path, **kwargs)
70
94
  end
71
95
 
72
96
  def modern_git_args
@@ -77,5 +101,11 @@ module Shipit
77
101
  def create_directories
78
102
  FileUtils.mkdir_p(@stack.deploys_path)
79
103
  end
104
+
105
+ private
106
+
107
+ def github
108
+ Shipit.github(organization: @stack.repository.owner)
109
+ end
80
110
  end
81
111
  end
data/lib/shipit/stat.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  module Stat
3
4
  extend self
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+ # rubocop:disable Lint/MissingSuper
1
3
  module Shipit
2
4
  class TaskCommands < Commands
3
5
  delegate :fetch, :fetched?, to: :stack_commands
@@ -52,6 +54,7 @@ module Shipit
52
54
  [
53
55
  git(
54
56
  'clone',
57
+ '--quiet',
55
58
  '--local',
56
59
  '--origin', 'cache',
57
60
  @stack.git_path,
@@ -85,5 +88,11 @@ module Shipit
85
88
  @task.working_directory
86
89
  end
87
90
  end
91
+
92
+ private
93
+
94
+ def github
95
+ Shipit.github(organization: @stack.repository.owner)
96
+ end
88
97
  end
89
98
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
- VERSION = '0.31.0'.freeze
3
+ VERSION = '0.35.0'
3
4
  end
data/lib/shipit.rb CHANGED
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'active_support/all'
2
3
  require 'active_model_serializers'
3
4
  require 'state_machines-activerecord'
@@ -23,7 +24,6 @@ require 'safe_yaml/load'
23
24
  require 'securecompare'
24
25
 
25
26
  require 'redis-objects'
26
- require 'redis-namespace'
27
27
 
28
28
  require 'octokit'
29
29
  require 'faraday-http-cache'
@@ -42,12 +42,14 @@ require 'shipit/simple_message_verifier'
42
42
  require 'shipit/command'
43
43
  require 'shipit/commands'
44
44
  require 'shipit/stack_commands'
45
+ require 'shipit/review_stack_commands'
45
46
  require 'shipit/task_commands'
46
47
  require 'shipit/deploy_commands'
47
48
  require 'shipit/rollback_commands'
48
49
  require 'shipit/environment_variables'
49
50
  require 'shipit/stat'
50
51
  require 'shipit/github_http_cache_middleware'
52
+ require 'shipit/same_site_cookie_middleware'
51
53
  require 'shipit/cast_value'
52
54
  require 'shipit/line_buffer'
53
55
 
@@ -57,10 +59,22 @@ SafeYAML::OPTIONS[:deserialize_symbols] = false
57
59
  module Shipit
58
60
  extend self
59
61
 
62
+ GithubOrganizationUnknown = Class.new(StandardError)
63
+ TOP_LEVEL_GH_KEYS = [:app_id, :installation_id, :webhook_secret, :private_key, :oauth, :domain]
64
+
60
65
  delegate :table_name_prefix, to: :secrets
61
66
 
62
- attr_accessor :disable_api_authentication, :timeout_exit_codes
63
- attr_writer :internal_hook_receivers, :task_logger, :preferred_org_emails
67
+ attr_accessor :disable_api_authentication, :timeout_exit_codes, :deployment_checks
68
+ attr_writer(
69
+ :internal_hook_receivers,
70
+ :preferred_org_emails,
71
+ :task_execution_strategy,
72
+ :task_logger,
73
+ )
74
+
75
+ def task_execution_strategy
76
+ @task_execution_strategy ||= Shipit::TaskExecutionStrategy::Default
77
+ end
64
78
 
65
79
  self.timeout_exit_codes = [].freeze
66
80
 
@@ -68,6 +82,10 @@ module Shipit
68
82
  ENV['SHIPIT_DISABLE_AUTH'].present?
69
83
  end
70
84
 
85
+ def enable_samesite_middleware?
86
+ ENV['SHIPIT_ENABLE_SAMESITE_NONE'].present?
87
+ end
88
+
71
89
  def app_name
72
90
  @app_name ||= secrets.app_name || Rails.application.class.name.split(':').first || 'Shipit'
73
91
  end
@@ -76,7 +94,7 @@ module Shipit
76
94
  secrets.redis_url.present? ? URI(secrets.redis_url) : nil
77
95
  end
78
96
 
79
- def redis(namespace = nil)
97
+ def redis
80
98
  @redis ||= Redis.new(
81
99
  url: redis_url.to_s.presence,
82
100
  logger: Rails.logger,
@@ -84,17 +102,41 @@ module Shipit
84
102
  reconnect_delay: 0.5,
85
103
  reconnect_delay_max: 1,
86
104
  )
87
- return @redis unless namespace
88
- Redis::Namespace.new(namespace, redis: @redis)
89
105
  end
90
106
 
91
- def github
92
- @github ||= GitHubApp.new(secrets.github)
107
+ def github(organization: github_default_organization)
108
+ # Backward compatibility
109
+ # nil signifies the single github app config schema is being used
110
+ if github_default_organization.nil?
111
+ config = secrets.github
112
+ else
113
+ config = github_app_config(organization)
114
+ raise GithubOrganizationUnknown, organization if config.nil?
115
+ end
116
+ @github ||= {}
117
+ @github[organization] ||= GitHubApp.new(organization, config)
118
+ end
119
+
120
+ def github_default_organization
121
+ return nil unless secrets&.github
122
+ org = secrets.github.keys.first
123
+ TOP_LEVEL_GH_KEYS.include?(org) ? nil : org
124
+ end
125
+
126
+ def github_organizations
127
+ return [nil] unless github_default_organization
128
+ secrets.github.keys
129
+ end
130
+
131
+ def github_app_config(organization)
132
+ github_config = secrets.github.deep_transform_keys(&:downcase)
133
+ github_organization = organization.downcase.to_sym
134
+ github_config[github_organization]
93
135
  end
94
136
 
95
137
  def legacy_github_api
96
138
  if secrets&.github_api.present?
97
- @legacy_github_api ||= github.new_client(access_token: secrets.github_api['access_token'])
139
+ @legacy_github_api ||= github.new_client(access_token: secrets.github_api[:access_token])
98
140
  end
99
141
  end
100
142
 
@@ -122,6 +164,10 @@ module Shipit
122
164
  secrets.default_merge_method || 'merge'
123
165
  end
124
166
 
167
+ def update_latest_deployed_ref
168
+ secrets.update_latest_deployed_ref
169
+ end
170
+
125
171
  def enforce_publish_config
126
172
  secrets.enforce_publish_config.presence
127
173
  end
@@ -147,7 +193,7 @@ module Shipit
147
193
  end
148
194
 
149
195
  def env
150
- {'SHIPIT' => '1'}.merge(secrets.env || {})
196
+ { 'SHIPIT' => '1' }.merge(secrets.env || {})
151
197
  end
152
198
 
153
199
  def shell_paths
@@ -155,13 +201,11 @@ module Shipit
155
201
  end
156
202
 
157
203
  def revision
158
- @revision ||= begin
159
- if revision_file.exist?
160
- revision_file.read
161
- else
162
- `git rev-parse HEAD`
163
- end.strip
164
- end
204
+ @revision ||= if revision_file.exist?
205
+ revision_file.read
206
+ else
207
+ %x(git rev-parse HEAD)
208
+ end.strip
165
209
  end
166
210
 
167
211
  def default_inactivity_timeout