shipit-engine 0.30.0 → 0.34.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 (410) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +19 -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 +0 -2
  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.rb +4 -0
  54. data/app/jobs/shipit/background_job/unique.rb +1 -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.rb +38 -7
  97. data/app/models/shipit/deploy_spec/bundler_discovery.rb +1 -0
  98. data/app/models/shipit/deploy_spec/capistrano_discovery.rb +1 -0
  99. data/app/models/shipit/deploy_spec/file_system.rb +20 -7
  100. data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +1 -0
  101. data/app/models/shipit/deploy_spec/lerna_discovery.rb +13 -4
  102. data/app/models/shipit/deploy_spec/npm_discovery.rb +5 -4
  103. data/app/models/shipit/deploy_spec/pypi_discovery.rb +1 -0
  104. data/app/models/shipit/deploy_spec/rubygems_discovery.rb +1 -0
  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.rb +32 -0
  115. data/app/models/shipit/provisioning_handler/base.rb +30 -0
  116. data/app/models/shipit/provisioning_handler/unregistered_provisioning_handler.rb +35 -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 +1 -0
  125. data/app/models/shipit/stack.rb +144 -44
  126. data/app/models/shipit/status.rb +3 -2
  127. data/app/models/shipit/status/common.rb +7 -6
  128. data/app/models/shipit/status/group.rb +2 -1
  129. data/app/models/shipit/status/missing.rb +2 -1
  130. data/app/models/shipit/status/unknown.rb +2 -1
  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.rb +11 -0
  141. data/app/models/shipit/webhooks/handlers/check_suite_handler.rb +1 -0
  142. data/app/models/shipit/webhooks/handlers/handler.rb +1 -0
  143. data/app/models/shipit/webhooks/handlers/membership_handler.rb +1 -0
  144. data/app/models/shipit/webhooks/handlers/pull_request/assigned_handler.rb +74 -0
  145. data/app/models/shipit/webhooks/handlers/pull_request/closed_handler.rb +68 -0
  146. data/app/models/shipit/webhooks/handlers/pull_request/edited_handler.rb +74 -0
  147. data/app/models/shipit/webhooks/handlers/pull_request/label_capturing_handler.rb +127 -0
  148. data/app/models/shipit/webhooks/handlers/pull_request/labeled_handler.rb +106 -0
  149. data/app/models/shipit/webhooks/handlers/pull_request/opened_handler.rb +83 -0
  150. data/app/models/shipit/webhooks/handlers/pull_request/reopened_handler.rb +88 -0
  151. data/app/models/shipit/webhooks/handlers/pull_request/review_stack_adapter.rb +103 -0
  152. data/app/models/shipit/webhooks/handlers/pull_request/unlabeled_handler.rb +107 -0
  153. data/app/models/shipit/webhooks/handlers/push_handler.rb +5 -1
  154. data/app/models/shipit/webhooks/handlers/status_handler.rb +1 -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 +20 -7
  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 +4 -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/lib/shipit.rb +61 -17
  220. data/lib/shipit/cast_value.rb +1 -0
  221. data/lib/shipit/command.rb +20 -21
  222. data/lib/shipit/commands.rb +14 -6
  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 +11 -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 +37 -7
  240. data/lib/shipit/stat.rb +1 -0
  241. data/lib/shipit/task_commands.rb +23 -16
  242. data/lib/shipit/version.rb +2 -1
  243. data/lib/snippets/publish-lerna-independent-packages +35 -34
  244. data/lib/snippets/publish-lerna-independent-packages-legacy +39 -0
  245. data/lib/snippets/release-gem +5 -1
  246. data/lib/tasks/cron.rake +13 -2
  247. data/lib/tasks/dev.rake +3 -2
  248. data/lib/tasks/shipit.rake +15 -14
  249. data/lib/tasks/teams.rake +1 -0
  250. data/test/controllers/api/base_controller_test.rb +3 -2
  251. data/test/controllers/api/ccmenu_controller_test.rb +9 -8
  252. data/test/controllers/api/commits_controller_test.rb +3 -2
  253. data/test/controllers/api/deploys_controller_test.rb +32 -14
  254. data/test/controllers/api/hooks_controller_test.rb +8 -7
  255. data/test/controllers/api/locks_controller_test.rb +7 -6
  256. data/test/controllers/api/{pull_requests_controller_test.rb → merge_requests_controller_test.rb} +17 -16
  257. data/test/controllers/api/outputs_controller_test.rb +3 -1
  258. data/test/controllers/api/release_statuses_controller_test.rb +2 -1
  259. data/test/controllers/api/rollback_controller_test.rb +113 -0
  260. data/test/controllers/api/stacks_controller_test.rb +71 -16
  261. data/test/controllers/api/tasks_controller_test.rb +13 -12
  262. data/test/controllers/api_clients_controller_test.rb +5 -4
  263. data/test/controllers/ccmenu_controller_test.rb +4 -3
  264. data/test/controllers/commit_checks_controller_test.rb +4 -3
  265. data/test/controllers/commits_controller_test.rb +3 -2
  266. data/test/controllers/deploys_controller_test.rb +32 -21
  267. data/test/controllers/github_authentication_controller_test.rb +1 -0
  268. data/test/controllers/merge_requests_controller_test.rb +32 -0
  269. data/test/controllers/merge_status_controller_test.rb +7 -6
  270. data/test/controllers/release_statuses_controller_test.rb +3 -2
  271. data/test/controllers/repositories_controller_test.rb +71 -0
  272. data/test/controllers/rollbacks_controller_test.rb +9 -8
  273. data/test/controllers/stacks_controller_test.rb +41 -19
  274. data/test/controllers/status_controller_test.rb +1 -0
  275. data/test/controllers/tasks_controller_test.rb +32 -19
  276. data/test/controllers/webhooks_controller_test.rb +33 -17
  277. data/test/dummy/app/assets/config/manifest.js +3 -0
  278. data/test/dummy/config/application.rb +7 -2
  279. data/test/dummy/config/database.yml +9 -0
  280. data/test/dummy/config/environments/development.rb +3 -4
  281. data/test/dummy/config/environments/test.rb +2 -5
  282. data/test/dummy/config/secrets_double_github_app.yml +79 -0
  283. data/test/dummy/db/schema.rb +59 -17
  284. data/test/dummy/db/seeds.rb +2 -1
  285. data/test/fixtures/payloads/check_suite_master.json +4 -32
  286. data/test/fixtures/payloads/invalid_pull_request.json +117 -0
  287. data/test/fixtures/payloads/provision_disabled_pull_request.json +454 -0
  288. data/test/fixtures/payloads/pull_request_assigned.json +480 -0
  289. data/test/fixtures/payloads/pull_request_closed.json +454 -0
  290. data/test/fixtures/payloads/pull_request_labeled.json +461 -0
  291. data/test/fixtures/payloads/pull_request_opened.json +454 -0
  292. data/test/fixtures/payloads/pull_request_reopened.json +454 -0
  293. data/test/fixtures/payloads/pull_request_unlabeled.json +454 -0
  294. data/test/fixtures/payloads/pull_request_with_no_repo.json +454 -0
  295. data/test/fixtures/payloads/push_master.json +1 -1
  296. data/test/fixtures/payloads/push_not_master.json +1 -1
  297. data/test/fixtures/shipit/commits.yml +31 -3
  298. data/test/fixtures/shipit/hooks.yml +1 -0
  299. data/test/fixtures/shipit/merge_requests.yml +141 -0
  300. data/test/fixtures/shipit/pull_request_assignments.yml +3 -0
  301. data/test/fixtures/shipit/pull_requests.yml +10 -131
  302. data/test/fixtures/shipit/repositories.yml +5 -0
  303. data/test/fixtures/shipit/stacks.yml +235 -14
  304. data/test/fixtures/shipit/statuses.yml +9 -0
  305. data/test/fixtures/shipit/tasks.yml +4 -1
  306. data/test/fixtures/shipit/users.yml +7 -0
  307. data/test/fixtures/timeout +2 -1
  308. data/test/helpers/api_helper.rb +1 -0
  309. data/test/helpers/fixture_aliases_helper.rb +1 -0
  310. data/test/helpers/hooks_helper.rb +2 -1
  311. data/test/helpers/json_helper.rb +20 -12
  312. data/test/helpers/links_helper.rb +4 -3
  313. data/test/helpers/payloads_helper.rb +5 -0
  314. data/test/helpers/queries_helper.rb +3 -2
  315. data/test/jobs/cache_deploy_spec_job_test.rb +2 -1
  316. data/test/jobs/chunk_rollup_job_test.rb +16 -1
  317. data/test/jobs/deliver_hook_job_test.rb +1 -0
  318. data/test/jobs/destroy_repository_job_test.rb +27 -0
  319. data/test/jobs/destroy_stack_job_test.rb +1 -0
  320. data/test/jobs/emit_event_job_test.rb +2 -1
  321. data/test/jobs/fetch_commit_stats_job_test.rb +1 -0
  322. data/test/jobs/fetch_deployed_revision_job_test.rb +1 -0
  323. data/test/jobs/github_sync_job_test.rb +3 -1
  324. data/test/jobs/mark_deploy_healthy_job_test.rb +1 -0
  325. data/test/jobs/perform_task_job_test.rb +12 -11
  326. data/test/jobs/{merge_pull_requests_job_test.rb → process_merge_requests_job_test.rb} +19 -18
  327. data/test/jobs/purge_old_deliveries_job_test.rb +1 -0
  328. data/test/jobs/reap_dead_tasks_job_test.rb +68 -0
  329. data/test/jobs/refresh_github_user_job_test.rb +1 -0
  330. data/test/jobs/refresh_status_job_test.rb +1 -0
  331. data/test/jobs/unique_job_test.rb +1 -0
  332. data/test/jobs/update_github_last_deployed_ref_job_test.rb +1 -0
  333. data/test/lib/shipit/deploy_commands_test.rb +16 -0
  334. data/test/lib/shipit/task_commands_test.rb +17 -0
  335. data/test/middleware/same_site_cookie_middleware_test.rb +52 -0
  336. data/test/models/api_client_test.rb +1 -0
  337. data/test/models/commit_checks_test.rb +1 -0
  338. data/test/models/commit_deployment_status_test.rb +4 -3
  339. data/test/models/commit_deployment_test.rb +2 -1
  340. data/test/models/commits_test.rb +96 -19
  341. data/test/models/delivery_test.rb +2 -1
  342. data/test/models/deploy_spec_test.rb +110 -65
  343. data/test/models/deploy_stats_test.rb +1 -0
  344. data/test/models/deploys_test.rb +197 -36
  345. data/test/models/duration_test.rb +1 -0
  346. data/test/models/github_hook_test.rb +1 -0
  347. data/test/models/hook_test.rb +47 -10
  348. data/test/models/membership_test.rb +1 -0
  349. data/test/models/{pull_request_test.rb → merge_request_test.rb} +53 -37
  350. data/test/models/pull_request_assignment_test.rb +16 -0
  351. data/test/models/release_statuses_test.rb +1 -0
  352. data/test/models/rollbacks_test.rb +1 -0
  353. data/test/models/shipit/check_run_test.rb +125 -5
  354. data/test/models/shipit/provisioning_handler/base_test.rb +33 -0
  355. data/test/models/shipit/provisioning_handler/unregistered_provisioning_handler_test.rb +49 -0
  356. data/test/models/shipit/provisioning_handler_test.rb +64 -0
  357. data/test/models/shipit/pull_request_test.rb +52 -0
  358. data/test/models/shipit/repository_test.rb +6 -1
  359. data/test/models/shipit/review_stack_provision_status_test.rb +77 -0
  360. data/test/models/shipit/review_stack_provisioning_queue_test.rb +63 -0
  361. data/test/models/shipit/review_stack_test.rb +91 -0
  362. data/test/models/{stacks_test.rb → shipit/stacks_test.rb} +121 -16
  363. data/test/models/shipit/webhooks/handlers/pull_request/assigned_handler_test.rb +45 -0
  364. data/test/models/shipit/webhooks/handlers/pull_request/closed_handler_test.rb +192 -0
  365. data/test/models/shipit/webhooks/handlers/pull_request/edited_handler_test.rb +47 -0
  366. data/test/models/shipit/webhooks/handlers/pull_request/label_capturing_handler_test.rb +209 -0
  367. data/test/models/shipit/webhooks/handlers/pull_request/labeled_handler_test.rb +332 -0
  368. data/test/models/shipit/webhooks/handlers/pull_request/opened_handler_test.rb +238 -0
  369. data/test/models/shipit/webhooks/handlers/pull_request/reopened_handler_test.rb +282 -0
  370. data/test/models/shipit/webhooks/handlers/pull_request/review_stack_adapter_test.rb +107 -0
  371. data/test/models/shipit/webhooks/handlers/pull_request/unlabeled_handler_test.rb +324 -0
  372. data/test/models/shipit/{wehbooks → webhooks}/handlers_test.rb +1 -0
  373. data/test/models/status/group_test.rb +1 -0
  374. data/test/models/status/missing_test.rb +1 -0
  375. data/test/models/status_test.rb +1 -0
  376. data/test/models/task_definitions_test.rb +9 -8
  377. data/test/models/tasks_test.rb +81 -1
  378. data/test/models/team_test.rb +4 -2
  379. data/test/models/undeployed_commits_test.rb +1 -0
  380. data/test/models/users_test.rb +13 -5
  381. data/test/serializers/shipit/pull_request_serializer_test.rb +29 -0
  382. data/test/test_command_integration.rb +3 -2
  383. data/test/test_helper.rb +49 -31
  384. data/test/unit/anonymous_user_serializer_test.rb +14 -0
  385. data/test/unit/command_test.rb +16 -10
  386. data/test/unit/commands_test.rb +1 -0
  387. data/test/unit/commit_serializer_test.rb +16 -0
  388. data/test/unit/csv_serializer_test.rb +3 -2
  389. data/test/unit/deploy_commands_test.rb +75 -18
  390. data/test/unit/deploy_serializer_test.rb +17 -0
  391. data/test/unit/environment_variables_test.rb +5 -4
  392. data/test/unit/github_app_test.rb +3 -3
  393. data/test/unit/github_apps_test.rb +416 -0
  394. data/test/unit/github_url_helper_test.rb +6 -0
  395. data/test/unit/rollback_commands_test.rb +2 -1
  396. data/test/unit/shipit_deployment_checks_test.rb +77 -0
  397. data/test/unit/shipit_helper_test.rb +17 -0
  398. data/test/unit/shipit_task_execution_strategy_test.rb +47 -0
  399. data/test/unit/shipit_test.rb +15 -0
  400. data/test/unit/user_serializer_test.rb +14 -0
  401. data/test/unit/variable_definition_test.rb +1 -0
  402. metadata +320 -178
  403. data/app/controllers/shipit/api/pull_requests_controller.rb +0 -36
  404. data/app/controllers/shipit/pull_requests_controller.rb +0 -30
  405. data/app/jobs/shipit/merge_pull_requests_job.rb +0 -31
  406. data/app/jobs/shipit/refresh_pull_request_job.rb +0 -10
  407. data/app/views/shipit/pull_requests/_pull_request.html.erb +0 -29
  408. data/test/controllers/pull_requests_controller_test.rb +0 -31
  409. data/test/fixtures/shipit/output_chunks.yml +0 -47
  410. data/test/models/output_chunk_test.rb +0 -20
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class MarkDeployHealthyJob < BackgroundJob
3
4
  include BackgroundJob::Unique
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class PerformCommitChecksJob < BackgroundJob
3
4
  include BackgroundJob::Unique
