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
@@ -1,8 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  path = './fixtures/timeout'
4
5
  buffer = []
5
- command = Shipit::Command.new({path => {'timeout' => 2}}, env: {}, chdir: __dir__)
6
+ command = Shipit::Command.new({ path => { 'timeout' => 2 } }, env: {}, chdir: __dir__)
6
7
  begin
7
8
  command.stream! do |chunk|
8
9
  buffer << chunk
@@ -24,5 +25,5 @@ unless buffer.join == expected_output.join
24
25
  puts "Got: ------------"
25
26
  puts buffer.map(&:inspect).join("\n")
26
27
  puts "-----------------"
27
- exit 1
28
+ exit(1)
28
29
  end
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
1
2
  ENV["RAILS_ENV"] ||= "test"
2
3
 
3
4
  require 'simplecov'
4
- SimpleCov.start 'rails'
5
+ SimpleCov.start('rails') do
6
+ enable_coverage :branch
7
+ end
5
8
 
6
- require 'fakeweb'
7
- FakeWeb.allow_net_connect = false
9
+ require 'webmock/minitest'
8
10
 
9
11
  require File.expand_path('../../test/dummy/config/environment.rb', __FILE__)
10
12
  ActiveRecord::Migrator.migrations_paths = [
@@ -12,13 +14,13 @@ ActiveRecord::Migrator.migrations_paths = [
12
14
  File.expand_path('../../db/migrate', __FILE__),
13
15
  ]
14
16
  require 'rails/test_help'
15
- require 'mocha/mini_test'
17
+ require 'mocha/minitest'
16
18
  require 'spy/integration'
17
19
 
18
20
  # Load fixtures from the engine
19
21
  if ActiveSupport::TestCase.respond_to?(:fixture_path=)
20
22
  ActiveSupport::TestCase.fixture_path = File.expand_path("../fixtures", __FILE__)
21
- ActiveSupport::TestCase.fixtures :all
23
+ ActiveSupport::TestCase.fixtures(:all)
22
24
  end
23
25
 
24
26
  Dir[File.expand_path('../helpers/**/*.rb', __FILE__)].each do |helper|
@@ -30,41 +32,43 @@ begin
30
32
  rescue LoadError
31
33
  end
32
34
 
33
- class ActiveSupport::TestCase
34
- include PayloadsHelper
35
- include FixtureAliasesHelper
36
- include QueriesHelper
37
- include JSONHelper
38
- include LinksHelper
39
- include ApiHelper
40
- include HooksHelper
41
- include ActiveJob::TestHelper
35
+ module ActiveSupport
36
+ class TestCase
37
+ include PayloadsHelper
38
+ include FixtureAliasesHelper
39
+ include QueriesHelper
40
+ include JSONHelper
41
+ include LinksHelper
42
+ include ApiHelper
43
+ include HooksHelper
44
+ include ActiveJob::TestHelper
42
45
 
43
- setup do
44
- @routes = Shipit::Engine.routes
45
- Shipit.github.api.stubs(:login).returns('shipit')
46
- end
46
+ setup do
47
+ @routes = Shipit::Engine.routes
48
+ Shipit.github.api.stubs(:login).returns('shipit')
49
+ end
47
50
 
48
- teardown do
49
- Shipit.redis.flushdb
50
- Shipit.instance_variable_names.each do |name|
51
- next if %w(@mocha @redis).include?(name)
52
- Shipit.remove_instance_variable(name)
51
+ teardown do
52
+ Shipit.redis.flushdb
53
+ Shipit.instance_variable_names.each do |name|
54
+ next if %w(@mocha @redis).include?(name)
55
+ Shipit.remove_instance_variable(name)
56
+ end
53
57
  end
54
- end
55
58
 
56
- ActiveRecord::Migration.check_pending!
59
+ ActiveRecord::Migration.check_pending!
57
60
 
58
- # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
59
- #
60
- # Note: You'll currently still have to declare fixtures explicitly in integration tests
61
- # -- they do not yet inherit this setting
62
- fixtures :all
61
+ # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
62
+ #
63
+ # Note: You'll currently still have to declare fixtures explicitly in integration tests
64
+ # -- they do not yet inherit this setting
65
+ fixtures :all
63
66
 
64
- # Add more helper methods to be used by all tests here...
65
- private
67
+ # Add more helper methods to be used by all tests here...
68
+ private
66
69
 
67
- def resource(data)
68
- Sawyer::Resource.new(Sawyer::Agent.new('http://example.com'), data)
70
+ def resource(data)
71
+ Sawyer::Resource.new(Sawyer::Agent.new('http://example.com'), data)
72
+ end
69
73
  end
70
74
  end
@@ -0,0 +1,14 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ module Shipit
5
+ class AnonymousUserSerializerTest < ActiveSupport::TestCase
6
+ test 'sets anonymous to true' do
7
+ user = AnonymousUser.new
8
+ serializer = ActiveModel::Serializer.serializer_for(user)
9
+ assert_equal AnonymousUserSerializer, serializer
10
+ serialized = serializer.new(user).to_json
11
+ assert_json("anonymous", true, document: serialized)
12
+ end
13
+ end
14
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -9,28 +10,32 @@ module Shipit
9
10
  end
10
11
 
11
12
  test "#interpolate_environment_variables replace environment variables by their value" do
12
- command = Command.new('cap $ENVIRONMENT deploy', env: {'ENVIRONMENT' => 'production'}, chdir: '.')
13
+ command = Command.new('cap $ENVIRONMENT deploy', env: { 'ENVIRONMENT' => 'production' }, chdir: '.')
13
14
  assert_equal [%(cap production deploy)], command.interpolated_arguments
14
15
  end
15
16
 
16
17
  test "#interpolate_environment_variables coerce nil to empty string" do
17
- command = Command.new('cap $FOO deploy', env: {'ENVIRONMENT' => 'production'}, chdir: '.')
18
+ command = Command.new('cap $FOO deploy', env: { 'ENVIRONMENT' => 'production' }, chdir: '.')
18
19
  assert_equal [%(cap '' deploy)], command.interpolated_arguments
19
20
  end
20
21
 
21
22
  test '#interpolate_environment_variables escape the variable contents' do
22
23
  malicious_string = '$(echo pwnd)'
23
- command = Command.new('echo $FOO', env: {'FOO' => malicious_string}, chdir: '.')
24
+ command = Command.new('echo $FOO', env: { 'FOO' => malicious_string }, chdir: '.')
24
25
  assert_equal malicious_string, command.run.chomp
25
26
  end
26
27
 
27
28
  test "#interpolate_environment_variables fallback to ENV" do
28
- command = Command.new('cap $LANG deploy', env: {'ENVIRONMENT' => 'production'}, chdir: '.')
29
- assert_equal [%(cap #{ENV['LANG']} deploy)], command.interpolated_arguments
29
+ previous = ENV['SHIPIT_TEST']
30
+ ENV['SHIPIT_TEST'] = 'quux'
31
+ command = Command.new('cap $SHIPIT_TEST deploy', env: { 'ENVIRONMENT' => 'production' }, chdir: '.')
32
+ assert_equal([%(cap quux deploy)], command.interpolated_arguments)
33
+ ensure
34
+ ENV['SHIPIT_TEST'] = previous
30
35
  end
31
36
 
32
37
  test "#timeout is 5 minutes by default" do
33
- command = Command.new('cap $LANG deploy', env: {'ENVIRONMENT' => 'production'}, chdir: '.')
38
+ command = Command.new('cap $LANG deploy', env: { 'ENVIRONMENT' => 'production' }, chdir: '.')
34
39
  assert_equal 5.minutes.to_i, command.timeout
35
40
  end
36
41
 
@@ -40,7 +45,7 @@ module Shipit
40
45
  end
41
46
 
42
47
  test "#timeout returns the command option timeout over the `default_timeout` if present" do
43
- command = Command.new({'cap $LANG deploy' => {'timeout' => 10}}, default_timeout: 5, env: {}, chdir: '.')
48
+ command = Command.new({ 'cap $LANG deploy' => { 'timeout' => 10 } }, default_timeout: 5, env: {}, chdir: '.')
44
49
  assert_equal 10, command.timeout
45
50
  end
46
51
 
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ module Shipit
5
+ class CommitSerializerTest < ActiveSupport::TestCase
6
+ test 'commit includes author object' do
7
+ commit = shipit_commits(:first)
8
+
9
+ serializer = ActiveModel::Serializer.serializer_for(commit)
10
+ assert_equal CommitSerializer, serializer
11
+ serialized = serializer.new(commit).to_json
12
+
13
+ assert_json("author.name", commit.author.name, document: serialized)
14
+ end
15
+ end
16
+ end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -28,7 +29,7 @@ module Shipit
28
29
  def assert_dumped(expected, object)
29
30
  message = "Expected CSVSerializer.dump(#{object.inspect}) to eq #{expected.inspect}"
30
31
  if expected.nil?
31
- assert_nil Shipit::CSVSerializer.dump(object), message
32
+ assert_nil(Shipit::CSVSerializer.dump(object), message)
32
33
  else
33
34
  assert_equal(expected, Shipit::CSVSerializer.dump(object), message)
34
35
  end
@@ -37,7 +38,7 @@ module Shipit
37
38
  def assert_loaded(expected, payload)
38
39
  message = "Expected CSVSerializer.load(#{payload.inspect}) to eq #{expected.inspect}"
39
40
  if expected.nil?
40
- assert_nil Shipit::CSVSerializer.load(payload), message
41
+ assert_nil(Shipit::CSVSerializer.load(payload), message)
41
42
  else
42
43
  assert_equal(expected, Shipit::CSVSerializer.load(payload), message)
43
44
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -10,7 +11,7 @@ module Shipit
10
11
  dependencies_steps!: ['bundle install --some-args'],
11
12
  deploy_steps!: ['bundle exec cap $ENVIRONMENT deploy'],
12
13
  rollback_steps!: ['bundle exec cap $ENVIRONMENT deploy:rollback'],
13
- machine_env: {'GLOBAL' => '1'},
14
+ machine_env: { 'GLOBAL' => '1' },
14
15
  directory: nil,
15
16
  clear_working_directory?: true,
16
17
  )
@@ -62,8 +63,8 @@ module Shipit
62
63
  commands = @commands.clone
63
64
  assert_equal 2, commands.size
64
65
  clone_args = [
65
- 'git', 'clone', '--local',
66
- '--origin', 'cache',
66
+ 'git', 'clone', '--quiet',
67
+ '--local', '--origin', 'cache',
67
68
  @stack.git_path, @deploy.working_directory
68
69
  ]
69
70
  assert_equal clone_args, commands.first.args
@@ -190,7 +191,7 @@ module Shipit
190
191
  end
191
192
 
192
193
  test "the deploy's `env` is merged in ENVIRONMENT" do
193
- @deploy.env = {'FOO' => 'BAR'}
194
+ @deploy.env = { 'FOO' => 'BAR' }
194
195
  command = @commands.install_dependencies.first
195
196
  assert_equal 'BAR', command.env['FOO']
196
197
  end
@@ -212,6 +213,15 @@ module Shipit
212
213
  assert_equal walrus.name, @commands.env['GIT_COMMITTER_NAME']
213
214
  end
214
215
 
216
+ test "GitHub repo details are exposed" do
217
+ assert_equal 'shopify', @commands.env['GITHUB_REPO_OWNER']
218
+ assert_equal 'shipit-engine', @commands.env['GITHUB_REPO_NAME']
219
+ end
220
+
221
+ test "Stack DEPLOY_URL is exposed" do
222
+ assert_equal "https://shipit.shopify.com", @commands.env['DEPLOY_URL']
223
+ end
224
+
215
225
  test "#clear_working_directory rm -rf the working directory" do
216
226
  FileUtils.expects(:rm_rf).with(@deploy.working_directory)
217
227
  @commands.clear_working_directory
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+ require 'test_helper'
3
+
4
+ module Shipit
5
+ class DeploySerializerTest < ActiveSupport::TestCase
6
+ test 'deploy commits includes author object' do
7
+ deploy = shipit_deploys(:shipit)
8
+ first_commit_author = deploy.commits.first.author
9
+
10
+ serializer = ActiveModel::Serializer.serializer_for(deploy)
11
+ assert_equal DeploySerializer, serializer
12
+ serialized = serializer.new(deploy).to_json
13
+
14
+ assert_json("commits.0.author.name", first_commit_author.name, document: serialized)
15
+ end
16
+ end
17
+ end
@@ -1,11 +1,12 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
4
5
  class EnvironmentVariablesTest < ActiveSupport::TestCase
5
6
  def setup
6
7
  variable_defs = [
7
- {"name" => "FOO", "title" => "Set to 0 to foo", "default" => 1},
8
- {"name" => "BAR", "title" => "Set to 1 to bar", "default" => 0},
8
+ { "name" => "FOO", "title" => "Set to 0 to foo", "default" => 1 },
9
+ { "name" => "BAR", "title" => "Set to 1 to bar", "default" => 0 },
9
10
  ]
10
11
  @variable_definitions = variable_defs.map(&VariableDefinition.method(:new))
11
12
  end
@@ -16,7 +17,7 @@ module Shipit
16
17
  end
17
18
 
18
19
  test 'correctly sanitizes env variables' do
19
- env = {'FOO' => 1, 'BAR' => 1}
20
+ env = { 'FOO' => 1, 'BAR' => 1 }
20
21
  assert_equal env, EnvironmentVariables.with(env).permit(@variable_definitions)
21
22
  end
22
23
 
@@ -27,7 +28,7 @@ module Shipit
27
28
  end
28
29
 
29
30
  test 'throws an exception when a variable is not whitelisted' do
30
- env = {'UNSAFE_VARIABLE' => 1}
31
+ env = { 'UNSAFE_VARIABLE' => 1 }
31
32
  assert_raises(EnvironmentVariables::NotPermitted) do
32
33
  EnvironmentVariables.with(env).permit(@variable_definitions)
33
34
  end
@@ -1,3 +1,4 @@
1
+ # frozen_string_literal: true
1
2
  require 'test_helper'
2
3
 
3
4
  module Shipit
@@ -5,6 +6,14 @@ module Shipit
5
6
  setup do
6
7
  @github = app
7
8
  @enterprise = app(domain: 'github.example.com')
9
+ @rails_env = Rails.env
10
+ @token_cache_key = 'github:integration:access-token'
11
+ Rails.cache.delete(@token_cache_key)
12
+ end
13
+
14
+ teardown do
15
+ Rails.env = @rails_env
16
+ Rails.cache.delete(@token_cache_key)
8
17
  end
9
18
 
10
19
  test "#initialize doesn't raise if given an empty config" do
@@ -13,6 +22,34 @@ module Shipit
13
22
  end
14
23
  end
15
24
 
25
+ test "#api_status" do
26
+ stub_request(:get, "https://www.githubstatus.com/api/v2/components.json").to_return(
27
+ status: 200,
28
+ body: %(
29
+ {
30
+ "page":{},
31
+ "components":[
32
+ {
33
+ "id":"brv1bkgrwx7q",
34
+ "name":"API Requests",
35
+ "status":"operational",
36
+ "created_at":"2017-01-31T20:01:46.621Z",
37
+ "updated_at":"2019-07-23T18:41:18.197Z",
38
+ "position":2,
39
+ "description":"Requests for GitHub APIs",
40
+ "showcase":false,
41
+ "group_id":null,
42
+ "page_id":"kctbh9vrtdwd",
43
+ "group":false,
44
+ "only_show_if_degraded":false
45
+ }
46
+ ]
47
+ }
48
+ ),
49
+ )
50
+ assert_equal "operational", app.api_status[:status]
51
+ end
52
+
16
53
  test "#domain defaults to github.com" do
17
54
  assert_equal 'github.com', @github.domain
18
55
  end
@@ -23,6 +60,11 @@ module Shipit
23
60
  assert_equal 'https://github.example.com/foo/bar/baz', @enterprise.url('foo/bar', 'baz')
24
61
  end
25
62
 
63
+ test "#new_client retruns an Octokit::Client configured to use the github installation" do
64
+ assert_equal 'https://github.example.com/', @enterprise.new_client.web_endpoint
65
+ assert_equal 'https://github.example.com/api/v3/', @enterprise.new_client.api_endpoint
66
+ end
67
+
26
68
  test "#oauth_config.last[:client_options] is nil if domain is not overriden" do
27
69
  assert_nil @github.oauth_config.last[:client_options][:site]
28
70
  end
@@ -31,6 +73,129 @@ module Shipit
31
73
  assert_equal 'https://github.example.com/api/v3/', @enterprise.oauth_config.last[:client_options][:site]
32
74
  end
33
75
 
76
+ test "#github token is refreshed after expiration" do
77
+ Rails.env = 'not_test'
78
+ config = {
79
+ app_id: "test_id",
80
+ installation_id: "test_installation_id",
81
+ private_key: "test_private_key",
82
+ }
83
+ initial_token = OpenStruct.new(
84
+ token: "some_initial_github_token",
85
+ expires_at: Time.now.utc + 60.minutes,
86
+ )
87
+ second_token = OpenStruct.new(
88
+ token: "some_new_github_token",
89
+ expires_at: initial_token.expires_at + 60.minutes,
90
+ )
91
+ auth_payload = "test_auth_payload"
92
+
93
+ GitHubApp.any_instance.expects(:authentication_payload).twice.returns(auth_payload)
94
+ valid_app = app(config)
95
+
96
+ freeze_time do
97
+ Octokit::Client
98
+ .any_instance
99
+ .expects(:create_app_installation_access_token).twice.with(config[:installation_id], anything)
100
+ .returns(initial_token, second_token)
101
+
102
+ initial_token = valid_app.token
103
+ initial_cached_token = Rails.cache.fetch(@token_cache_key)
104
+ assert_equal initial_token, initial_cached_token.to_s
105
+
106
+ travel 5.minutes
107
+ assert_equal initial_token, valid_app.token
108
+
109
+ travel_to initial_cached_token.expires_at + 5.minutes
110
+ assert_equal second_token.token, valid_app.token
111
+ end
112
+ end
113
+
114
+ test "#github token is refreshed in refresh window before expiry" do
115
+ Rails.env = 'not_test'
116
+ config = {
117
+ app_id: "test_id",
118
+ installation_id: "test_installation_id",
119
+ private_key: "test_private_key",
120
+ }
121
+ initial_token = OpenStruct.new(
122
+ token: "some_initial_github_token",
123
+ expires_at: Time.now.utc + 60.minutes,
124
+ )
125
+ second_token = OpenStruct.new(
126
+ token: "some_new_github_token",
127
+ expires_at: initial_token.expires_at + 60.minutes,
128
+ )
129
+ auth_payload = "test_auth_payload"
130
+
131
+ GitHubApp.any_instance.expects(:authentication_payload).twice.returns(auth_payload)
132
+ valid_app = app(config)
133
+
134
+ freeze_time do
135
+ Octokit::Client
136
+ .any_instance
137
+ .expects(:create_app_installation_access_token).twice.with(config[:installation_id], anything)
138
+ .returns(initial_token, second_token)
139
+
140
+ initial_token = valid_app.token
141
+ initial_cached_token = Rails.cache.fetch(@token_cache_key)
142
+ assert_equal initial_token, initial_cached_token.to_s
143
+
144
+ # Travel forward, but before the token is refreshed, so the cached value should be the same.
145
+ travel 40.minutes
146
+ assert_equal initial_token, valid_app.token
147
+
148
+ # Travel to when the token should refresh, but is not expired, which should result in our cache.fetch update block.
149
+ travel 15.minutes
150
+ updated_token = valid_app.token
151
+ assert_not_equal initial_token, updated_token
152
+
153
+ cached_token = Rails.cache.fetch(@token_cache_key)
154
+ assert_operator cached_token.expires_at, :>, initial_cached_token.expires_at
155
+ end
156
+ end
157
+
158
+ test "#github token is missing refresh_at field" do
159
+ # $debugging = true
160
+ Rails.env = 'not_test'
161
+ config = {
162
+ app_id: "test_id",
163
+ installation_id: "test_installation_id",
164
+ private_key: "test_private_key",
165
+ }
166
+ initial_cached_token = Shipit::GitHubApp::Token.new("some_initial_github_token", Time.now.utc - 1.minute)
167
+ initial_cached_token.instance_variable_set(:@refresh_at, nil)
168
+
169
+ second_token = OpenStruct.new(
170
+ token: "some_new_github_token",
171
+ expires_at: initial_cached_token.expires_at + 60.minutes,
172
+ )
173
+ auth_payload = "test_auth_payload"
174
+
175
+ GitHubApp.any_instance.expects(:authentication_payload).returns(auth_payload)
176
+ valid_app = app(config)
177
+
178
+ freeze_time do
179
+ valid_app.instance_variable_set(:@token, initial_cached_token)
180
+ Rails.cache.write(@token_cache_key, initial_cached_token, expires_in: 1.minute)
181
+
182
+ Octokit::Client
183
+ .any_instance
184
+ .expects(:create_app_installation_access_token).with(config[:installation_id], anything)
185
+ .returns(second_token)
186
+
187
+ first_token = valid_app.token
188
+
189
+ first_cached_token = Rails.cache.fetch(@token_cache_key)
190
+ assert_equal first_token, first_cached_token.to_s
191
+
192
+ travel_to first_cached_token.expires_at + 5.minutes
193
+ new_token = valid_app.token
194
+
195
+ assert_equal second_token.token, new_token
196
+ end
197
+ end
198
+
34
199
  private
35
200
 
36
201
  def app(extra_config = {})