shipit-engine 0.28.0 → 0.32.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 (314) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +41 -2
  3. data/Rakefile +4 -2
  4. data/app/assets/images/archive-solid.svg +1 -0
  5. data/app/assets/stylesheets/_pages/_stacks.scss +76 -3
  6. data/app/assets/stylesheets/_structure/_main.scss +2 -1
  7. data/app/assets/stylesheets/merge_status.scss +0 -3
  8. data/app/controllers/concerns/shipit/active_model_serializers_patch.rb +13 -0
  9. data/app/controllers/concerns/shipit/api/cacheable.rb +1 -0
  10. data/app/controllers/concerns/shipit/api/paginable.rb +3 -2
  11. data/app/controllers/concerns/shipit/api/rendering.rb +5 -4
  12. data/app/controllers/concerns/shipit/authentication.rb +3 -2
  13. data/app/controllers/concerns/shipit/pagination.rb +2 -1
  14. data/app/controllers/shipit/api/base_controller.rb +11 -6
  15. data/app/controllers/shipit/api/ccmenu_controller.rb +2 -1
  16. data/app/controllers/shipit/api/commits_controller.rb +2 -1
  17. data/app/controllers/shipit/api/deploys_controller.rb +4 -3
  18. data/app/controllers/shipit/api/hooks_controller.rb +6 -5
  19. data/app/controllers/shipit/api/locks_controller.rb +5 -4
  20. data/app/controllers/shipit/api/outputs_controller.rb +2 -1
  21. data/app/controllers/shipit/api/pull_requests_controller.rb +7 -6
  22. data/app/controllers/shipit/api/release_statuses_controller.rb +3 -2
  23. data/app/controllers/shipit/api/rollbacks_controller.rb +33 -0
  24. data/app/controllers/shipit/api/stacks_controller.rb +37 -5
  25. data/app/controllers/shipit/api/tasks_controller.rb +6 -5
  26. data/app/controllers/shipit/api_clients_controller.rb +50 -0
  27. data/app/controllers/shipit/ccmenu_url_controller.rb +4 -3
  28. data/app/controllers/shipit/commit_checks_controller.rb +2 -1
  29. data/app/controllers/shipit/commits_controller.rb +2 -1
  30. data/app/controllers/shipit/deploys_controller.rb +3 -2
  31. data/app/controllers/shipit/github_authentication_controller.rb +4 -3
  32. data/app/controllers/shipit/merge_status_controller.rb +19 -14
  33. data/app/controllers/shipit/pull_requests_controller.rb +3 -2
  34. data/app/controllers/shipit/release_statuses_controller.rb +3 -2
  35. data/app/controllers/shipit/rollbacks_controller.rb +3 -2
  36. data/app/controllers/shipit/shipit_controller.rb +2 -1
  37. data/app/controllers/shipit/stacks_controller.rb +78 -14
  38. data/app/controllers/shipit/status_controller.rb +2 -1
  39. data/app/controllers/shipit/tasks_controller.rb +6 -5
  40. data/app/controllers/shipit/webhooks_controller.rb +5 -132
  41. data/app/helpers/shipit/chunks_helper.rb +1 -0
  42. data/app/helpers/shipit/deploys_helper.rb +4 -3
  43. data/app/helpers/shipit/github_url_helper.rb +1 -0
  44. data/app/helpers/shipit/merge_status_helper.rb +1 -0
  45. data/app/helpers/shipit/shipit_helper.rb +1 -0
  46. data/app/helpers/shipit/stacks_helper.rb +5 -0
  47. data/app/helpers/shipit/tasks_helper.rb +1 -0
  48. data/app/jobs/shipit/background_job.rb +4 -0
  49. data/app/jobs/shipit/background_job/unique.rb +4 -1
  50. data/app/jobs/shipit/cache_deploy_spec_job.rb +1 -0
  51. data/app/jobs/shipit/chunk_rollup_job.rb +4 -0
  52. data/app/jobs/shipit/clear_git_cache_job.rb +1 -0
  53. data/app/jobs/shipit/continuous_delivery_job.rb +3 -1
  54. data/app/jobs/shipit/create_on_github_job.rb +6 -1
  55. data/app/jobs/shipit/create_release_statuses_job.rb +1 -0
  56. data/app/jobs/shipit/deferred_touch_job.rb +4 -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_stack_job.rb +3 -2
  60. data/app/jobs/shipit/emit_event_job.rb +2 -1
  61. data/app/jobs/shipit/fetch_commit_stats_job.rb +1 -0
  62. data/app/jobs/shipit/fetch_deployed_revision_job.rb +2 -1
  63. data/app/jobs/shipit/github_sync_job.rb +3 -2
  64. data/app/jobs/shipit/{mark_deploy_healty_job.rb → mark_deploy_healthy_job.rb} +1 -0
  65. data/app/jobs/shipit/merge_pull_requests_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 +14 -5
  68. data/app/jobs/shipit/purge_old_deliveries_job.rb +1 -0
  69. data/app/jobs/shipit/reap_dead_tasks_job.rb +21 -0
  70. data/app/jobs/shipit/refresh_check_runs_job.rb +1 -0
  71. data/app/jobs/shipit/refresh_github_user_job.rb +1 -0
  72. data/app/jobs/shipit/refresh_pull_request_job.rb +1 -0
  73. data/app/jobs/shipit/refresh_statuses_job.rb +1 -0
  74. data/app/jobs/shipit/setup_github_hook_job.rb +1 -0
  75. data/app/jobs/shipit/update_estimated_deploy_duration_job.rb +1 -0
  76. data/app/jobs/shipit/update_github_last_deployed_ref_job.rb +6 -3
  77. data/app/models/concerns/shipit/deferred_touch.rb +4 -3
  78. data/app/models/shipit/anonymous_user.rb +5 -0
  79. data/app/models/shipit/api_client.rb +3 -2
  80. data/app/models/shipit/application_record.rb +2 -1
  81. data/app/models/shipit/check_run.rb +4 -3
  82. data/app/models/shipit/command_line_user.rb +1 -0
  83. data/app/models/shipit/commit.rb +31 -12
  84. data/app/models/shipit/commit_checks.rb +1 -0
  85. data/app/models/shipit/commit_deployment.rb +17 -12
  86. data/app/models/shipit/commit_deployment_status.rb +8 -3
  87. data/app/models/shipit/commit_message.rb +1 -0
  88. data/app/models/shipit/delivery.rb +4 -3
  89. data/app/models/shipit/deploy.rb +40 -10
  90. data/app/models/shipit/deploy_spec.rb +22 -3
  91. data/app/models/shipit/deploy_spec/bundler_discovery.rb +2 -1
  92. data/app/models/shipit/deploy_spec/capistrano_discovery.rb +1 -0
  93. data/app/models/shipit/deploy_spec/file_system.rb +10 -3
  94. data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +1 -0
  95. data/app/models/shipit/deploy_spec/lerna_discovery.rb +1 -0
  96. data/app/models/shipit/deploy_spec/npm_discovery.rb +5 -4
  97. data/app/models/shipit/deploy_spec/pypi_discovery.rb +1 -0
  98. data/app/models/shipit/deploy_spec/rubygems_discovery.rb +1 -0
  99. data/app/models/shipit/deploy_stats.rb +58 -0
  100. data/app/models/shipit/duration.rb +3 -2
  101. data/app/models/shipit/ephemeral_commit_checks.rb +1 -0
  102. data/app/models/shipit/github_hook.rb +2 -1
  103. data/app/models/shipit/github_status.rb +3 -2
  104. data/app/models/shipit/hook.rb +6 -5
  105. data/app/models/shipit/membership.rb +3 -2
  106. data/app/models/shipit/output_chunk.rb +7 -2
  107. data/app/models/shipit/pull_request.rb +13 -7
  108. data/app/models/shipit/record.rb +18 -0
  109. data/app/models/shipit/release_status.rb +3 -2
  110. data/app/models/shipit/repository.rb +43 -0
  111. data/app/models/shipit/rollback.rb +1 -0
  112. data/app/models/shipit/stack.rb +109 -50
  113. data/app/models/shipit/status.rb +3 -2
  114. data/app/models/shipit/status/common.rb +7 -6
  115. data/app/models/shipit/status/group.rb +1 -0
  116. data/app/models/shipit/status/missing.rb +2 -1
  117. data/app/models/shipit/status/unknown.rb +2 -1
  118. data/app/models/shipit/task.rb +64 -9
  119. data/app/models/shipit/task_definition.rb +1 -0
  120. data/app/models/shipit/team.rb +2 -1
  121. data/app/models/shipit/undeployed_commit.rb +1 -0
  122. data/app/models/shipit/unlimited_api_client.rb +1 -0
  123. data/app/models/shipit/user.rb +29 -5
  124. data/app/models/shipit/variable_definition.rb +1 -0
  125. data/app/models/shipit/webhooks.rb +33 -0
  126. data/app/models/shipit/webhooks/handlers/check_suite_handler.rb +20 -0
  127. data/app/models/shipit/webhooks/handlers/handler.rb +41 -0
  128. data/app/models/shipit/webhooks/handlers/membership_handler.rb +46 -0
  129. data/app/models/shipit/webhooks/handlers/push_handler.rb +21 -0
  130. data/app/models/shipit/webhooks/handlers/status_handler.rb +27 -0
  131. data/app/serializers/concerns/shipit/conditional_attributes.rb +1 -0
  132. data/app/serializers/shipit/anonymous_user_serializer.rb +1 -0
  133. data/app/serializers/shipit/command_line_user_serializer.rb +1 -0
  134. data/app/serializers/shipit/commit_serializer.rb +1 -0
  135. data/app/serializers/shipit/deploy_serializer.rb +2 -1
  136. data/app/serializers/shipit/hook_serializer.rb +1 -0
  137. data/app/serializers/shipit/pull_request_serializer.rb +1 -0
  138. data/app/serializers/shipit/rollback_serializer.rb +1 -0
  139. data/app/serializers/shipit/short_commit_serializer.rb +1 -0
  140. data/app/serializers/shipit/stack_serializer.rb +7 -1
  141. data/app/serializers/shipit/tail_task_serializer.rb +1 -0
  142. data/app/serializers/shipit/task_serializer.rb +2 -17
  143. data/app/serializers/shipit/user_serializer.rb +6 -1
  144. data/app/validators/ascii_only_validator.rb +4 -3
  145. data/app/validators/subset_validator.rb +1 -0
  146. data/app/views/layouts/_head.html.erb +0 -0
  147. data/app/views/layouts/shipit.html.erb +6 -4
  148. data/app/views/shipit/_variables.html.erb +1 -1
  149. data/app/views/shipit/api_clients/index.html.erb +36 -0
  150. data/app/views/shipit/api_clients/new.html.erb +33 -0
  151. data/app/views/shipit/api_clients/show.html.erb +35 -0
  152. data/app/views/shipit/ccmenu/project.xml.builder +2 -1
  153. data/app/views/shipit/deploys/new.html.erb +17 -12
  154. data/app/views/shipit/deploys/show.html.erb +2 -2
  155. data/app/views/shipit/merge_status/logged_out.erb +1 -1
  156. data/app/views/shipit/stacks/_header.html.erb +27 -12
  157. data/app/views/shipit/stacks/_links.html.erb +1 -0
  158. data/app/views/shipit/stacks/all_tasks.html.erb +28 -0
  159. data/app/views/shipit/stacks/index.html.erb +7 -2
  160. data/app/views/shipit/stacks/settings.html.erb +19 -0
  161. data/app/views/shipit/stacks/statistics.html.erb +82 -0
  162. data/app/views/shipit/tasks/show.html.erb +1 -1
  163. data/config/initializers/inflections.rb +2 -1
  164. data/config/locales/en.yml +18 -5
  165. data/config/routes.rb +14 -2
  166. data/db/migrate/20191209231045_create_shipit_repositories.rb +12 -0
  167. data/db/migrate/20191209231307_add_repository_reference_to_stacks.rb +15 -0
  168. data/db/migrate/20191216162728_backfill_repository_data.rb +22 -0
  169. data/db/migrate/20191216163010_remove_repository_information_from_stacks.rb +20 -0
  170. data/db/migrate/20191219205202_add_archived_since_to_stacks.rb +6 -0
  171. data/db/migrate/20200102175621_optional_task_commits.rb +6 -0
  172. data/db/migrate/20200109132519_add_sha_to_commit_deployments.rb +5 -0
  173. data/db/migrate/20200226211925_add_index_to_tasks_status.rb +5 -0
  174. data/db/migrate/20200427135152_add_pull_request_head_sha_to_commit.rb +5 -0
  175. data/db/migrate/20200615181558_add_rollback_once_aborted_to.rb +5 -0
  176. data/lib/shipit.rb +18 -20
  177. data/lib/shipit/cast_value.rb +1 -0
  178. data/lib/shipit/command.rb +14 -18
  179. data/lib/shipit/commands.rb +5 -4
  180. data/lib/shipit/csv_serializer.rb +1 -0
  181. data/lib/shipit/deploy_commands.rb +1 -0
  182. data/lib/shipit/engine.rb +11 -2
  183. data/lib/shipit/environment_variables.rb +11 -1
  184. data/lib/shipit/first_parent_commits_iterator.rb +1 -0
  185. data/lib/shipit/flock.rb +1 -0
  186. data/lib/shipit/github_app.rb +60 -6
  187. data/lib/shipit/github_http_cache_middleware.rb +57 -0
  188. data/lib/shipit/null_serializer.rb +1 -0
  189. data/lib/shipit/octokit_check_runs.rb +3 -2
  190. data/lib/shipit/octokit_iterator.rb +3 -2
  191. data/lib/shipit/paginator.rb +3 -2
  192. data/lib/shipit/rollback_commands.rb +1 -0
  193. data/lib/shipit/same_site_cookie_middleware.rb +29 -0
  194. data/lib/shipit/simple_message_verifier.rb +1 -0
  195. data/lib/shipit/stack_commands.rb +6 -3
  196. data/lib/shipit/stat.rb +1 -0
  197. data/lib/shipit/task_commands.rb +22 -14
  198. data/lib/shipit/version.rb +2 -1
  199. data/lib/snippets/release-gem +5 -1
  200. data/lib/tasks/cron.rake +2 -0
  201. data/lib/tasks/dev.rake +3 -2
  202. data/lib/tasks/shipit.rake +16 -17
  203. data/lib/tasks/teams.rake +1 -0
  204. data/test/controllers/api/base_controller_test.rb +3 -2
  205. data/test/controllers/api/ccmenu_controller_test.rb +9 -8
  206. data/test/controllers/api/commits_controller_test.rb +3 -2
  207. data/test/controllers/api/deploys_controller_test.rb +15 -14
  208. data/test/controllers/api/hooks_controller_test.rb +8 -7
  209. data/test/controllers/api/locks_controller_test.rb +7 -6
  210. data/test/controllers/api/outputs_controller_test.rb +3 -2
  211. data/test/controllers/api/pull_requests_controller_test.rb +8 -7
  212. data/test/controllers/api/release_statuses_controller_test.rb +2 -1
  213. data/test/controllers/api/rollback_controller_test.rb +113 -0
  214. data/test/controllers/api/stacks_controller_test.rb +44 -15
  215. data/test/controllers/api/tasks_controller_test.rb +13 -12
  216. data/test/controllers/api_clients_controller_test.rb +104 -0
  217. data/test/controllers/ccmenu_controller_test.rb +4 -3
  218. data/test/controllers/commit_checks_controller_test.rb +4 -3
  219. data/test/controllers/commits_controller_test.rb +3 -2
  220. data/test/controllers/deploys_controller_test.rb +33 -22
  221. data/test/controllers/github_authentication_controller_test.rb +1 -0
  222. data/test/controllers/merge_status_controller_test.rb +27 -9
  223. data/test/controllers/pull_requests_controller_test.rb +4 -3
  224. data/test/controllers/release_statuses_controller_test.rb +3 -2
  225. data/test/controllers/rollbacks_controller_test.rb +9 -8
  226. data/test/controllers/stacks_controller_test.rb +64 -15
  227. data/test/controllers/status_controller_test.rb +1 -0
  228. data/test/controllers/tasks_controller_test.rb +20 -19
  229. data/test/controllers/webhooks_controller_test.rb +36 -9
  230. data/test/dummy/config/application.rb +1 -1
  231. data/test/dummy/config/environments/development.rb +24 -4
  232. data/test/dummy/config/environments/test.rb +2 -0
  233. data/test/dummy/db/schema.rb +25 -11
  234. data/test/dummy/db/seeds.rb +34 -17
  235. data/test/fixtures/shipit/commit_deployment_statuses.yml +4 -4
  236. data/test/fixtures/shipit/commit_deployments.yml +8 -8
  237. data/test/fixtures/shipit/commits.yml +38 -0
  238. data/test/fixtures/shipit/repositories.yml +27 -0
  239. data/test/fixtures/shipit/stacks.yml +190 -30
  240. data/test/fixtures/shipit/tasks.yml +66 -3
  241. data/test/fixtures/timeout +2 -1
  242. data/test/helpers/api_helper.rb +1 -0
  243. data/test/helpers/fixture_aliases_helper.rb +1 -0
  244. data/test/helpers/hooks_helper.rb +2 -1
  245. data/test/helpers/json_helper.rb +15 -11
  246. data/test/helpers/links_helper.rb +4 -3
  247. data/test/helpers/payloads_helper.rb +1 -0
  248. data/test/helpers/queries_helper.rb +3 -2
  249. data/test/jobs/cache_deploy_spec_job_test.rb +2 -1
  250. data/test/jobs/chunk_rollup_job_test.rb +1 -0
  251. data/test/jobs/deliver_hook_job_test.rb +2 -1
  252. data/test/jobs/destroy_stack_job_test.rb +10 -0
  253. data/test/jobs/emit_event_job_test.rb +2 -1
  254. data/test/jobs/fetch_commit_stats_job_test.rb +1 -0
  255. data/test/jobs/fetch_deployed_revision_job_test.rb +1 -0
  256. data/test/jobs/github_sync_job_test.rb +1 -0
  257. data/test/jobs/mark_deploy_healthy_job_test.rb +1 -0
  258. data/test/jobs/merge_pull_requests_job_test.rb +5 -4
  259. data/test/jobs/perform_task_job_test.rb +4 -3
  260. data/test/jobs/purge_old_deliveries_job_test.rb +1 -0
  261. data/test/jobs/reap_dead_tasks_job_test.rb +68 -0
  262. data/test/jobs/refresh_github_user_job_test.rb +1 -0
  263. data/test/jobs/refresh_status_job_test.rb +1 -0
  264. data/test/jobs/unique_job_test.rb +1 -0
  265. data/test/jobs/update_github_last_deployed_ref_job_test.rb +13 -11
  266. data/test/middleware/same_site_cookie_middleware_test.rb +52 -0
  267. data/test/models/api_client_test.rb +1 -0
  268. data/test/models/commit_checks_test.rb +1 -0
  269. data/test/models/commit_deployment_status_test.rb +34 -4
  270. data/test/models/commit_deployment_test.rb +9 -11
  271. data/test/models/commits_test.rb +99 -7
  272. data/test/models/delivery_test.rb +3 -2
  273. data/test/models/deploy_spec_test.rb +47 -42
  274. data/test/models/deploy_stats_test.rb +113 -0
  275. data/test/models/deploys_test.rb +60 -13
  276. data/test/models/duration_test.rb +1 -0
  277. data/test/models/github_hook_test.rb +1 -0
  278. data/test/models/hook_test.rb +20 -16
  279. data/test/models/membership_test.rb +1 -0
  280. data/test/models/output_chunk_test.rb +1 -0
  281. data/test/models/pull_request_test.rb +18 -11
  282. data/test/models/release_statuses_test.rb +1 -0
  283. data/test/models/rollbacks_test.rb +1 -0
  284. data/test/models/shipit/check_run_test.rb +1 -0
  285. data/test/models/shipit/repository_test.rb +77 -0
  286. data/test/models/shipit/wehbooks/handlers_test.rb +27 -0
  287. data/test/models/stacks_test.rb +110 -56
  288. data/test/models/status/group_test.rb +1 -0
  289. data/test/models/status/missing_test.rb +1 -0
  290. data/test/models/status_test.rb +1 -0
  291. data/test/models/task_definitions_test.rb +9 -8
  292. data/test/models/tasks_test.rb +18 -1
  293. data/test/models/team_test.rb +4 -2
  294. data/test/models/undeployed_commits_test.rb +14 -0
  295. data/test/models/users_test.rb +109 -1
  296. data/test/test_command_integration.rb +3 -2
  297. data/test/test_helper.rb +38 -34
  298. data/test/unit/anonymous_user_serializer_test.rb +14 -0
  299. data/test/unit/command_test.rb +12 -7
  300. data/test/unit/commands_test.rb +1 -0
  301. data/test/unit/commit_serializer_test.rb +16 -0
  302. data/test/unit/csv_serializer_test.rb +3 -2
  303. data/test/unit/deploy_commands_test.rb +14 -4
  304. data/test/unit/deploy_serializer_test.rb +17 -0
  305. data/test/unit/environment_variables_test.rb +5 -4
  306. data/test/unit/github_app_test.rb +165 -0
  307. data/test/unit/github_url_helper_test.rb +1 -0
  308. data/test/unit/rollback_commands_test.rb +2 -1
  309. data/test/unit/shipit_helper_test.rb +17 -0
  310. data/test/unit/shipit_test.rb +1 -0
  311. data/test/unit/user_serializer_test.rb +14 -0
  312. data/test/unit/variable_definition_test.rb +1 -0
  313. metadata +215 -157
  314. data/lib/shipit/strip_cache_control.rb +0 -40