@@ -1,100 +1,13 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class PerformTaskJob < BackgroundJob
3
4
  queue_as :deploys
4
5
 
5
6
  def perform(task)
6
- @task = task
7
- @commands = Commands.for(@task)
8
- unless @task.pending?
9
- logger.error("Task ##{@task.id} already in `#{@task.status}` state. Aborting.")
10
- return
11
- end
12
- run
13
- ensure
14
- @commands.clear_working_directory
15
- end
16
-
17
- def run
18
- @task.run!
19
- checkout_repository
20
- perform_task
21
- @task.write("\nCompleted successfully\n")
22
- @task.report_complete!
23
- rescue Command::TimedOut => error
24
- @task.write("\n#{error.message}\n")
25
- @task.report_timeout!(error)
26
- rescue Command::Error => error
27
- @task.write("\n#{error.message}\n")
28
- @task.report_failure!(error)
29
- rescue StandardError => error
30
- @task.report_error!(error)
31
- rescue Exception => error
32
- @task.report_error!(error)
33
- raise
34
- end
35
-
36
- def abort!(signal: 'TERM')
37
- pid = @task.pid
38
- if pid
39
- @task.write("$ kill #{pid}\n")
40
- Process.kill(signal, pid)
41
- else
42
- @task.write("Can't abort, no recorded pid, WTF?\n")
43
- end
44
- rescue SystemCallError => error
45
- @task.write("kill: (#{pid}) - #{error.message}\n")
46
- end
47
-
48
- def check_for_abort
49
- @task.should_abort? do |times_killed|
50
- if times_killed > 3
51
- abort!(signal: 'KILL')
52
- else
53
- abort!
54
- end
55
- end
56
- end
57
-
58
- def perform_task
59
- capture_all! @commands.install_dependencies
60
- capture_all! @commands.perform
61
- end
62
-
63
- def checkout_repository
64
- unless @commands.fetched?(@task.until_commit).tap(&:run).success?
65
- @task.acquire_git_cache_lock do
66
- unless @commands.fetched?(@task.until_commit).tap(&:run).success?
67
- capture! @commands.fetch
68
- end
69
- end
70
- end
71
- capture_all! @commands.clone
72
- capture! @commands.checkout(@task.until_commit)
73
- end
74
-
75
- def capture_all!(commands)
76
- commands.map { |c| capture!(c) }
77
- end
78
-
79
- def capture!(command)
80
- command.start do
81
- @task.ping
82
- check_for_abort
83
- end
84
- @task.write("$ #{command}\npid: #{command.pid}\n")
85
- @task.pid = command.pid
86
- command.stream! do |line|
87
- @task.write(line)
88
- end
89
- @task.write("\n")
90
- command.success?
91
- end
92
-
93
- def capture(command)
94
- capture!(command)
95
- command.success?
96
- rescue Command::Error
97
- false
7
+ Shipit
8
+ .task_execution_strategy
9
+ .new(task)
10
+ .execute
98
11
  end
