shipit-engine 0.31.0 → 0.35.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/README.md +17 -4
- data/Rakefile +4 -2
- data/app/assets/images/magic-solid.svg +1 -0
- data/app/assets/javascripts/shipit/repositories_search.js.coffee +60 -0
- data/app/assets/javascripts/shipit/{search.js.coffee → stack_search.js.coffee} +0 -0
- data/app/assets/stylesheets/_pages/_deploy.scss +2 -3
- data/app/assets/stylesheets/_pages/_repositories.scss +148 -0
- data/app/assets/stylesheets/_pages/_stacks.scss +19 -3
- data/app/assets/stylesheets/merge_status.scss +0 -3
- data/app/assets/stylesheets/shipit.scss +1 -0
- data/app/controllers/concerns/shipit/active_model_serializers_patch.rb +1 -0
- data/app/controllers/concerns/shipit/api/cacheable.rb +1 -0
- data/app/controllers/concerns/shipit/api/paginable.rb +3 -2
- data/app/controllers/concerns/shipit/api/rendering.rb +5 -4
- data/app/controllers/concerns/shipit/authentication.rb +3 -2
- data/app/controllers/concerns/shipit/pagination.rb +2 -1
- data/app/controllers/shipit/api/base_controller.rb +11 -6
- data/app/controllers/shipit/api/ccmenu_controller.rb +2 -1
- data/app/controllers/shipit/api/commits_controller.rb +2 -1
- data/app/controllers/shipit/api/deploys_controller.rb +6 -3
- data/app/controllers/shipit/api/hooks_controller.rb +6 -5
- data/app/controllers/shipit/api/locks_controller.rb +5 -4
- data/app/controllers/shipit/api/merge_requests_controller.rb +37 -0
- data/app/controllers/shipit/api/outputs_controller.rb +2 -1
- data/app/controllers/shipit/api/release_statuses_controller.rb +3 -2
- data/app/controllers/shipit/api/rollbacks_controller.rb +34 -0
- data/app/controllers/shipit/api/stacks_controller.rb +32 -5
- data/app/controllers/shipit/api/tasks_controller.rb +6 -5
- data/app/controllers/shipit/api_clients_controller.rb +4 -3
- data/app/controllers/shipit/ccmenu_url_controller.rb +4 -3
- data/app/controllers/shipit/commit_checks_controller.rb +2 -1
- data/app/controllers/shipit/commits_controller.rb +2 -1
- data/app/controllers/shipit/deploys_controller.rb +4 -3
- data/app/controllers/shipit/github_authentication_controller.rb +4 -3
- data/app/controllers/shipit/merge_requests_controller.rb +31 -0
- data/app/controllers/shipit/merge_status_controller.rb +31 -30
- data/app/controllers/shipit/release_statuses_controller.rb +3 -2
- data/app/controllers/shipit/repositories_controller.rb +74 -0
- data/app/controllers/shipit/rollbacks_controller.rb +3 -2
- data/app/controllers/shipit/shipit_controller.rb +2 -1
- data/app/controllers/shipit/stacks_controller.rb +24 -9
- data/app/controllers/shipit/status_controller.rb +2 -1
- data/app/controllers/shipit/tasks_controller.rb +7 -6
- data/app/controllers/shipit/webhooks_controller.rb +26 -6
- data/app/helpers/shipit/chunks_helper.rb +3 -2
- data/app/helpers/shipit/deploys_helper.rb +4 -3
- data/app/helpers/shipit/github_url_helper.rb +9 -0
- data/app/helpers/shipit/merge_status_helper.rb +1 -0
- data/app/helpers/shipit/shipit_helper.rb +1 -1
- data/app/helpers/shipit/stacks_helper.rb +5 -0
- data/app/helpers/shipit/tasks_helper.rb +1 -0
- data/app/jobs/shipit/background_job/unique.rb +1 -0
- data/app/jobs/shipit/background_job.rb +4 -0
- data/app/jobs/shipit/cache_deploy_spec_job.rb +1 -0
- data/app/jobs/shipit/chunk_rollup_job.rb +4 -0
- data/app/jobs/shipit/clear_git_cache_job.rb +1 -0
- data/app/jobs/shipit/continuous_delivery_job.rb +2 -1
- data/app/jobs/shipit/create_on_github_job.rb +7 -1
- data/app/jobs/shipit/create_release_statuses_job.rb +1 -0
- data/app/jobs/shipit/deferred_touch_job.rb +4 -0
- data/app/jobs/shipit/deliver_hook_job.rb +2 -1
- data/app/jobs/shipit/destroy_job.rb +1 -0
- data/app/jobs/shipit/destroy_repository_job.rb +24 -0
- data/app/jobs/shipit/destroy_stack_job.rb +3 -2
- data/app/jobs/shipit/emit_event_job.rb +2 -1
- data/app/jobs/shipit/fetch_commit_stats_job.rb +1 -0
- data/app/jobs/shipit/fetch_deployed_revision_job.rb +1 -0
- data/app/jobs/shipit/github_sync_job.rb +15 -10
- data/app/jobs/shipit/mark_deploy_healthy_job.rb +1 -0
- data/app/jobs/shipit/perform_commit_checks_job.rb +1 -0
- data/app/jobs/shipit/perform_task_job.rb +5 -92
- data/app/jobs/shipit/process_merge_requests_job.rb +32 -0
- data/app/jobs/shipit/purge_old_deliveries_job.rb +1 -0
- data/app/jobs/shipit/reap_dead_tasks_job.rb +21 -0
- data/app/jobs/shipit/refresh_check_runs_job.rb +1 -0
- data/app/jobs/shipit/refresh_github_user_job.rb +1 -0
- data/app/jobs/shipit/refresh_merge_request_job.rb +11 -0
- data/app/jobs/shipit/refresh_statuses_job.rb +1 -0
- data/app/jobs/shipit/setup_github_hook_job.rb +1 -0
- data/app/jobs/shipit/update_estimated_deploy_duration_job.rb +1 -0
- data/app/jobs/shipit/update_github_last_deployed_ref_job.rb +5 -4
- data/app/models/concerns/shipit/deferred_touch.rb +4 -3
- data/app/models/shipit/anonymous_user.rb +15 -2
- data/app/models/shipit/api_client.rb +3 -2
- data/app/models/shipit/application_record.rb +2 -1
- data/app/models/shipit/check_run.rb +41 -4
- data/app/models/shipit/command_line_user.rb +5 -0
- data/app/models/shipit/commit.rb +42 -24
- data/app/models/shipit/commit_checks.rb +15 -13
- data/app/models/shipit/commit_deployment.rb +6 -5
- data/app/models/shipit/commit_deployment_status.rb +5 -4
- data/app/models/shipit/commit_message.rb +1 -0
- data/app/models/shipit/delivery.rb +4 -3
- data/app/models/shipit/deploy.rb +23 -28
- data/app/models/shipit/deploy_spec/bundler_discovery.rb +1 -0
- data/app/models/shipit/deploy_spec/capistrano_discovery.rb +1 -0
- data/app/models/shipit/deploy_spec/file_system.rb +20 -7
- data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +1 -0
- data/app/models/shipit/deploy_spec/lerna_discovery.rb +13 -4
- data/app/models/shipit/deploy_spec/npm_discovery.rb +5 -4
- data/app/models/shipit/deploy_spec/pypi_discovery.rb +1 -0
- data/app/models/shipit/deploy_spec/rubygems_discovery.rb +1 -0
- data/app/models/shipit/deploy_spec.rb +38 -7
- data/app/models/shipit/deploy_stats.rb +2 -1
- data/app/models/shipit/duration.rb +5 -2
- data/app/models/shipit/ephemeral_commit_checks.rb +1 -0
- data/app/models/shipit/github_hook.rb +2 -1
- data/app/models/shipit/github_status.rb +2 -1
- data/app/models/shipit/hook.rb +34 -7
- data/app/models/shipit/membership.rb +3 -2
- data/app/models/shipit/merge_request.rb +304 -0
- data/app/models/shipit/output_chunk.rb +7 -2
- data/app/models/shipit/provisioning_handler/base.rb +30 -0
- data/app/models/shipit/provisioning_handler/unregistered_provisioning_handler.rb +35 -0
- data/app/models/shipit/provisioning_handler.rb +32 -0
- data/app/models/shipit/pull_request.rb +28 -266
- data/app/models/shipit/pull_request_assignment.rb +10 -0
- data/app/models/shipit/record.rb +18 -0
- data/app/models/shipit/release_status.rb +4 -3
- data/app/models/shipit/repository.rb +71 -6
- data/app/models/shipit/review_stack.rb +130 -0
- data/app/models/shipit/review_stack_provisioning_queue.rb +39 -0
- data/app/models/shipit/rollback.rb +6 -0
- data/app/models/shipit/stack.rb +127 -45
- data/app/models/shipit/status/common.rb +7 -6
- data/app/models/shipit/status/group.rb +2 -1
- data/app/models/shipit/status/missing.rb +2 -1
- data/app/models/shipit/status/unknown.rb +2 -1
- data/app/models/shipit/status.rb +3 -2
- data/app/models/shipit/task.rb +98 -12
- data/app/models/shipit/task_definition.rb +1 -0
- data/app/models/shipit/task_execution_strategy/base.rb +20 -0
- data/app/models/shipit/task_execution_strategy/default.rb +109 -0
- data/app/models/shipit/team.rb +6 -3
- data/app/models/shipit/undeployed_commit.rb +1 -0
- data/app/models/shipit/unlimited_api_client.rb +1 -0
- data/app/models/shipit/user.rb +19 -8
- data/app/models/shipit/variable_definition.rb +1 -0
- data/app/models/shipit/webhooks/handlers/check_suite_handler.rb +1 -0
- data/app/models/shipit/webhooks/handlers/handler.rb +1 -0
- data/app/models/shipit/webhooks/handlers/membership_handler.rb +1 -0
- data/app/models/shipit/webhooks/handlers/pull_request/assigned_handler.rb +74 -0
- data/app/models/shipit/webhooks/handlers/pull_request/closed_handler.rb +68 -0
- data/app/models/shipit/webhooks/handlers/pull_request/edited_handler.rb +74 -0
- data/app/models/shipit/webhooks/handlers/pull_request/label_capturing_handler.rb +127 -0
- data/app/models/shipit/webhooks/handlers/pull_request/labeled_handler.rb +106 -0
- data/app/models/shipit/webhooks/handlers/pull_request/opened_handler.rb +83 -0
- data/app/models/shipit/webhooks/handlers/pull_request/reopened_handler.rb +88 -0
- data/app/models/shipit/webhooks/handlers/pull_request/review_stack_adapter.rb +103 -0
- data/app/models/shipit/webhooks/handlers/pull_request/unlabeled_handler.rb +107 -0
- data/app/models/shipit/webhooks/handlers/push_handler.rb +5 -1
- data/app/models/shipit/webhooks/handlers/status_handler.rb +1 -0
- data/app/models/shipit/webhooks.rb +11 -0
- data/app/serializers/concerns/shipit/conditional_attributes.rb +1 -0
- data/app/serializers/shipit/anonymous_user_serializer.rb +1 -0
- data/app/serializers/shipit/command_line_user_serializer.rb +1 -0
- data/app/serializers/shipit/commit_serializer.rb +1 -0
- data/app/serializers/shipit/deploy_serializer.rb +8 -1
- data/app/serializers/shipit/hook_serializer.rb +1 -0
- data/app/serializers/shipit/merge_request_serializer.rb +21 -0
- data/app/serializers/shipit/pull_request_serializer.rb +6 -8
- data/app/serializers/shipit/review_stack_serializer.rb +7 -0
- data/app/serializers/shipit/rollback_serializer.rb +1 -0
- data/app/serializers/shipit/short_commit_serializer.rb +1 -0
- data/app/serializers/shipit/stack_serializer.rb +8 -6
- data/app/serializers/shipit/tail_task_serializer.rb +11 -2
- data/app/serializers/shipit/task_serializer.rb +2 -17
- data/app/serializers/shipit/user_serializer.rb +6 -1
- data/app/validators/ascii_only_validator.rb +1 -0
- data/app/validators/subset_validator.rb +2 -1
- data/app/views/layouts/merge_status.html.erb +1 -1
- data/app/views/layouts/shipit.html.erb +1 -1
- data/app/views/shipit/_variables.html.erb +1 -1
- data/app/views/shipit/ccmenu/project.xml.builder +2 -1
- data/app/views/shipit/deploys/show.html.erb +2 -2
- data/app/views/shipit/merge_requests/_merge_request.html.erb +29 -0
- data/app/views/shipit/{pull_requests → merge_requests}/index.html.erb +2 -2
- data/app/views/shipit/merge_requests/merge_requests/_pull_request.html.erb +29 -0
- data/app/views/shipit/merge_requests/merge_requests/index.html.erb +20 -0
- data/app/views/shipit/merge_status/_merge_queue_button.html.erb +3 -3
- data/app/views/shipit/merge_status/backlogged.html.erb +1 -1
- data/app/views/shipit/merge_status/failure.html.erb +1 -1
- data/app/views/shipit/merge_status/locked.html.erb +1 -1
- data/app/views/shipit/merge_status/success.html.erb +2 -2
- data/app/views/shipit/repositories/_header.html.erb +19 -0
- data/app/views/shipit/repositories/index.html.erb +31 -0
- data/app/views/shipit/repositories/new.html.erb +23 -0
- data/app/views/shipit/repositories/settings.html.erb +53 -0
- data/app/views/shipit/repositories/show.html.erb +30 -0
- data/app/views/shipit/stacks/_banners.html.erb +15 -1
- data/app/views/shipit/stacks/_header.html.erb +8 -2
- data/app/views/shipit/stacks/_stack.html.erb +8 -0
- data/app/views/shipit/stacks/all_tasks.html.erb +28 -0
- data/app/views/shipit/stacks/index.html.erb +3 -2
- data/app/views/shipit/stacks/new.html.erb +1 -1
- data/app/views/shipit/stacks/settings.html.erb +5 -5
- data/app/views/shipit/stacks/show.html.erb +1 -1
- data/app/views/shipit/tasks/_task_output.html.erb +1 -1
- data/app/views/shipit/tasks/show.html.erb +1 -1
- data/config/initializers/inflections.rb +2 -1
- data/config/locales/en.yml +3 -3
- data/config/routes.rb +25 -7
- data/config/secrets.development.example.yml +24 -0
- data/config/secrets.development.shopify.yml +20 -9
- data/db/migrate/20200226211925_add_index_to_tasks_status.rb +5 -0
- data/db/migrate/20200427135152_add_pull_request_head_sha_to_commit.rb +5 -0
- data/db/migrate/20200615181558_add_rollback_once_aborted_to.rb +5 -0
- data/db/migrate/20200706145406_add_review_stacks.rb +12 -0
- data/db/migrate/20200804144639_rename_pull_request_to_merge_request.rb +7 -0
- data/db/migrate/20200804161512_rename_commits_pull_request_id_to_merge_request_id.rb +5 -0
- data/db/migrate/20200813134712_recreate_shipit_pull_requests.rb +22 -0
- data/db/migrate/20200813194056_create_pull_request_assignments.rb +8 -0
- data/db/migrate/20201001125502_add_provision_pr_stacks_flag_to_repositories.rb +7 -0
- data/db/migrate/20201008145809_add_retry_attempt_to_tasks.rb +5 -0
- data/db/migrate/20201008152744_add_max_retries_to_tasks.rb +5 -0
- data/db/migrate/20210325194053_remove_stacks_branch_default.rb +5 -0
- data/db/migrate/20210504200438_add_github_updated_at_to_check_runs.rb +5 -0
- data/db/migrate/20210823075617_change_check_runs_github_updated_at_default.rb +5 -0
- data/lib/shipit/cast_value.rb +1 -0
- data/lib/shipit/command.rb +19 -17
- data/lib/shipit/commands.rb +23 -9
- data/lib/shipit/csv_serializer.rb +1 -0
- data/lib/shipit/deploy_commands.rb +1 -0
- data/lib/shipit/engine.rb +9 -2
- data/lib/shipit/environment_variables.rb +2 -1
- data/lib/shipit/first_parent_commits_iterator.rb +1 -0
- data/lib/shipit/flock.rb +9 -1
- data/lib/shipit/github_app.rb +15 -12
- data/lib/shipit/github_http_cache_middleware.rb +1 -0
- data/lib/shipit/null_serializer.rb +1 -0
- data/lib/shipit/octokit_check_runs.rb +3 -2
- data/lib/shipit/octokit_iterator.rb +4 -3
- data/lib/shipit/paginator.rb +3 -2
- data/lib/shipit/review_stack_commands.rb +8 -0
- data/lib/shipit/rollback_commands.rb +1 -0
- data/lib/shipit/same_site_cookie_middleware.rb +29 -0
- data/lib/shipit/simple_message_verifier.rb +3 -2
- data/lib/shipit/stack_commands.rb +39 -9
- data/lib/shipit/stat.rb +1 -0
- data/lib/shipit/task_commands.rb +9 -0
- data/lib/shipit/version.rb +2 -1
- data/lib/shipit.rb +61 -17
- data/lib/snippets/publish-lerna-independent-packages +35 -34
- data/lib/snippets/publish-lerna-independent-packages-legacy +39 -0
- data/lib/snippets/release-gem +5 -1
- data/lib/tasks/cron.rake +13 -2
- data/lib/tasks/dev.rake +3 -2
- data/lib/tasks/shipit.rake +15 -14
- data/lib/tasks/teams.rake +1 -0
- data/test/controllers/api/base_controller_test.rb +3 -2
- data/test/controllers/api/ccmenu_controller_test.rb +9 -8
- data/test/controllers/api/commits_controller_test.rb +3 -2
- data/test/controllers/api/deploys_controller_test.rb +32 -14
- data/test/controllers/api/hooks_controller_test.rb +8 -7
- data/test/controllers/api/locks_controller_test.rb +7 -6
- data/test/controllers/api/{pull_requests_controller_test.rb → merge_requests_controller_test.rb} +17 -16
- data/test/controllers/api/outputs_controller_test.rb +3 -1
- data/test/controllers/api/release_statuses_controller_test.rb +2 -1
- data/test/controllers/api/rollback_controller_test.rb +113 -0
- data/test/controllers/api/stacks_controller_test.rb +71 -16
- data/test/controllers/api/tasks_controller_test.rb +13 -12
- data/test/controllers/api_clients_controller_test.rb +5 -4
- data/test/controllers/ccmenu_controller_test.rb +4 -3
- data/test/controllers/commit_checks_controller_test.rb +4 -3
- data/test/controllers/commits_controller_test.rb +3 -2
- data/test/controllers/deploys_controller_test.rb +32 -21
- data/test/controllers/github_authentication_controller_test.rb +1 -0
- data/test/controllers/merge_requests_controller_test.rb +32 -0
- data/test/controllers/merge_status_controller_test.rb +7 -6
- data/test/controllers/release_statuses_controller_test.rb +3 -2
- data/test/controllers/repositories_controller_test.rb +71 -0
- data/test/controllers/rollbacks_controller_test.rb +9 -8
- data/test/controllers/stacks_controller_test.rb +41 -19
- data/test/controllers/status_controller_test.rb +1 -0
- data/test/controllers/tasks_controller_test.rb +32 -19
- data/test/controllers/webhooks_controller_test.rb +33 -17
- data/test/dummy/app/assets/config/manifest.js +3 -0
- data/test/dummy/config/application.rb +7 -2
- data/test/dummy/config/database.yml +9 -0
- data/test/dummy/config/environments/development.rb +3 -4
- data/test/dummy/config/environments/test.rb +2 -5
- data/test/dummy/config/secrets_double_github_app.yml +79 -0
- data/test/dummy/db/schema.rb +59 -17
- data/test/dummy/db/seeds.rb +2 -1
- data/test/fixtures/payloads/check_suite_master.json +4 -32
- data/test/fixtures/payloads/invalid_pull_request.json +117 -0
- data/test/fixtures/payloads/provision_disabled_pull_request.json +454 -0
- data/test/fixtures/payloads/pull_request_assigned.json +480 -0
- data/test/fixtures/payloads/pull_request_closed.json +454 -0
- data/test/fixtures/payloads/pull_request_labeled.json +461 -0
- data/test/fixtures/payloads/pull_request_opened.json +454 -0
- data/test/fixtures/payloads/pull_request_reopened.json +454 -0
- data/test/fixtures/payloads/pull_request_unlabeled.json +454 -0
- data/test/fixtures/payloads/pull_request_with_no_repo.json +454 -0
- data/test/fixtures/payloads/push_master.json +1 -1
- data/test/fixtures/payloads/push_not_master.json +1 -1
- data/test/fixtures/shipit/commits.yml +31 -3
- data/test/fixtures/shipit/hooks.yml +1 -0
- data/test/fixtures/shipit/merge_requests.yml +141 -0
- data/test/fixtures/shipit/pull_request_assignments.yml +3 -0
- data/test/fixtures/shipit/pull_requests.yml +10 -131
- data/test/fixtures/shipit/repositories.yml +5 -0
- data/test/fixtures/shipit/stacks.yml +235 -14
- data/test/fixtures/shipit/statuses.yml +9 -0
- data/test/fixtures/shipit/tasks.yml +4 -1
- data/test/fixtures/shipit/users.yml +7 -0
- data/test/fixtures/timeout +2 -1
- data/test/helpers/api_helper.rb +1 -0
- data/test/helpers/fixture_aliases_helper.rb +1 -0
- data/test/helpers/hooks_helper.rb +2 -1
- data/test/helpers/json_helper.rb +20 -12
- data/test/helpers/links_helper.rb +4 -3
- data/test/helpers/payloads_helper.rb +5 -0
- data/test/helpers/queries_helper.rb +3 -2
- data/test/jobs/cache_deploy_spec_job_test.rb +2 -1
- data/test/jobs/chunk_rollup_job_test.rb +16 -1
- data/test/jobs/deliver_hook_job_test.rb +1 -0
- data/test/jobs/destroy_repository_job_test.rb +27 -0
- data/test/jobs/destroy_stack_job_test.rb +1 -0
- data/test/jobs/emit_event_job_test.rb +2 -1
- data/test/jobs/fetch_commit_stats_job_test.rb +1 -0
- data/test/jobs/fetch_deployed_revision_job_test.rb +1 -0
- data/test/jobs/github_sync_job_test.rb +3 -1
- data/test/jobs/mark_deploy_healthy_job_test.rb +1 -0
- data/test/jobs/perform_task_job_test.rb +12 -11
- data/test/jobs/{merge_pull_requests_job_test.rb → process_merge_requests_job_test.rb} +19 -18
- data/test/jobs/purge_old_deliveries_job_test.rb +1 -0
- data/test/jobs/reap_dead_tasks_job_test.rb +68 -0
- data/test/jobs/refresh_github_user_job_test.rb +1 -0
- data/test/jobs/refresh_status_job_test.rb +1 -0
- data/test/jobs/unique_job_test.rb +1 -0
- data/test/jobs/update_github_last_deployed_ref_job_test.rb +1 -0
- data/test/lib/shipit/deploy_commands_test.rb +16 -0
- data/test/lib/shipit/task_commands_test.rb +17 -0
- data/test/middleware/same_site_cookie_middleware_test.rb +52 -0
- data/test/models/api_client_test.rb +1 -0
- data/test/models/commit_checks_test.rb +1 -0
- data/test/models/commit_deployment_status_test.rb +4 -3
- data/test/models/commit_deployment_test.rb +2 -1
- data/test/models/commits_test.rb +96 -19
- data/test/models/delivery_test.rb +2 -1
- data/test/models/deploy_spec_test.rb +110 -65
- data/test/models/deploy_stats_test.rb +1 -0
- data/test/models/deploys_test.rb +219 -36
- data/test/models/duration_test.rb +1 -0
- data/test/models/github_hook_test.rb +1 -0
- data/test/models/hook_test.rb +47 -10
- data/test/models/membership_test.rb +1 -0
- data/test/models/{pull_request_test.rb → merge_request_test.rb} +53 -37
- data/test/models/pull_request_assignment_test.rb +16 -0
- data/test/models/release_statuses_test.rb +1 -0
- data/test/models/rollbacks_test.rb +1 -0
- data/test/models/shipit/check_run_test.rb +125 -5
- data/test/models/shipit/provisioning_handler/base_test.rb +33 -0
- data/test/models/shipit/provisioning_handler/unregistered_provisioning_handler_test.rb +49 -0
- data/test/models/shipit/provisioning_handler_test.rb +64 -0
- data/test/models/shipit/pull_request_test.rb +52 -0
- data/test/models/shipit/repository_test.rb +6 -1
- data/test/models/shipit/review_stack_provision_status_test.rb +77 -0
- data/test/models/shipit/review_stack_provisioning_queue_test.rb +63 -0
- data/test/models/shipit/review_stack_test.rb +91 -0
- data/test/models/{stacks_test.rb → shipit/stacks_test.rb} +82 -16
- data/test/models/shipit/webhooks/handlers/pull_request/assigned_handler_test.rb +45 -0
- data/test/models/shipit/webhooks/handlers/pull_request/closed_handler_test.rb +192 -0
- data/test/models/shipit/webhooks/handlers/pull_request/edited_handler_test.rb +47 -0
- data/test/models/shipit/webhooks/handlers/pull_request/label_capturing_handler_test.rb +209 -0
- data/test/models/shipit/webhooks/handlers/pull_request/labeled_handler_test.rb +332 -0
- data/test/models/shipit/webhooks/handlers/pull_request/opened_handler_test.rb +238 -0
- data/test/models/shipit/webhooks/handlers/pull_request/reopened_handler_test.rb +282 -0
- data/test/models/shipit/webhooks/handlers/pull_request/review_stack_adapter_test.rb +107 -0
- data/test/models/shipit/webhooks/handlers/pull_request/unlabeled_handler_test.rb +324 -0
- data/test/models/shipit/{wehbooks → webhooks}/handlers_test.rb +1 -0
- data/test/models/status/group_test.rb +1 -0
- data/test/models/status/missing_test.rb +1 -0
- data/test/models/status_test.rb +1 -0
- data/test/models/task_definitions_test.rb +9 -8
- data/test/models/tasks_test.rb +81 -1
- data/test/models/team_test.rb +4 -2
- data/test/models/undeployed_commits_test.rb +1 -0
- data/test/models/users_test.rb +13 -5
- data/test/serializers/shipit/pull_request_serializer_test.rb +29 -0
- data/test/test_command_integration.rb +3 -2
- data/test/test_helper.rb +49 -31
- data/test/unit/anonymous_user_serializer_test.rb +14 -0
- data/test/unit/command_test.rb +16 -10
- data/test/unit/commands_test.rb +1 -0
- data/test/unit/commit_serializer_test.rb +16 -0
- data/test/unit/csv_serializer_test.rb +3 -2
- data/test/unit/deploy_commands_test.rb +77 -20
- data/test/unit/deploy_serializer_test.rb +17 -0
- data/test/unit/environment_variables_test.rb +5 -4
- data/test/unit/github_app_test.rb +3 -3
- data/test/unit/github_apps_test.rb +416 -0
- data/test/unit/github_url_helper_test.rb +6 -0
- data/test/unit/rollback_commands_test.rb +2 -1
- data/test/unit/shipit_deployment_checks_test.rb +77 -0
- data/test/unit/shipit_helper_test.rb +17 -0
- data/test/unit/shipit_task_execution_strategy_test.rb +47 -0
- data/test/unit/shipit_test.rb +15 -0
- data/test/unit/user_serializer_test.rb +14 -0
- data/test/unit/variable_definition_test.rb +1 -0
- metadata +325 -182
- data/app/controllers/shipit/api/pull_requests_controller.rb +0 -36
- data/app/controllers/shipit/pull_requests_controller.rb +0 -30
- data/app/jobs/shipit/merge_pull_requests_job.rb +0 -31
- data/app/jobs/shipit/refresh_pull_request_job.rb +0 -10
- data/app/views/shipit/pull_requests/_pull_request.html.erb +0 -29
- data/test/controllers/pull_requests_controller_test.rb +0 -31
- data/test/fixtures/shipit/output_chunks.yml +0 -47
- data/test/models/output_chunk_test.rb +0 -20
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
module Shipit
|
|
3
|
+
class Record < ActiveRecord::Base
|
|
4
|
+
self.abstract_class = true
|
|
5
|
+
|
|
6
|
+
class << self
|
|
7
|
+
def serializer_class
|
|
8
|
+
if defined? @serializer_class
|
|
9
|
+
@serializer_class
|
|
10
|
+
else
|
|
11
|
+
@serializer_class = "#{name}Serializer".safe_constantize
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
delegate :serializer_class, to: :class
|
|
17
|
+
end
|
|
18
|
+
end
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Shipit
|
|
2
|
-
class ReleaseStatus <
|
|
3
|
+
class ReleaseStatus < Record
|
|
3
4
|
MAX_DESCRIPTION_LENGTH = 140
|
|
4
5
|
include DeferredTouch
|
|
5
6
|
|
|
@@ -13,7 +14,7 @@ module Shipit
|
|
|
13
14
|
scope :to_be_created, -> { where(github_id: nil).order(id: :asc) }
|
|
14
15
|
|
|
15
16
|
STATES = %w(pending success failure error).freeze
|
|
16
|
-
validates :state, presence: true, inclusion: {in: STATES}
|
|
17
|
+
validates :state, presence: true, inclusion: { in: STATES }
|
|
17
18
|
|
|
18
19
|
def create_status_on_github!
|
|
19
20
|
return true if github_id?
|
|
@@ -24,7 +25,7 @@ module Shipit
|
|
|
24
25
|
private
|
|
25
26
|
|
|
26
27
|
def create_status_on_github
|
|
27
|
-
|
|
28
|
+
stack.github_api.create_status(
|
|
28
29
|
stack.github_repo_name,
|
|
29
30
|
commit.sha,
|
|
30
31
|
state,
|
|
@@ -1,4 +1,35 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Shipit
|
|
3
|
+
class NullRepository
|
|
4
|
+
def id
|
|
5
|
+
nil
|
|
6
|
+
end
|
|
7
|
+
|
|
8
|
+
def stacks
|
|
9
|
+
Shipit::Stack.none
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def review_stacks
|
|
13
|
+
Shipit::ReviewStack.none
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def review_stacks_enabled
|
|
17
|
+
false
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def provisioning_behavior_allow_all?
|
|
21
|
+
false
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def provisioning_behavior_allow_with_label?
|
|
25
|
+
false
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def provisioning_behavior_prevent_with_label?
|
|
29
|
+
false
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
|
2
33
|
class Repository < ApplicationRecord
|
|
3
34
|
OWNER_MAX_SIZE = 39
|
|
4
35
|
private_constant :OWNER_MAX_SIZE
|
|
@@ -6,13 +37,17 @@ module Shipit
|
|
|
6
37
|
NAME_MAX_SIZE = 100
|
|
7
38
|
private_constant :NAME_MAX_SIZE
|
|
8
39
|
|
|
9
|
-
validates :name, uniqueness: {scope: %i(owner), case_sensitive: false,
|
|
10
|
-
|
|
40
|
+
validates :name, uniqueness: { scope: %i(owner), case_sensitive: false,
|
|
41
|
+
message: 'cannot be used more than once', }
|
|
11
42
|
validates :owner, :name, presence: true, ascii_only: true
|
|
12
|
-
validates :owner, format: {with: /\A[a-z0-9_\-\.]+\z/}, length: {maximum: OWNER_MAX_SIZE}
|
|
13
|
-
validates :name, format: {with: /\A[a-z0-9_\-\.]+\z/}, length: {maximum: NAME_MAX_SIZE}
|
|
43
|
+
validates :owner, format: { with: /\A[a-z0-9_\-\.]+\z/ }, length: { maximum: OWNER_MAX_SIZE }
|
|
44
|
+
validates :name, format: { with: /\A[a-z0-9_\-\.]+\z/ }, length: { maximum: NAME_MAX_SIZE }
|
|
14
45
|
|
|
15
46
|
has_many :stacks, dependent: :destroy
|
|
47
|
+
has_many :review_stacks, dependent: :destroy
|
|
48
|
+
|
|
49
|
+
PROVISIONING_BEHAVIORS = %w(allow_all allow_with_label prevent_with_label).freeze
|
|
50
|
+
enum provisioning_behavior: PROVISIONING_BEHAVIORS.zip(PROVISIONING_BEHAVIORS).to_h, _prefix: :provisioning_behavior
|
|
16
51
|
|
|
17
52
|
def self.from_github_repo_name(github_repo_name)
|
|
18
53
|
repo_owner, repo_name = github_repo_name.downcase.split('/')
|
|
@@ -27,12 +62,42 @@ module Shipit
|
|
|
27
62
|
super(o&.downcase)
|
|
28
63
|
end
|
|
29
64
|
|
|
65
|
+
def github_repo_name
|
|
66
|
+
[owner, name].join('/')
|
|
67
|
+
end
|
|
68
|
+
|
|
30
69
|
def http_url
|
|
31
|
-
|
|
70
|
+
github_app.url(full_name)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def full_name
|
|
74
|
+
"#{owner}/#{name}"
|
|
32
75
|
end
|
|
33
76
|
|
|
34
77
|
def git_url
|
|
35
|
-
"https://#{
|
|
78
|
+
"https://#{github_app.domain}/#{owner}/#{name}.git"
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def schedule_for_destroy!
|
|
82
|
+
DestroyRepositoryJob.perform_later(self)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def to_param
|
|
86
|
+
github_repo_name
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def self.from_param!(param)
|
|
90
|
+
repo_owner, repo_name = param.split('/')
|
|
91
|
+
where(
|
|
92
|
+
owner: repo_owner.downcase,
|
|
93
|
+
name: repo_name.downcase,
|
|
94
|
+
).first!
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
protected
|
|
98
|
+
|
|
99
|
+
def github_app
|
|
100
|
+
Shipit.github(organization: owner)
|
|
36
101
|
end
|
|
37
102
|
end
|
|
38
103
|
end
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shipit
|
|
4
|
+
class ReviewStack < Shipit::Stack
|
|
5
|
+
def self.clear_stale_caches
|
|
6
|
+
Shipit::ReviewStack.where(
|
|
7
|
+
"archived_since > :earliest AND archived_since < :latest",
|
|
8
|
+
earliest: 1.day.ago,
|
|
9
|
+
latest: 1.hour.ago
|
|
10
|
+
).find_each do |review_stack|
|
|
11
|
+
review_stack.clear_local_files
|
|
12
|
+
end
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def self.delete_old_deployment_directories
|
|
16
|
+
Shipit::Deploy.not_active.where(
|
|
17
|
+
"created_at > :earliest AND updated_at < :latest",
|
|
18
|
+
earliest: 1.day.ago,
|
|
19
|
+
latest: 1.hour.ago
|
|
20
|
+
).find_each do |deploy|
|
|
21
|
+
Shipit::Commands.for(deploy).clear_working_directory
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def update_latest_deployed_ref
|
|
26
|
+
# noop: last deployed ref is useless for review stacks
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
model_name.class_eval do
|
|
30
|
+
def route_key
|
|
31
|
+
"stacks"
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def singular_route_key
|
|
35
|
+
"stack"
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
has_one :pull_request, foreign_key: :stack_id
|
|
40
|
+
|
|
41
|
+
after_commit :emit_added_hooks, on: :create
|
|
42
|
+
after_commit :emit_updated_hooks, on: :update
|
|
43
|
+
after_commit :emit_removed_hooks, on: :destroy
|
|
44
|
+
|
|
45
|
+
state_machine :provision_status, initial: :deprovisioned do
|
|
46
|
+
state :provisioned
|
|
47
|
+
state :provisioning
|
|
48
|
+
state :deprovisioning
|
|
49
|
+
state :deprovisioned
|
|
50
|
+
|
|
51
|
+
event :provision do
|
|
52
|
+
transition deprovisioned: :provisioning
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
event :provision_success do
|
|
56
|
+
transition provisioning: :provisioned
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
event :provision_failure do
|
|
60
|
+
transition provisioning: :deprovisioned
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
event :deprovision do
|
|
64
|
+
transition provisioned: :deprovisioning
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
event :deprovision_success do
|
|
68
|
+
transition deprovisioning: :deprovisioned
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
event :deprovision_failure do
|
|
72
|
+
transition deprovisioning: :provisioned
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
after_transition deprovisioned: :provisioning do |stack, _|
|
|
76
|
+
stack.provisioner.up
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
after_transition provisioned: :deprovisioning do |stack, _|
|
|
80
|
+
stack.provisioner.down
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def env
|
|
85
|
+
return super unless pull_request.present?
|
|
86
|
+
|
|
87
|
+
super
|
|
88
|
+
.merge(
|
|
89
|
+
pull_request
|
|
90
|
+
.labels
|
|
91
|
+
.each_with_object({}) { |label_name, labels| labels[label_name.upcase] = "true" }
|
|
92
|
+
)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def provisioner
|
|
96
|
+
provisioner_class.new(self)
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def provisioner_class
|
|
100
|
+
ProvisioningHandler.fetch(provisioning_handler_name)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def enqueue_for_provisioning
|
|
104
|
+
return if awaiting_provision
|
|
105
|
+
update!(awaiting_provision: true)
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def remove_from_provisioning_queue
|
|
109
|
+
return unless awaiting_provision
|
|
110
|
+
update!(awaiting_provision: false)
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def to_partial_path
|
|
114
|
+
"shipit/stacks/stack"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def emit_added_hooks
|
|
118
|
+
Hook.emit(:review_stack, self, action: :added, review_stack: self)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def emit_updated_hooks
|
|
122
|
+
changed = !(previous_changes.keys - %w(updated_at)).empty?
|
|
123
|
+
Hook.emit(:review_stack, self, action: :updated, review_stack: self) if changed
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
def emit_removed_hooks
|
|
127
|
+
Hook.emit(:review_stack, self, action: :removed, review_stack: self)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
end
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Shipit
|
|
4
|
+
class ReviewStackProvisioningQueue
|
|
5
|
+
def self.work
|
|
6
|
+
new.work
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def self.add(stack)
|
|
10
|
+
stack.enqueue_for_provisioning
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def self.queued_stacks
|
|
14
|
+
new.queued_stacks
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def work
|
|
18
|
+
queued_stacks.find_each(&method(:provision))
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def queued_stacks
|
|
22
|
+
@queued_stacks ||= Shipit::ReviewStack
|
|
23
|
+
.with_provision_status(:deprovisioned)
|
|
24
|
+
.where(awaiting_provision: true)
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def provision(stack)
|
|
30
|
+
if stack.provisioner.provision?
|
|
31
|
+
stack.provision
|
|
32
|
+
else
|
|
33
|
+
Rails.logger.info(
|
|
34
|
+
"Putting review ReviewStack<#{stack.id}> back into the provisioning queue - #provision? was falsey."
|
|
35
|
+
)
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
module Shipit
|
|
2
3
|
class Rollback < Deploy
|
|
3
4
|
belongs_to :deploy, foreign_key: :parent_id, inverse_of: false
|
|
@@ -32,6 +33,10 @@ module Shipit
|
|
|
32
33
|
'deploys/deploy'
|
|
33
34
|
end
|
|
34
35
|
|
|
36
|
+
def report_complete!
|
|
37
|
+
complete!
|
|
38
|
+
end
|
|
39
|
+
|
|
35
40
|
private
|
|
36
41
|
|
|
37
42
|
def update_release_status
|
|
@@ -39,6 +44,7 @@ module Shipit
|
|
|
39
44
|
|
|
40
45
|
# When we rollback to a certain revision, assume that all later deploys were faulty
|
|
41
46
|
stack.deploys.newer_than(deploy.id).until(stack.last_completed_deploy.id).to_a.each do |deploy|
|
|
47
|
+
next if deploy.id == id
|
|
42
48
|
deploy.report_faulty!(description: "A rollback of #{stack.to_param} was triggered")
|
|
43
49
|
end
|
|
44
50
|
end
|
data/app/models/shipit/stack.rb
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
1
2
|
require 'fileutils'
|
|
2
3
|
|
|
3
4
|
module Shipit
|
|
4
|
-
class Stack <
|
|
5
|
+
class Stack < Record
|
|
5
6
|
module NoDeployedCommit
|
|
6
7
|
extend self
|
|
7
8
|
|
|
@@ -26,14 +27,14 @@ module Shipit
|
|
|
26
27
|
REQUIRED_HOOKS = %i(push status).freeze
|
|
27
28
|
|
|
28
29
|
has_many :commits, dependent: :destroy
|
|
29
|
-
has_many :
|
|
30
|
+
has_many :merge_requests, dependent: :destroy
|
|
30
31
|
has_many :tasks, dependent: :destroy
|
|
31
32
|
has_many :deploys
|
|
32
33
|
has_many :rollbacks
|
|
33
34
|
has_many :deploys_and_rollbacks,
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
35
|
+
-> { where(type: %w(Shipit::Deploy Shipit::Rollback)) },
|
|
36
|
+
class_name: 'Task',
|
|
37
|
+
inverse_of: :stack
|
|
37
38
|
has_many :github_hooks, dependent: :destroy, class_name: 'Shipit::GithubHook::Repo'
|
|
38
39
|
has_many :hooks, dependent: :destroy
|
|
39
40
|
has_many :api_clients, dependent: :destroy
|
|
@@ -43,6 +44,11 @@ module Shipit
|
|
|
43
44
|
|
|
44
45
|
scope :not_archived, -> { where(archived_since: nil) }
|
|
45
46
|
|
|
47
|
+
include DeferredTouch
|
|
48
|
+
deferred_touch repository: :updated_at
|
|
49
|
+
|
|
50
|
+
default_scope { preload(:repository) }
|
|
51
|
+
|
|
46
52
|
def env
|
|
47
53
|
{
|
|
48
54
|
'ENVIRONMENT' => environment,
|
|
@@ -77,19 +83,36 @@ module Shipit
|
|
|
77
83
|
after_commit :emit_merge_status_hooks, on: :update
|
|
78
84
|
after_commit :sync_github, on: :create
|
|
79
85
|
after_commit :schedule_merges_if_necessary, on: :update
|
|
86
|
+
after_commit :sync_github_if_necessary, on: :update
|
|
87
|
+
|
|
88
|
+
def sync_github_if_necessary
|
|
89
|
+
if (archived_since_previously_changed? && archived_since.nil?) || branch_previously_changed?
|
|
90
|
+
sync_github
|
|
91
|
+
end
|
|
92
|
+
end
|
|
80
93
|
|
|
81
94
|
validates :repository, uniqueness: {
|
|
82
95
|
scope: %i(environment), case_sensitive: false,
|
|
83
|
-
message: 'cannot be used more than once with this environment. Check archived stacks.'
|
|
96
|
+
message: 'cannot be used more than once with this environment. Check archived stacks.',
|
|
84
97
|
}
|
|
85
|
-
validates :environment, format: {with: /\A[a-z0-9\-_\:]+\z/}, length: {maximum: ENVIRONMENT_MAX_SIZE}
|
|
86
|
-
validates :deploy_url, format: {with: URI.regexp(%w(http https ssh))}, allow_blank: true
|
|
98
|
+
validates :environment, format: { with: /\A[a-z0-9\-_\:]+\z/ }, length: { maximum: ENVIRONMENT_MAX_SIZE }
|
|
99
|
+
validates :deploy_url, format: { with: URI.regexp(%w(http https ssh)) }, allow_blank: true
|
|
100
|
+
validates :branch, presence: true
|
|
87
101
|
|
|
88
|
-
validates :lock_reason, length: {maximum: 4096}
|
|
102
|
+
validates :lock_reason, length: { maximum: 4096 }
|
|
89
103
|
|
|
90
104
|
serialize :cached_deploy_spec, DeploySpec
|
|
91
|
-
delegate
|
|
92
|
-
|
|
105
|
+
delegate(
|
|
106
|
+
:provisioning_handler_name,
|
|
107
|
+
:find_task_definition,
|
|
108
|
+
:release_status?,
|
|
109
|
+
:release_status_context,
|
|
110
|
+
:release_status_delay,
|
|
111
|
+
:supports_fetch_deployed_revision?,
|
|
112
|
+
:supports_rollback?,
|
|
113
|
+
to: :cached_deploy_spec,
|
|
114
|
+
allow_nil: true
|
|
115
|
+
)
|
|
93
116
|
|
|
94
117
|
def self.refresh_deployed_revisions
|
|
95
118
|
find_each.select(&:supports_fetch_deployed_revision?).each(&:async_refresh_deployed_revision)
|
|
@@ -136,13 +159,29 @@ module Shipit
|
|
|
136
159
|
env: filter_deploy_envs(env&.to_h || {}),
|
|
137
160
|
allow_concurrency: force,
|
|
138
161
|
ignored_safeties: force || !until_commit.deployable?,
|
|
162
|
+
max_retries: retries_on_deploy,
|
|
139
163
|
)
|
|
140
164
|
end
|
|
141
165
|
|
|
142
166
|
def trigger_deploy(*args, **kwargs)
|
|
167
|
+
if changed?
|
|
168
|
+
# If this is the first deploy since the spec changed it's possible the record will be dirty here, meaning we
|
|
169
|
+
# cant lock. In this one case persist the changes, otherwise log a warning and let the lock raise, so we
|
|
170
|
+
# can debug what's going on here. We don't expect anything other than the deploy spec to dirty the model
|
|
171
|
+
# instance, because of how that field is serialised.
|
|
172
|
+
if changes.keys == ['cached_deploy_spec']
|
|
173
|
+
save!
|
|
174
|
+
else
|
|
175
|
+
Rails.logger.warning("#{changes.keys} field(s) were unexpectedly modified on stack #{id} while deploying")
|
|
176
|
+
end
|
|
177
|
+
end
|
|
178
|
+
|
|
143
179
|
run_now = kwargs.delete(:run_now)
|
|
144
|
-
deploy =
|
|
145
|
-
|
|
180
|
+
deploy = with_lock do
|
|
181
|
+
deploy = build_deploy(*args, **kwargs)
|
|
182
|
+
deploy.save!
|
|
183
|
+
deploy
|
|
184
|
+
end
|
|
146
185
|
run_now ? deploy.run_now! : deploy.enqueue
|
|
147
186
|
continuous_delivery_resumed!
|
|
148
187
|
deploy
|
|
@@ -153,7 +192,7 @@ module Shipit
|
|
|
153
192
|
end
|
|
154
193
|
|
|
155
194
|
def continuous_delivery_delayed?
|
|
156
|
-
continuous_delivery_delayed_since? && continuous_deployment? && checks?
|
|
195
|
+
continuous_delivery_delayed_since? && continuous_deployment? && (checks? || deployment_checks?)
|
|
157
196
|
end
|
|
158
197
|
|
|
159
198
|
def continuous_delivery_delayed!
|
|
@@ -161,15 +200,16 @@ module Shipit
|
|
|
161
200
|
end
|
|
162
201
|
|
|
163
202
|
def trigger_continuous_delivery
|
|
203
|
+
return if cached_deploy_spec.blank?
|
|
204
|
+
|
|
164
205
|
commit = next_commit_to_deploy
|
|
165
206
|
|
|
166
|
-
if
|
|
207
|
+
if should_resume_continuous_delivery?(commit)
|
|
167
208
|
continuous_delivery_resumed!
|
|
168
209
|
return
|
|
169
210
|
end
|
|
170
211
|
|
|
171
|
-
if
|
|
172
|
-
commit.recently_pushed?
|
|
212
|
+
if should_delay_continuous_delivery?(commit)
|
|
173
213
|
continuous_delivery_delayed!
|
|
174
214
|
return
|
|
175
215
|
end
|
|
@@ -181,7 +221,7 @@ module Shipit
|
|
|
181
221
|
end
|
|
182
222
|
|
|
183
223
|
def schedule_merges
|
|
184
|
-
|
|
224
|
+
ProcessMergeRequestsJob.perform_later(self)
|
|
185
225
|
end
|
|
186
226
|
|
|
187
227
|
def next_commit_to_deploy
|
|
@@ -201,7 +241,7 @@ module Shipit
|
|
|
201
241
|
def async_refresh_deployed_revision
|
|
202
242
|
async_refresh_deployed_revision!
|
|
203
243
|
rescue => error
|
|
204
|
-
logger.warn
|
|
244
|
+
logger.warn("Failed to dispatch FetchDeployedRevisionJob: [#{error.class.name}] #{error.message}")
|
|
205
245
|
end
|
|
206
246
|
|
|
207
247
|
def async_refresh_deployed_revision!
|
|
@@ -269,8 +309,8 @@ module Shipit
|
|
|
269
309
|
next if commits_to_lock.empty?
|
|
270
310
|
|
|
271
311
|
affected_rows += commits
|
|
272
|
-
|
|
273
|
-
|
|
312
|
+
.where(id: commits_to_lock.map(&:id).uniq)
|
|
313
|
+
.lock_all(revert.author)
|
|
274
314
|
end
|
|
275
315
|
|
|
276
316
|
touch if affected_rows > 1
|
|
@@ -321,7 +361,7 @@ module Shipit
|
|
|
321
361
|
end
|
|
322
362
|
|
|
323
363
|
def deployable?
|
|
324
|
-
!locked? && !active_task?
|
|
364
|
+
!locked? && !active_task? && !awaiting_provision? && deployment_checks_passed?
|
|
325
365
|
end
|
|
326
366
|
|
|
327
367
|
def allows_merges?
|
|
@@ -329,7 +369,7 @@ module Shipit
|
|
|
329
369
|
end
|
|
330
370
|
|
|
331
371
|
def merge_method
|
|
332
|
-
cached_deploy_spec&.
|
|
372
|
+
cached_deploy_spec&.merge_request_merge_method || Shipit.default_merge_method
|
|
333
373
|
end
|
|
334
374
|
|
|
335
375
|
delegate :name=, to: :repository, prefix: :repo
|
|
@@ -340,42 +380,51 @@ module Shipit
|
|
|
340
380
|
delegate :git_url, to: :repository, prefix: :repo
|
|
341
381
|
|
|
342
382
|
def base_path
|
|
343
|
-
Rails.root.join('data', 'stacks', repo_owner, repo_name, environment)
|
|
383
|
+
@base_path ||= Rails.root.join('data', 'stacks', repo_owner, repo_name, environment)
|
|
344
384
|
end
|
|
345
385
|
|
|
346
386
|
def deploys_path
|
|
347
|
-
|
|
387
|
+
@deploys_path ||= base_path.join("deploys")
|
|
348
388
|
end
|
|
349
389
|
|
|
350
390
|
def git_path
|
|
351
|
-
|
|
391
|
+
@git_path ||= base_path.join("git")
|
|
352
392
|
end
|
|
353
393
|
|
|
354
394
|
def acquire_git_cache_lock(timeout: 15, &block)
|
|
355
|
-
Flock.new(git_path.to_s + '.lock')
|
|
395
|
+
@git_cache_lock ||= Flock.new(git_path.to_s + '.lock')
|
|
396
|
+
@git_cache_lock.lock(timeout: timeout, &block)
|
|
356
397
|
end
|
|
357
398
|
|
|
358
399
|
def clear_git_cache!
|
|
359
400
|
tmp_path = "#{git_path}-#{SecureRandom.hex}"
|
|
360
|
-
return unless
|
|
401
|
+
return unless git_path.exist?
|
|
361
402
|
acquire_git_cache_lock do
|
|
362
|
-
|
|
403
|
+
git_path.rename(tmp_path)
|
|
363
404
|
end
|
|
364
405
|
FileUtils.rm_rf(tmp_path)
|
|
365
406
|
end
|
|
366
407
|
|
|
367
408
|
def github_repo_name
|
|
368
|
-
|
|
409
|
+
repository.github_repo_name
|
|
369
410
|
end
|
|
370
411
|
|
|
371
412
|
def github_commits
|
|
372
413
|
handle_github_redirections do
|
|
373
|
-
|
|
414
|
+
github_api.commits(github_repo_name, sha: branch)
|
|
374
415
|
end
|
|
375
416
|
rescue Octokit::Conflict
|
|
376
417
|
[] # Repository is empty...
|
|
377
418
|
end
|
|
378
419
|
|
|
420
|
+
def github_api
|
|
421
|
+
github_app.api
|
|
422
|
+
end
|
|
423
|
+
|
|
424
|
+
def github_app
|
|
425
|
+
Shipit.github(organization: repository.owner)
|
|
426
|
+
end
|
|
427
|
+
|
|
379
428
|
def handle_github_redirections
|
|
380
429
|
# https://developer.github.com/v3/#http-redirects
|
|
381
430
|
resource = yield
|
|
@@ -388,9 +437,9 @@ module Shipit
|
|
|
388
437
|
end
|
|
389
438
|
|
|
390
439
|
def refresh_repository!
|
|
391
|
-
resource =
|
|
440
|
+
resource = github_api.repo(github_repo_name)
|
|
392
441
|
if resource.try(:message) == 'Moved Permanently'
|
|
393
|
-
resource =
|
|
442
|
+
resource = github_api.get(resource.url)
|
|
394
443
|
end
|
|
395
444
|
repository.update!(owner: resource.owner.login, name: resource.name)
|
|
396
445
|
end
|
|
@@ -409,7 +458,7 @@ module Shipit
|
|
|
409
458
|
end
|
|
410
459
|
|
|
411
460
|
def lock(reason, user)
|
|
412
|
-
params = {lock_reason: reason, lock_author: user}
|
|
461
|
+
params = { lock_reason: reason, lock_author: user }
|
|
413
462
|
update!(params)
|
|
414
463
|
end
|
|
415
464
|
|
|
@@ -455,8 +504,9 @@ module Shipit
|
|
|
455
504
|
end
|
|
456
505
|
|
|
457
506
|
delegate :plugins, :task_definitions, :hidden_statuses, :required_statuses, :soft_failing_statuses,
|
|
458
|
-
|
|
459
|
-
|
|
507
|
+
:blocking_statuses, :deploy_variables, :filter_task_envs, :filter_deploy_envs,
|
|
508
|
+
:maximum_commits_per_deploy, :pause_between_deploys, :retries_on_deploy, :retries_on_rollback,
|
|
509
|
+
to: :cached_deploy_spec
|
|
460
510
|
|
|
461
511
|
def monitoring?
|
|
462
512
|
monitoring.present?
|
|
@@ -481,13 +531,15 @@ module Shipit
|
|
|
481
531
|
end
|
|
482
532
|
|
|
483
533
|
def update_latest_deployed_ref
|
|
484
|
-
|
|
534
|
+
if Shipit.update_latest_deployed_ref
|
|
535
|
+
UpdateGithubLastDeployedRefJob.perform_later(self)
|
|
536
|
+
end
|
|
485
537
|
end
|
|
486
538
|
|
|
487
539
|
def broadcast_update
|
|
488
540
|
Pubsubstub.publish(
|
|
489
541
|
"stack.#{id}",
|
|
490
|
-
{id: id, updated_at: updated_at}.to_json,
|
|
542
|
+
{ id: id, updated_at: updated_at }.to_json,
|
|
491
543
|
name: 'update',
|
|
492
544
|
)
|
|
493
545
|
end
|
|
@@ -546,19 +598,31 @@ module Shipit
|
|
|
546
598
|
links_spec.transform_values { |url| context.interpolate(url) }
|
|
547
599
|
end
|
|
548
600
|
|
|
601
|
+
def clear_local_files
|
|
602
|
+
FileUtils.rm_rf(base_path.to_s)
|
|
603
|
+
end
|
|
604
|
+
|
|
605
|
+
def deployment_checks_passed?
|
|
606
|
+
return true unless deployment_checks?
|
|
607
|
+
|
|
608
|
+
Shipit.deployment_checks.call(self)
|
|
609
|
+
end
|
|
610
|
+
|
|
549
611
|
private
|
|
550
612
|
|
|
551
613
|
def clear_cache
|
|
552
614
|
remove_instance_variable(:@active_task) if defined?(@active_task)
|
|
553
615
|
end
|
|
554
616
|
|
|
555
|
-
def clear_local_files
|
|
556
|
-
FileUtils.rm_rf(base_path.to_s)
|
|
557
|
-
end
|
|
558
|
-
|
|
559
617
|
def update_defaults
|
|
560
618
|
self.environment = 'production' if environment.blank?
|
|
561
|
-
self.branch =
|
|
619
|
+
self.branch = default_branch_name if branch.blank?
|
|
620
|
+
end
|
|
621
|
+
|
|
622
|
+
def default_branch_name
|
|
623
|
+
Shipit.github.api.repo(github_repo_name).default_branch
|
|
624
|
+
rescue Octokit::NotFound, Octokit::InvalidRepository
|
|
625
|
+
nil
|
|
562
626
|
end
|
|
563
627
|
|
|
564
628
|
def set_locked_since
|
|
@@ -572,7 +636,7 @@ module Shipit
|
|
|
572
636
|
end
|
|
573
637
|
|
|
574
638
|
def schedule_merges_if_necessary
|
|
575
|
-
if
|
|
639
|
+
if lock_reason_previously_changed? && lock_reason.blank?
|
|
576
640
|
schedule_merges
|
|
577
641
|
end
|
|
578
642
|
end
|
|
@@ -581,7 +645,7 @@ module Shipit
|
|
|
581
645
|
return unless previous_changes.include?('lock_reason')
|
|
582
646
|
|
|
583
647
|
lock_details = if previous_changes['lock_reason'].last.blank?
|
|
584
|
-
{from: previous_changes['locked_since'].first, until: Time.zone.now}
|
|
648
|
+
{ from: previous_changes['locked_since'].first, until: Time.zone.now }
|
|
585
649
|
end
|
|
586
650
|
|
|
587
651
|
Hook.emit(:lock, self, locked: locked?, lock_details: lock_details, stack: self)
|
|
@@ -607,5 +671,23 @@ module Shipit
|
|
|
607
671
|
def ci_enabled_cache_key
|
|
608
672
|
"stacks:#{id}:ci_enabled"
|
|
609
673
|
end
|
|
674
|
+
|
|
675
|
+
def should_resume_continuous_delivery?(commit)
|
|
676
|
+
(deployment_checks_passed? && !deployable?) ||
|
|
677
|
+
deployed_too_recently? ||
|
|
678
|
+
commit.nil? ||
|
|
679
|
+
commit.deployed?
|
|
680
|
+
end
|
|
681
|
+
|
|
682
|
+
def should_delay_continuous_delivery?(commit)
|
|
683
|
+
commit.deploy_failed? ||
|
|
684
|
+
(checks? && !EphemeralCommitChecks.new(commit).run.success?) ||
|
|
685
|
+
!deployment_checks_passed? ||
|
|
686
|
+
commit.recently_pushed?
|
|
687
|
+
end
|
|
688
|
+
|
|
689
|
+
def deployment_checks?
|
|
690
|
+
Shipit.deployment_checks.present?
|
|
691
|
+
end
|
|
610
692
|
end
|
|
611
693
|
end
|