@@ -0,0 +1,113 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ module Shipit
5
+ class DeployStatsTest < ActiveSupport::TestCase
6
+ def setup
7
+ @stack = shipit_stacks(:shipit_stats)
8
+ @stats = Shipit::DeployStats.new(@stack.deploys.not_active)
9
+ @old_deploys = @stack.deploys.not_active.where(created_at: 62.minutes.ago..32.minutes.ago)
10
+ @new_deploys = @stack.deploys.not_active.where("created_at > ?", 32.minutes.ago)
11
+ end
12
+
13
+ test "#average_duration is accurate" do
14
+ assert_equal 225.0, @stats.average_duration
15
+ end
16
+
17
+ test "#median_duration is accurate" do
18
+ assert_equal 210.0, @stats.median_duration
19
+ end
20
+
21
+ test "#max_duration is accurate" do
22
+ assert_equal 360.0, @stats.max_duration
23
+ end
24
+
25
+ test "#min_duration is accurate" do
26
+ assert_equal 120.0, @stats.min_duration
27
+ end
28
+
29
+ test "#success_rate is accurate" do
30
+ assert_equal 75.0, @stats.success_rate
31
+ end
32
+
33
+ test "#average_duration handles empty deploy data" do
34
+ stats = Shipit::DeployStats.new([])
35
+ assert_nil stats.average_duration
36
+ end
37
+
38
+ test "#median_duration handles empty deploy data" do
39
+ stats = Shipit::DeployStats.new([])
40
+ assert_nil stats.median_duration
41
+ end
42
+
43
+ test "#max_duration handles empty deploy data" do
44
+ stats = Shipit::DeployStats.new([])
45
+ assert_nil stats.max_duration
46
+ end
47
+
48
+ test "#min_duration handles empty deploy data" do
49
+ stats = Shipit::DeployStats.new([])
50
+ assert_nil stats.min_duration
51
+ end
52
+
53
+ test "#success_rate handles empty deploy data" do
54
+ stats = Shipit::DeployStats.new([])
55
+ assert_nil stats.success_rate
56
+ end
57
+
58
+ test "#compare count handles empty compare count" do
59
+ comparison = Shipit::DeployStats.new([])
60
+ results = @stats.compare(comparison)
61
+ assert_equal 400, results[:count]
62
+ end
63
+
64
+ test "#compare average and median handles empty array" do
65
+ comparison = Shipit::DeployStats.new([])
66
+ results = @stats.compare(comparison)
67
+ assert_nil results[:average_duration]
68
+ assert_nil results[:median_duration]
69
+ end
70
+
71
+ test "#compare average is accurate when negative" do
72
+ new_data = Shipit::DeployStats.new(@new_deploys)
73
+ old_data = Shipit::DeployStats.new(@old_deploys)
74
+ results = new_data.compare(old_data)
75
+ assert_equal(-53.84615384615385, results[:average_duration])
76
+ end
77
+
78
+ test "#compare median is accurate when negative" do
79
+ new_data = Shipit::DeployStats.new(@new_deploys)
80
+ old_data = Shipit::DeployStats.new(@old_deploys)
81
+ results = new_data.compare(old_data)
82
+ assert_equal(-50, results[:median_duration])
83
+ end
84
+
85
+ test "#compare count is accurate when negative" do
86
+ new_data = Shipit::DeployStats.new(@new_deploys)
87
+ old_data = Shipit::DeployStats.new(@old_deploys)
88
+ results = new_data.compare(old_data)
89
+ assert_equal(-66.66666666666666, results[:count])
90
+ end
91
+
92
+ test "#compare average is accurate" do
93
+ old_data = Shipit::DeployStats.new(@new_deploys)
94
+ new_data = Shipit::DeployStats.new(@old_deploys)
95
+ results = new_data.compare(old_data)
96
+ assert_equal(116.66666666666667, results[:average_duration])
97
+ end
98
+
99
+ test "#compare median is accurate" do
100
+ old_data = Shipit::DeployStats.new(@new_deploys)
101
+ new_data = Shipit::DeployStats.new(@old_deploys)
102
+ results = new_data.compare(old_data)
103
+ assert_equal(100, results[:median_duration])
104
+ end
105
+
106
+ test "#compare count is accurate" do
107
+ old_data = Shipit::DeployStats.new(@new_deploys)
108
+ new_data = Shipit::DeployStats.new(@old_deploys)
109
+ results = new_data.compare(old_data)
110
+ assert_equal(200, results[:count])
111
+ end
112
+ end
113
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -199,6 +200,7 @@ module Shipit
199
200
  since_commit: shipit.commits.first,