99
12
  end
100
13
  end
@@ -0,0 +1,32 @@
1
+ # frozen_string_literal: true
2
+ module Shipit
3
+ class ProcessMergeRequestsJob < BackgroundJob
4
+ include BackgroundJob::Unique
5
+ on_duplicate :drop
6
+
7
+ queue_as :default
8
+
9
+ def perform(stack)
10
+ merge_requests = stack.merge_requests.to_be_merged.to_a
11
+ merge_requests.each do |merge_request|
12
+ merge_request.refresh!
13
+ merge_request.reject_unless_mergeable!
14
+ merge_request.cancel! if merge_request.closed?
15
+ merge_request.revalidate! if merge_request.need_revalidation?
16
+ end
17
+
18
+ return false unless stack.allows_merges?
19
+
20
+ merge_requests.select(&:pending?).each do |merge_request|
21
+ merge_request.refresh!
22
+ next unless merge_request.all_status_checks_passed?
23
+ begin
24
+ merge_request.merge!
25
+ rescue MergeRequest::NotReady
26
+ ProcessMergeRequestsJob.set(wait: 10.seconds).perform_later(stack)
27
+ return false
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class PurgeOldDeliveriesJob < BackgroundJob
3
4
  include BackgroundJob::Unique
@@ -0,0 +1,21 @@
1
+ # frozen_string_literal: true
2
+ module Shipit
3
+ class ReapDeadTasksJob < BackgroundJob
4
+ include BackgroundJob::Unique
5
+ queue_as :default
6
+
7
+ def perform
8
+ Rails.logger.info("Reaping #{zombie_tasks.size} running tasks.")
9
+ zombie_tasks.each do |task|
10
+ Rails.logger.info("Reaping task #{task.id}: #{task.title}")
11
+ task.report_dead!
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def zombie_tasks
18
+ @zombie_tasks ||= Task.zombies
19
+ end
20
+ end
21
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class RefreshCheckRunsJob < BackgroundJob
3
4
  queue_as :default
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class RefreshGithubUserJob < BackgroundJob
3
4
  queue_as :default
@@ -0,0 +1,11 @@
1
+ # frozen_string_literal: true
2
+ module Shipit
3
+ class RefreshMergeRequestJob < BackgroundJob
4
+ queue_as :default
5
+
6
+ def perform(merge_request)
7
+ merge_request.refresh!
8
+ ProcessMergeRequestsJob.perform_later(merge_request.stack)
9
+ end
10
+ end
11
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class RefreshStatusesJob < BackgroundJob
3
4
  queue_as :default
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class SetupGithubHookJob < BackgroundJob
3
4
  queue_as :default
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class UpdateEstimatedDeployDurationJob < BackgroundJob
3
4
  queue_as :default
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class UpdateGithubLastDeployedRefJob < BackgroundJob
3
4
  queue_as :default
4
5
 
5
6
  # We do not prefix 'refs/' because Octokit methods will do this automatically.
6
- BRANCH_REF_PREFIX = 'heads'.freeze
7
- DEPLOY_PREFIX = 'shipit-deploy'.freeze
7
+ BRANCH_REF_PREFIX = 'heads'
8
+ DEPLOY_PREFIX = "#{Shipit.app_name.downcase}-deploy"
8
9
 
9
10
  def perform(stack)
10
11
  stack_sha = stack.last_successful_deploy_commit&.sha