200
201
  until_commit: shipit.commits.last,
201
202
  )
203
+ deploy.stubs(:pull_request_head_for_commit).returns(nil)
202
204
 
203
205
  expect_event(deploy)
204
206
  deploy.save!
@@ -246,6 +248,8 @@ module Shipit
246
248
  end
247
249
 
248
250
  test "transitioning to success enqueues a last-deployed git reference update" do
251
+ Shipit.stubs(:update_latest_deployed_ref).returns(true)
252
+
249
253
  @deploy = shipit_deploys(:shipit_running)
250
254
  assert_enqueued_with(job: UpdateGithubLastDeployedRefJob, args: [@deploy.stack]) do
251
255
  @deploy.complete!
@@ -300,15 +304,17 @@ module Shipit
300
304
  end
301
305
  end
302
306
 
303
- test "creating a deploy creates one CommitDeployment per commit" do
304
- shipit = shipit_stacks(:shipit)
305
- deploy = shipit.deploys.build(
306
- since_commit: shipit.commits.first,
307
- until_commit: shipit.commits.last,
308
- )
307
+ test "transitioning to aborted schedule a rollback to the designated deploy if set" do
308
+ @rollback_to = shipit_deploys(:shipit_pending)
309
+ @deploy = shipit_deploys(:shipit_running)
310
+ @deploy.ping
311
+ @deploy.pid = 42
312
+ @deploy.abort!(rollback_once_aborted: true, rollback_once_aborted_to: @rollback_to, aborted_by: @user)
309
313
 