@@ -12,7 +13,7 @@ module Shipit
12
13
 
13
14
  environment = stack.environment
14
15
  stack_ref = create_full_ref(environment)
15
- client = Shipit.github.api
16
+ client = stack.github_api
16
17
 
17
18
  full_repo_name = stack.github_repo_name
18
19
 
@@ -33,7 +34,7 @@ module Shipit
33
34
  client.update_ref(repo_name, ref, new_sha)
34
35
  rescue Octokit::UnprocessableEntity => e
35
36
  error_msg = e.message
36
- if error_msg.include? "Reference does not exist"
37
+ if error_msg.include?("Reference does not exist")
37
38
  create_ref(client: client, repo_name: repo_name, ref: ref, sha: new_sha)
38
39
  else
39
40
  raise
@@ -1,10 +1,11 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  module DeferredTouch
3
4
  extend ActiveSupport::Concern
4
5
 
5
- SET_KEY = 'shipit:deferred_touches'.freeze
6
- TMP_KEY = "#{SET_KEY}:updating".freeze
7
- CACHE_KEY = "#{SET_KEY}:scheduled".freeze
6
+ SET_KEY = 'shipit:deferred_touches'
7
+ TMP_KEY = "#{SET_KEY}:updating"
8
+ CACHE_KEY = "#{SET_KEY}:scheduled"
8
9
  THROTTLE_TTL = 1.second