310
- assert_difference -> { CommitDeployment.count }, deploy.commits.size do
311
- deploy.save!
314
+ assert_difference -> { @stack.rollbacks.count }, 1 do
315
+ assert_enqueued_with(job: PerformTaskJob) do
316
+ @deploy.aborted!
317
+ end
312
318
  end
313
319
  end
314
320
 
@@ -338,10 +344,9 @@ module Shipit
338
344
  assert_equal shipit_commits(:second), @stack.last_deployed_commit
339
345
  end
340
346
 
341
- def create_test_stack
347
+ def create_test_stack(repository: Shipit::Repository.find_or_create_by!(owner: "shopify-test", name: "shipit-engine-test"))
342
348
  Shipit::Stack.create(
343
- repo_owner: "shopify-test",
344
- repo_name: "shipit-engine-test",
349
+ repository: repository,
345
350
  environment: 'production',
346
351
  branch: "master",
347
352
  merge_queue_enabled: true,
@@ -441,6 +446,20 @@ module Shipit
441
446
  assert_equal "Shipit::Rollback", last_deploy.type
442
447
  end
443
448
 
449
+ test "#trigger_revert uses rollback_to if set" do
450
+ test_stack = create_test_stack
451
+ test_stack.save
452
+ test_stack.reload
453
+
454
+ running_deploy = shipit_deploys(:shipit_running)
455
+ rollback_to = shipit_deploys(:shipit_pending)
456
+
457
+ final_rollback = running_deploy.trigger_revert(rollback_to: rollback_to)
458
+
459
+ assert_equal "Shipit::Rollback", final_rollback.type
460
+ assert_equal 4, final_rollback.until_commit_id
461
+ end
462
+
444
463
  test "#trigger_revert skips unsuccessful deploys when reverting" do
445
464
  user_id = @user.id
446
465
  test_stack = create_test_stack
@@ -552,8 +571,7 @@ module Shipit
552
571
  user_id = @user.id
553
572
  test_stack = create_test_stack
554
573
  test_stack.save
555
- other_stack = create_test_stack
556
- other_stack.repo_name += "_other"
574
+ other_stack = create_test_stack(repository: Shipit::Repository.create!(owner: "_", name: "_some-other-repository"))
557
575
  other_stack.save
558
576
  other_stack.reload
559
577
  stack_id = test_stack.id
@@ -860,6 +878,35 @@ module Shipit
860
878
  end
861
879
  end
862
880
 
881
+ test "succeeding a deploy creates CommitDeploymentStatuses" do
882
+ @deploy = shipit_deploys(:shipit_running)
883
+ refute_empty @deploy.commit_deployments
884
+
885
+ assert_difference -> { CommitDeploymentStatus.count }, @deploy.commit_deployments.size do
886
+ @deploy.report_complete!
887
+ end
888
+
889
+ assert_equal 'success', CommitDeploymentStatus.last.status
890
+ end
891
+
892
+ test "creates one CommitDeployment and status per commit, and one more for the batch head" do
893
+ template_task = shipit_tasks(:shipit_pending)
894
+ deploy = template_task.stack.deploys.build(
895
+ since_commit: template_task.since_commit,
896
+ until_commit: template_task.until_commit,
897
+ )
898
+
899
+ expected_delta = deploy.commits.select(&:pull_request?).size + 1
900
+ assert_difference -> { CommitDeployment.count }, expected_delta do
901
+ assert_difference -> { CommitDeploymentStatus.count }, expected_delta do
902
+ deploy.save!
903
+ end
904
+ end
905
+
906
+ refute_nil CommitDeployment.find_by(sha: '6dcb09b5b57875f334f61aebed695e2e4193db5e')
907
+ refute_nil CommitDeployment.find_by(sha: deploy.until_commit.sha)
908
+ end
909
+
863
910
  private
864
911
 
865
912
  def expect_event(deploy)
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -50,26 +51,29 @@ module Shipit
50
51
  end
51
52
 
52
53
  test ".emit calls #deliver on internal hooks" do
53
- begin
54
- original_receivers = Shipit.internal_hook_receivers
55
- FakeReceiver = Module.new
56
- FakeReceiver.expects(:deliver).with(:deploy, @stack, 'foo' => 42)
54
+ original_receivers = Shipit.internal_hook_receivers
55
+ FakeReceiver = Module.new
56
+ FakeReceiver.expects(:deliver).with(:deploy, @stack, 'foo' => 42)
57
57
 
58
- Shipit.internal_hook_receivers << FakeReceiver
59
- Hook.emit(:deploy, @stack, 'foo' => 42)
60
- ensure
61
- Shipit.internal_hook_receivers = original_receivers
62
- end
58
+ Shipit.internal_hook_receivers << FakeReceiver
59
+ Hook.emit(:deploy, @stack, 'foo' => 42)
60
+ ensure
61
+ Shipit.internal_hook_receivers = original_receivers
63
62
  end
64
63
 
65
64
  test ".emit calls no internal hooks if there are no internal_hook_receivers" do
66
- begin
67
- original_receivers = Shipit.internal_hook_receivers
68
- Shipit.internal_hook_receivers = nil
69
- Hook.emit(:deploy, @stack, 'foo' => 42)
70
- ensure
71
- Shipit.internal_hook_receivers = original_receivers
72
- end
65
+ original_receivers = Shipit.internal_hook_receivers
66
+ Shipit.internal_hook_receivers = nil
67
+ Hook.emit(:deploy, @stack, 'foo' => 42)
68
+ ensure
69
+ Shipit.internal_hook_receivers = original_receivers
70
+ end
71
+
72
+ test ".coerce_payload coerces anonymous user correctly" do
73
+ locked_stack = Stack.first
74
+ locked_stack.lock("Some Reason", nil)
75
+ serialized = Hook.coerce_payload(stack: locked_stack)
76
+ assert_json("stack.lock_author.anonymous", true, document: serialized)
73
77
  end
74
78
  end
75
79
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -116,7 +117,7 @@ module Shipit
116
117
  )