9
10
 
10
11
  included do
@@ -1,7 +1,8 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class AnonymousUser
3
- def present?
4
- false
4
+ def blank?
5
+ true
5
6
  end
6
7
 
7
8
  def email
@@ -34,6 +35,10 @@ module Shipit
34
35
  Shipit.authentication_disabled?
35
36
  end
36
37
 
38
+ def repositories_contributed_to
39
+ []
40
+ end
41
+
37
42
  def stacks_contributed_to
38
43
  []
39
44
  end
@@ -54,5 +59,13 @@ module Shipit
54
59
  def github_api
55
60
  Shipit.github.api
56
61
  end
62
+
63
+ def serializer_class
64
+ AnonymousUserSerializer
65
+ end
66
+
67
+ def marked_for_destruction?
68
+ true
69
+ end
57
70
  end
58
71
  end
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
- class ApiClient < ActiveRecord::Base
3
+ class ApiClient < Record
3
4
  InsufficientPermission = Class.new(StandardError)
4
5
 
5
6
  belongs_to :creator, class_name: 'User'
@@ -16,7 +17,7 @@ module Shipit
16
17
  read:hook
17
18
  write:hook
18
19
  ).freeze
19
- validates :permissions, subset: {of: PERMISSIONS}
20
+ validates :permissions, subset: { of: PERMISSIONS }
20
21
 
21
22
  class << self
22
23
  def authenticate(token)
@@ -1,5 +1,6 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
- class ApplicationRecord < ActiveRecord::Base
3
+ class ApplicationRecord < Record
3
4
  self.abstract_class = true
4
5
  end
5
6
  end
@@ -1,15 +1,18 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class CheckRun < ApplicationRecord
3
- CONCLUSIONS = %w(success failure neutral cancelled timed_out action_required).freeze
4
+ CONCLUSIONS = %w(success failure neutral cancelled timed_out action_required stale skipped).freeze
4
5
  include DeferredTouch