117
118
  end
118
119
 
119
- Shipit.github.api.expects(:statuses).with(@stack.github_repo_name, head_sha).returns([stub(
120
+ Shipit.github.api.expects(:statuses).with(@stack.github_repo_name, head_sha, per_page: 100).returns([stub(
120
121
  state: 'success',
121
122
  description: nil,
122
123
  context: 'default',
@@ -183,23 +184,29 @@ module Shipit
183
184
  refute_predicate @pr, :rejected?
184
185
  end
185
186
 
186
- test "#reject_unless_mergeable! reject the PR if it has a missing CI status" do
187
+ test "#reject_unless_mergeable! reject the PR if it has a missing required CI status" do
188
+ @pr.stack.cached_deploy_spec.stubs(:required_statuses).returns(['ci/circle'])
187
189
  @pr.head.statuses.where(context: 'ci/circle').delete_all
188
190
 
189
- assert_predicate @pr, :all_status_checks_passed?
191
+ refute_predicate @pr, :all_status_checks_passed?
190
192
  refute_predicate @pr, :any_status_checks_failed?
191
- assert_equal false, @pr.reject_unless_mergeable!
192
- refute_predicate @pr, :rejected?
193
+ assert_predicate @pr, :any_status_checks_missing?
194
+ assert_equal true, @pr.reject_unless_mergeable!
195
+ assert_predicate @pr, :rejected?
196
+ assert_equal 'ci_missing', @pr.rejection_reason
193
197
  end
194
198
 
195
199
  test "#reject_unless_mergeable! reject the PR if it has a missing CI status (multi-status)" do
200
+ @pr.stack.cached_deploy_spec.stubs(:required_statuses).returns(['ci/circle'])
196
201
  @pr.head.statuses.where(context: 'ci/circle').delete_all
197
202
  @pr.head.statuses.create!(stack: @pr.stack, state: 'success', context: 'ci/travis')
198
203
 
199
- assert_predicate @pr, :all_status_checks_passed?
204
+ refute_predicate @pr, :all_status_checks_passed?
200
205
  refute_predicate @pr, :any_status_checks_failed?
201
- assert_equal false, @pr.reject_unless_mergeable!
202
- refute_predicate @pr, :rejected?
206
+ assert_predicate @pr, :any_status_checks_missing?
207
+ assert_equal true, @pr.reject_unless_mergeable!
208
+ assert_predicate @pr, :rejected?
209
+ assert_equal 'ci_missing', @pr.rejection_reason
203
210
  end
204
211
 
205
212
  test "#reject_unless_mergeable! rejects the PR if it is stale" do
@@ -265,7 +272,7 @@ module Shipit
265
272
  behind_by: 10,
266
273
  ),
267
274
  )
268
- spec = {'merge' => {'max_divergence' => {'commits' => 1}}}
275
+ spec = { 'merge' => { 'max_divergence' => { 'commits' => 1 } } }
269
276
  @pr.stack.cached_deploy_spec = DeploySpec.new(spec)
270
277
  assert_predicate @pr, :stale?
271
278
  end
@@ -273,14 +280,14 @@ module Shipit
273
280
  test "#stale? returns true when the branch falls behind the maximum age" do
274
281
  @pr.base_commit = shipit_commits(:second)
275
282
  @pr.head.committed_at = 2.hours.ago
276
- spec = {'merge' => {'max_divergence' => {'age' => '1h'}}}
283
+ spec = { 'merge' => { 'max_divergence' => { 'age' => '1h' } } }
277
284
  @pr.stack.cached_deploy_spec = DeploySpec.new(spec)
278
285
  assert_predicate @pr, :stale?
279
286
  end
280
287
 
281
288
  test "#stale? is false when base_commit information is missing" do
282
289
  @pr.base_commit = nil
283
- spec = {'merge' => {'max_divergence' => {'age' => '1h', 'commits' => 10}}}
290
+ spec = { 'merge' => { 'max_divergence' => { 'age' => '1h', 'commits' => 10 } } }
284
291
  @pr.stack.cached_deploy_spec = DeploySpec.new(spec)
285
292
  refute_predicate @pr, :stale?
286
293
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -0,0 +1,77 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ module Shipit
5
+ class RepositoryTest < ActiveSupport::TestCase
6
+ setup do
7
+ @repository = shipit_repositories(:shipit)
8
+ end
9
+
10
+ test "owner, and name uniqueness is enforced" do
11
+ clone = Repository.new(@repository.attributes.except('id'))
12
+ refute clone.save
13
+ assert_equal ["cannot be used more than once"], clone.errors[:name]
14
+ end
15
+
16
+ test "owner, name, and environment can only be ASCII" do
17
+ @repository.update(owner: 'héllò', name: 'wørld')
18
+ refute_predicate @repository, :valid?
19
+ end
20
+
21
+ test "owner and name are case insensitive" do
22
+ assert_no_difference -> { Repository.count } do
23
+ error = assert_raises ActiveRecord::RecordInvalid do
24
+ Repository.create!(
25
+ owner: @repository.owner.upcase,
26
+ name: @repository.name.upcase,
27
+ )
28
+ end
29
+ assert_equal 'Validation failed: Name cannot be used more than once', error.message
30
+ end
31
+
32
+ new_repository = Repository.create!(owner: 'FOO', name: 'BAR')
33
+ assert_equal new_repository, Repository.find_by(owner: 'foo', name: 'bar')
34
+ end
35
+
36
+ test "owner is automatically downcased" do
37
+ @repository.owner = 'George'
38
+ assert_equal 'george', @repository.owner
39
+ end
40
+
41
+ test "name is automatically downcased" do
42
+ @repository.name = 'Cyclim.se'
43
+ assert_equal 'cyclim.se', @repository.name
44
+ end
45
+
46
+ test "owner cannot contain a `/`" do
47
+ assert @repository.valid?
48
+ @repository.owner = 'foo/bar'
49
+ refute @repository.valid?
50
+ end
51
+
52
+ test "name cannot contain a `/`" do
53
+ assert @repository.valid?
54
+ @repository.name = 'foo/bar'
55
+ refute @repository.valid?
56
+ end
57
+
58
+ test "http_url" do
59
+ assert_equal "https://github.com/#{@repository.owner}/#{@repository.name}", @repository.http_url
60
+ end
61
+
62
+ test "git_url" do
63
+ assert_equal "https://github.com/#{@repository.owner}/#{@repository.name}.git", @repository.git_url
64
+ end
65
+
66
+ test "from_github_repo_name" do
67
+ owner = "repository-owner"
68
+ name = "repository-name"
69
+ github_repo_name = [owner, name].join("/")
70
+ expected_repository = Repository.create(owner: owner, name: name)
71
+
72
+ found_repository = Repository.from_github_repo_name(github_repo_name)
73
+
74
+ assert_equal(expected_repository, found_repository)
75
+ end
76
+ end
77
+ end