5
6
  include Status::Common
6
7
 
8
+ CHECK_RUN_REFRESH_DELAY = 5.seconds
9
+
7
10
  belongs_to :stack, required: true
8
11
  belongs_to :commit, required: true
9
12
 
10
13
  deferred_touch commit: :updated_at
11
14
 
12
- validates :conclusion, inclusion: {in: CONCLUSIONS, allow_nil: true}
15
+ validates :conclusion, inclusion: { in: CONCLUSIONS, allow_nil: true }
13
16
 
14
17
  after_create :enable_ci_on_stack
15
18
 
@@ -18,11 +21,30 @@ module Shipit
18
21
  create!(selector.merge(attributes))
19
22
  rescue ActiveRecord::RecordNotUnique
20
23
  record = find_by!(selector)
24
+
25
+ # Checkruns can jump between states and conclusions, and the github timestamps are low precision and unreliable.
26
+ # Since there's a conflict and the webhook seems older, enqueue a refresh.
27
+ # Persist the received data anyways, in case it is now the canonical data on GitHub despite the timestamp.
28
+ if attributes[:conclusion] != record.conclusion && record.newer_than_webhook?(attributes)
29
+ Rails.logger.warn(
30
+ "Conflicting stale checkrun received. Checkrun id: #{selector[:github_id]}, Details: #{attributes}"
31
+ )
32
+ RefreshCheckRunsJob.set(wait: CHECK_RUN_REFRESH_DELAY).perform_later(commit_id: record.commit_id)
33
+ end
34
+
21
35
  record.update!(attributes)
22
36
  record
23
37
  end
24
38
 
25
39
  def create_or_update_from_github!(stack_id, github_check_run)
40
+ checkrun_date = parse_newest_date(github_check_run)
41
+
42
+ unless checkrun_date
43
+ Rails.logger.warn("No valid timestamp found in checkrun data. Checkrun id: #{github_check_run.id}.")
44
+ RefreshCheckRunsJob.set(wait: CHECK_RUN_REFRESH_DELAY).perform_later(stack_id: stack_id)
45
+ return
46
+ end
47
+
26
48
  create_or_update_by!(
27
49
  selector: {
28
50
  github_id: github_check_run.id,
@@ -34,18 +56,29 @@ module Shipit
34
56
  title: github_check_run.output.title.to_s.truncate(1_000),
35
57
  details_url: github_check_run.details_url,
36
58
  html_url: github_check_run.html_url,
59
+ github_updated_at: checkrun_date,
37
60
  },
38
61
  )
39
62
  end
63
+
64
+ def parse_newest_date(github_check_run)
65
+ started_at = github_check_run.started_at
66
+ completed_at = github_check_run.completed_at
67
+
68
+ started_at_date = Time.parse(started_at.to_s) if started_at
69
+ completed_at_date = Time.parse(completed_at.to_s) if completed_at
70
+
71
+ [started_at_date, completed_at_date].compact.max
72
+ end
40
73
  end
41
74
 
42
75
  def state
43
76
  case conclusion
44
77
  when nil, 'action_required'
45
78
  'pending'
46
- when 'success', 'neutral'
79
+ when 'success', 'neutral', 'skipped'
47
80
  'success'
48
- when 'failure', 'cancelled'
81
+ when 'failure', 'cancelled', 'stale'
49
82
  'failure'
50
83
  when 'timed_out'
51
84
  'error'
@@ -70,6 +103,10 @@ module Shipit
70
103
  'shipit/statuses/status'
71
104
  end
72
105
 
106
+ def newer_than_webhook?(webhook_attributes)
107
+ github_updated_at && github_updated_at >= webhook_attributes[:github_updated_at]
108
+ end
109
+
73
110
  private
74
111
 
75
112
  def enable_ci_on_stack
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  module Shipit
2
3
  class CommandLineUser
3
4
  def present?
@@ -34,6 +35,10 @@ module Shipit
34
35
  Shipit.authentication_disabled?
35
36
  end
36
37
 
38
+ def repositories_contributed_to
39
+ []
40
+ end
41
+
37
42
  def stacks_contributed_to
38
43
  []
39
44
  end