shipit-engine 0.39.0 → 0.40.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 +40 -1
- data/Rakefile +2 -1
- data/app/assets/javascripts/shipit/continuous_delivery_schedule.js.coffee +15 -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 +1 -0
- data/app/controllers/concerns/shipit/authentication.rb +1 -0
- data/app/controllers/concerns/shipit/pagination.rb +3 -2
- data/app/controllers/shipit/api/base_controller.rb +10 -8
- data/app/controllers/shipit/api/ccmenu_controller.rb +2 -1
- data/app/controllers/shipit/api/commits_controller.rb +2 -3
- data/app/controllers/shipit/api/deploys_controller.rb +2 -1
- data/app/controllers/shipit/api/hooks_controller.rb +4 -3
- data/app/controllers/shipit/api/locks_controller.rb +1 -0
- data/app/controllers/shipit/api/merge_requests_controller.rb +6 -5
- data/app/controllers/shipit/api/outputs_controller.rb +1 -0
- data/app/controllers/shipit/api/release_statuses_controller.rb +2 -1
- data/app/controllers/shipit/api/rollbacks_controller.rb +1 -0
- data/app/controllers/shipit/api/stacks_controller.rb +15 -14
- data/app/controllers/shipit/api/tasks_controller.rb +6 -5
- data/app/controllers/shipit/api_clients_controller.rb +6 -7
- data/app/controllers/shipit/ccmenu_url_controller.rb +3 -2
- data/app/controllers/shipit/commit_checks_controller.rb +2 -1
- data/app/controllers/shipit/commits_controller.rb +1 -0
- data/app/controllers/shipit/continuous_delivery_schedules_controller.rb +42 -0
- data/app/controllers/shipit/deploys_controller.rb +6 -5
- data/app/controllers/shipit/github_authentication_controller.rb +6 -0
- data/app/controllers/shipit/merge_requests_controller.rb +1 -0
- data/app/controllers/shipit/merge_status_controller.rb +30 -26
- data/app/controllers/shipit/release_statuses_controller.rb +1 -0
- data/app/controllers/shipit/repositories_controller.rb +4 -7
- data/app/controllers/shipit/rollbacks_controller.rb +2 -1
- data/app/controllers/shipit/shipit_controller.rb +1 -0
- data/app/controllers/shipit/stacks_controller.rb +27 -31
- data/app/controllers/shipit/status_controller.rb +1 -0
- data/app/controllers/shipit/tasks_controller.rb +3 -1
- data/app/controllers/shipit/webhooks_controller.rb +2 -1
- data/app/helpers/shipit/api_clients_helper.rb +1 -0
- data/app/helpers/shipit/chunks_helper.rb +3 -1
- data/app/helpers/shipit/deploys_helper.rb +7 -3
- data/app/helpers/shipit/github_url_helper.rb +5 -4
- data/app/helpers/shipit/merge_status_helper.rb +1 -0
- data/app/helpers/shipit/shipit_helper.rb +11 -10
- data/app/helpers/shipit/stacks_helper.rb +10 -11
- data/app/helpers/shipit/tasks_helper.rb +2 -1
- data/app/jobs/shipit/background_job/unique.rb +3 -2
- data/app/jobs/shipit/background_job.rb +9 -1
- data/app/jobs/shipit/cache_deploy_spec_job.rb +2 -1
- data/app/jobs/shipit/chunk_rollup_job.rb +1 -0
- data/app/jobs/shipit/clear_git_cache_job.rb +1 -0
- data/app/jobs/shipit/continuous_delivery_job.rb +5 -0
- data/app/jobs/shipit/create_on_github_job.rb +1 -0
- data/app/jobs/shipit/create_release_statuses_job.rb +2 -0
- data/app/jobs/shipit/deferred_touch_job.rb +1 -0
- data/app/jobs/shipit/deliver_hook_job.rb +1 -0
- data/app/jobs/shipit/destroy_job.rb +1 -0
- data/app/jobs/shipit/destroy_repository_job.rb +1 -0
- data/app/jobs/shipit/destroy_stack_job.rb +36 -15
- data/app/jobs/shipit/emit_event_job.rb +1 -0
- 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 +4 -2
- 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 +1 -0
- data/app/jobs/shipit/process_merge_requests_job.rb +2 -0
- data/app/jobs/shipit/purge_old_deliveries_job.rb +1 -0
- data/app/jobs/shipit/reap_dead_tasks_job.rb +1 -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 +1 -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 +6 -7
- data/app/models/concerns/shipit/deferred_touch.rb +5 -2
- data/app/models/shipit/anonymous_user.rb +4 -5
- data/app/models/shipit/api_client.rb +4 -2
- data/app/models/shipit/application_record.rb +1 -0
- data/app/models/shipit/check_run.rb +7 -6
- data/app/models/shipit/command_line_user.rb +4 -5
- data/app/models/shipit/commit.rb +46 -32
- data/app/models/shipit/commit_checks.rb +4 -2
- data/app/models/shipit/commit_deployment.rb +7 -5
- data/app/models/shipit/commit_deployment_status.rb +5 -2
- data/app/models/shipit/commit_message.rb +2 -0
- data/app/models/shipit/continuous_delivery_schedule.rb +84 -0
- data/app/models/shipit/delivery.rb +4 -3
- data/app/models/shipit/deploy.rb +46 -26
- data/app/models/shipit/deploy_spec/bundler_discovery.rb +3 -1
- data/app/models/shipit/deploy_spec/capistrano_discovery.rb +1 -0
- data/app/models/shipit/deploy_spec/file_system.rb +35 -16
- data/app/models/shipit/deploy_spec/kubernetes_discovery.rb +4 -3
- data/app/models/shipit/deploy_spec/lerna_discovery.rb +32 -31
- data/app/models/shipit/deploy_spec/npm_discovery.rb +18 -13
- data/app/models/shipit/deploy_spec/pypi_discovery.rb +5 -4
- data/app/models/shipit/deploy_spec/rubygems_discovery.rb +1 -0
- data/app/models/shipit/deploy_spec.rb +25 -30
- data/app/models/shipit/deploy_stats.rb +6 -1
- data/app/models/shipit/duration.rb +5 -3
- data/app/models/shipit/ephemeral_commit_checks.rb +8 -7
- data/app/models/shipit/github_hook.rb +1 -0
- data/app/models/shipit/github_status.rb +1 -0
- data/app/models/shipit/hook.rb +8 -6
- data/app/models/shipit/membership.rb +1 -0
- data/app/models/shipit/merge_request.rb +26 -16
- data/app/models/shipit/output_chunk.rb +1 -0
- data/app/models/shipit/provisioning_handler.rb +1 -0
- data/app/models/shipit/pull_request.rb +1 -1
- data/app/models/shipit/record.rb +1 -0
- data/app/models/shipit/release_status.rb +4 -3
- data/app/models/shipit/repository.rb +12 -11
- data/app/models/shipit/review_stack.rb +3 -1
- data/app/models/shipit/review_stack_provisioning_queue.rb +2 -2
- data/app/models/shipit/rollback.rb +2 -0
- data/app/models/shipit/stack.rb +59 -56
- data/app/models/shipit/status/common.rb +1 -0
- data/app/models/shipit/status/group.rb +5 -3
- data/app/models/shipit/status/missing.rb +2 -1
- data/app/models/shipit/status/unknown.rb +1 -0
- data/app/models/shipit/status.rb +5 -4
- data/app/models/shipit/task.rb +33 -28
- data/app/models/shipit/task_definition.rb +10 -7
- data/app/models/shipit/task_execution_strategy/default.rb +13 -13
- data/app/models/shipit/team.rb +13 -12
- data/app/models/shipit/undeployed_commit.rb +8 -3
- data/app/models/shipit/unlimited_api_client.rb +2 -2
- data/app/models/shipit/user.rb +21 -16
- data/app/models/shipit/variable_definition.rb +2 -1
- 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 +10 -10
- data/app/models/shipit/webhooks/handlers/pull_request/closed_handler.rb +1 -1
- data/app/models/shipit/webhooks/handlers/pull_request/edited_handler.rb +10 -10
- data/app/models/shipit/webhooks/handlers/pull_request/label_capturing_handler.rb +2 -2
- data/app/models/shipit/webhooks/handlers/pull_request/labeled_handler.rb +2 -2
- data/app/models/shipit/webhooks/handlers/pull_request/reopened_handler.rb +1 -1
- data/app/models/shipit/webhooks/handlers/pull_request/review_stack_adapter.rb +3 -3
- data/app/models/shipit/webhooks/handlers/pull_request/unlabeled_handler.rb +1 -1
- data/app/models/shipit/webhooks/handlers/push_handler.rb +2 -1
- data/app/models/shipit/webhooks/handlers/status_handler.rb +1 -0
- data/app/models/shipit/webhooks.rb +3 -2
- 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 +2 -1
- data/app/serializers/shipit/deploy_serializer.rb +1 -0
- data/app/serializers/shipit/hook_serializer.rb +1 -0
- data/app/serializers/shipit/merge_request_serializer.rb +2 -1
- 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 +4 -3
- data/app/serializers/shipit/tail_task_serializer.rb +4 -1
- data/app/serializers/shipit/task_serializer.rb +1 -0
- data/app/serializers/shipit/user_serializer.rb +1 -0
- data/app/validators/ascii_only_validator.rb +4 -3
- data/app/validators/subset_validator.rb +1 -0
- data/app/views/shipit/ccmenu/project.xml.builder +2 -1
- data/app/views/shipit/continuous_delivery_schedules/show.html.erb +59 -0
- data/app/views/shipit/stacks/_settings_form.erb +1 -0
- data/config/initializers/inflections.rb +1 -0
- data/config/locales/en.yml +1 -0
- data/config/routes.rb +21 -18
- data/db/migrate/20240821003007_add_continuous_delivery_schedules.rb +13 -0
- data/db/migrate/20250207203053_embiggen_github_ids.rb +8 -0
- data/lib/shipit/cast_value.rb +1 -0
- data/lib/shipit/command.rb +29 -9
- data/lib/shipit/commands.rb +4 -2
- data/lib/shipit/csv_serializer.rb +3 -0
- data/lib/shipit/deploy_commands.rb +2 -1
- data/lib/shipit/engine.rb +5 -4
- data/lib/shipit/environment_variables.rb +2 -0
- data/lib/shipit/first_parent_commits_iterator.rb +2 -3
- data/lib/shipit/flock.rb +11 -9
- data/lib/shipit/github_app.rb +14 -15
- 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 +1 -0
- data/lib/shipit/octokit_iterator.rb +2 -0
- data/lib/shipit/paginator.rb +1 -0
- data/lib/shipit/rollback_commands.rb +2 -1
- data/lib/shipit/same_site_cookie_middleware.rb +1 -0
- data/lib/shipit/simple_message_verifier.rb +1 -0
- data/lib/shipit/stack_commands.rb +34 -26
- data/lib/shipit/stat.rb +1 -0
- data/lib/shipit/task_commands.rb +7 -6
- data/lib/shipit/version.rb +2 -1
- data/lib/shipit.rb +29 -16
- data/lib/tasks/cron.rake +2 -1
- data/lib/tasks/dev.rake +3 -2
- data/lib/tasks/shipit.rake +3 -2
- data/lib/tasks/teams.rake +3 -2
- data/test/controllers/api/base_controller_test.rb +1 -0
- data/test/controllers/api/ccmenu_controller_test.rb +4 -3
- data/test/controllers/api/commits_controller_test.rb +1 -0
- data/test/controllers/api/deploys_controller_test.rb +2 -1
- data/test/controllers/api/hooks_controller_test.rb +6 -5
- data/test/controllers/api/locks_controller_test.rb +1 -0
- data/test/controllers/api/merge_requests_controller_test.rb +1 -0
- data/test/controllers/api/outputs_controller_test.rb +1 -0
- data/test/controllers/api/release_statuses_controller_test.rb +4 -3
- data/test/controllers/api/rollback_controller_test.rb +3 -2
- data/test/controllers/api/stacks_controller_test.rb +13 -12
- data/test/controllers/api/tasks_controller_test.rb +7 -6
- data/test/controllers/api_clients_controller_test.rb +10 -10
- data/test/controllers/ccmenu_controller_test.rb +1 -0
- data/test/controllers/commit_checks_controller_test.rb +1 -0
- data/test/controllers/commits_controller_test.rb +9 -8
- data/test/controllers/continuous_delivery_schedules_controller_test.rb +66 -0
- data/test/controllers/deploys_controller_test.rb +4 -2
- data/test/controllers/github_authentication_controller_test.rb +6 -4
- data/test/controllers/merge_requests_controller_test.rb +1 -0
- data/test/controllers/merge_status_controller_test.rb +5 -4
- data/test/controllers/release_statuses_controller_test.rb +1 -0
- data/test/controllers/repositories_controller_test.rb +6 -5
- data/test/controllers/rollbacks_controller_test.rb +3 -2
- data/test/controllers/stacks_controller_test.rb +7 -5
- data/test/controllers/status_controller_test.rb +1 -0
- data/test/controllers/tasks_controller_test.rb +5 -4
- data/test/controllers/webhooks_controller_test.rb +10 -9
- data/test/dummy/config/application.rb +1 -1
- data/test/dummy/db/schema.rb +33 -6
- data/test/fixtures/shipit/commits.yml +7 -7
- data/test/fixtures/shipit/stacks.yml +4 -10
- data/test/fixtures/shipit/tasks.yml +3 -3
- data/test/helpers/api_helper.rb +2 -3
- data/test/helpers/fixture_aliases_helper.rb +1 -0
- data/test/helpers/hooks_helper.rb +1 -0
- data/test/helpers/json_helper.rb +4 -3
- data/test/helpers/links_helper.rb +2 -1
- data/test/helpers/payloads_helper.rb +1 -0
- data/test/helpers/queries_helper.rb +4 -3
- data/test/jobs/cache_deploy_spec_job_test.rb +3 -2
- data/test/jobs/chunk_rollup_job_test.rb +3 -2
- data/test/jobs/deliver_hook_job_test.rb +1 -0
- data/test/jobs/destroy_repository_job_test.rb +1 -0
- data/test/jobs/destroy_stack_job_test.rb +12 -0
- data/test/jobs/emit_event_job_test.rb +1 -0
- 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 +22 -21
- data/test/jobs/mark_deploy_healthy_job_test.rb +1 -0
- data/test/jobs/perform_task_job_test.rb +3 -3
- data/test/jobs/process_merge_requests_job_test.rb +7 -6
- data/test/jobs/purge_old_deliveries_job_test.rb +1 -0
- data/test/jobs/reap_dead_tasks_job_test.rb +1 -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/shipit/background_job_test.rb +35 -0
- data/test/jobs/shipit/continuous_delivery_job_test.rb +31 -0
- data/test/jobs/unique_job_test.rb +3 -1
- data/test/jobs/update_github_last_deployed_ref_job_test.rb +1 -0
- data/test/middleware/same_site_cookie_middleware_test.rb +2 -2
- data/test/models/api_client_test.rb +1 -0
- data/test/models/commit_checks_test.rb +2 -1
- data/test/models/commit_deployment_status_test.rb +2 -1
- data/test/models/commit_deployment_test.rb +4 -3
- data/test/models/commits_test.rb +72 -70
- data/test/models/delivery_test.rb +3 -2
- data/test/models/deploy_spec_test.rb +113 -109
- data/test/models/deploy_stats_test.rb +1 -0
- data/test/models/deploys_test.rb +65 -56
- data/test/models/duration_test.rb +1 -1
- data/test/models/github_hook_test.rb +1 -0
- data/test/models/hook_test.rb +7 -4
- data/test/models/membership_test.rb +1 -0
- data/test/models/merge_request_test.rb +23 -20
- data/test/models/release_statuses_test.rb +2 -1
- data/test/models/rollbacks_test.rb +4 -3
- data/test/models/shipit/check_run_test.rb +16 -15
- data/test/models/shipit/continuous_delivery_schedule_test.rb +109 -0
- data/test/models/shipit/deploy_spec/file_system_test.rb +54 -10
- data/test/models/shipit/pull_request_test.rb +9 -9
- data/test/models/shipit/repository_test.rb +3 -2
- data/test/models/shipit/review_stack_provisioning_queue_test.rb +2 -2
- data/test/models/shipit/stack_test.rb +30 -29
- data/test/models/shipit/webhooks/handlers/pull_request/closed_handler_test.rb +36 -34
- data/test/models/shipit/webhooks/handlers/pull_request/label_capturing_handler_test.rb +28 -28
- data/test/models/shipit/webhooks/handlers/pull_request/labeled_handler_test.rb +42 -42
- data/test/models/shipit/webhooks/handlers/pull_request/opened_handler_test.rb +33 -33
- data/test/models/shipit/webhooks/handlers/pull_request/reopened_handler_test.rb +37 -37
- data/test/models/shipit/webhooks/handlers/pull_request/review_stack_adapter_test.rb +1 -1
- data/test/models/shipit/webhooks/handlers/pull_request/unlabeled_handler_test.rb +44 -42
- data/test/models/shipit/webhooks/handlers_test.rb +1 -0
- data/test/models/status/group_test.rb +3 -2
- data/test/models/status/missing_test.rb +1 -0
- data/test/models/status_test.rb +2 -1
- data/test/models/task_definitions_test.rb +7 -6
- data/test/models/tasks_test.rb +5 -4
- data/test/models/team_test.rb +5 -4
- data/test/models/undeployed_commits_test.rb +10 -9
- data/test/models/users_test.rb +21 -20
- data/test/test_command_integration.rb +1 -1
- data/test/test_helper.rb +11 -9
- data/test/unit/anonymous_user_serializer_test.rb +1 -0
- data/test/unit/command_test.rb +10 -1
- data/test/unit/commands_test.rb +1 -0
- data/test/unit/commit_serializer_test.rb +1 -0
- data/test/unit/csv_serializer_test.rb +3 -2
- data/test/unit/deploy_commands_test.rb +33 -23
- data/test/unit/deploy_serializer_test.rb +1 -0
- data/test/unit/environment_variables_test.rb +2 -1
- data/test/unit/github_app_test.rb +10 -9
- data/test/unit/github_apps_test.rb +19 -18
- data/test/unit/github_url_helper_test.rb +1 -0
- data/test/unit/line_buffer_test.rb +1 -1
- data/test/unit/rollback_commands_test.rb +2 -1
- data/test/unit/shipit_helper_test.rb +1 -0
- data/test/unit/shipit_test.rb +47 -1
- data/test/unit/user_serializer_test.rb +1 -0
- data/test/unit/variable_definition_test.rb +4 -3
- metadata +53 -43
data/app/models/shipit/status.rb
CHANGED
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Shipit
|
3
4
|
class Status < Record
|
4
5
|
include Common
|
5
6
|
include DeferredTouch
|
6
7
|
|
7
|
-
STATES = %w
|
8
|
-
enum state
|
8
|
+
STATES = %w[pending success failure error].freeze
|
9
|
+
enum :state, STATES.zip(STATES).to_h
|
9
10
|
|
10
11
|
belongs_to :stack, required: true
|
11
12
|
belongs_to :commit, required: true
|
@@ -22,12 +23,12 @@ module Shipit
|
|
22
23
|
class << self
|
23
24
|
def replicate_from_github!(stack_id, github_status)
|
24
25
|
find_or_create_by!(
|
25
|
-
stack_id
|
26
|
+
stack_id:,
|
26
27
|
state: github_status.state,
|
27
28
|
description: github_status.description,
|
28
29
|
target_url: github_status.target_url,
|
29
30
|
context: github_status.context,
|
30
|
-
created_at: github_status.created_at
|
31
|
+
created_at: github_status.created_at
|
31
32
|
)
|
32
33
|
end
|
33
34
|
end
|
data/app/models/shipit/task.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Shipit
|
3
4
|
class Task < Record
|
4
5
|
include DeferredTouch
|
@@ -10,12 +11,12 @@ module Shipit
|
|
10
11
|
end
|
11
12
|
|
12
13
|
PRESENCE_CHECK_TIMEOUT = 30
|
13
|
-
ACTIVE_STATUSES = %w
|
14
|
-
COMPLETED_STATUSES = %w
|
15
|
-
UNSUCCESSFUL_STATUSES = %w
|
14
|
+
ACTIVE_STATUSES = %w[pending running aborting].freeze
|
15
|
+
COMPLETED_STATUSES = %w[success flapping faulty validating].freeze
|
16
|
+
UNSUCCESSFUL_STATUSES = %w[error failed aborted flapping timedout faulty].freeze
|
16
17
|
OUTPUT_SIZE_LIMIT = 16.megabytes # A MySQL mediumblob
|
17
18
|
HUMAN_READABLE_OUTPUT_LIMIT = ActionController::Base.helpers.number_to_human_size(OUTPUT_SIZE_LIMIT)
|
18
|
-
OUTPUT_TRUNCATED_MESSAGE = "Output exceeded the limit of #{HUMAN_READABLE_OUTPUT_LIMIT} and was truncated\n"
|
19
|
+
OUTPUT_TRUNCATED_MESSAGE = "Output exceeded the limit of #{HUMAN_READABLE_OUTPUT_LIMIT} and was truncated\n".freeze
|
19
20
|
|
20
21
|
attr_accessor :pid
|
21
22
|
|
@@ -35,6 +36,7 @@ module Shipit
|
|
35
36
|
class << self
|
36
37
|
def dump(hash)
|
37
38
|
raise TypeError, "Task#env should be a Hash[String => String]" unless hash.is_a?(Hash)
|
39
|
+
|
38
40
|
hash = hash.to_h.stringify_keys
|
39
41
|
hash.transform_values! do |value|
|
40
42
|
case value
|
@@ -49,7 +51,7 @@ module Shipit
|
|
49
51
|
end
|
50
52
|
|
51
53
|
def load(hash)
|
52
|
-
hash
|
54
|
+
hash.to_h # cast back to a real hash
|
53
55
|
end
|
54
56
|
|
55
57
|
def new
|
@@ -104,11 +106,11 @@ module Shipit
|
|
104
106
|
task.ended_at ||= Time.now.utc
|
105
107
|
end
|
106
108
|
|
107
|
-
after_transition any => %i
|
109
|
+
after_transition any => %i[success failed error timedout] do |task|
|
108
110
|
task.async_refresh_deployed_revision
|
109
111
|
end
|
110
112
|
|
111
|
-
after_transition any => %i
|
113
|
+
after_transition any => %i[aborted success failed error timedout] do |task|
|
112
114
|
task.schedule_rollup_chunks
|
113
115
|
end
|
114
116
|
|
@@ -120,7 +122,7 @@ module Shipit
|
|
120
122
|
task.async_update_estimated_deploy_duration
|
121
123
|
end
|
122
124
|
|
123
|
-
after_transition any => %i
|
125
|
+
after_transition any => %i[failed error timedout] do |task|
|
124
126
|
task.retry_if_necessary
|
125
127
|
end
|
126
128
|
|
@@ -129,19 +131,19 @@ module Shipit
|
|
129
131
|
end
|
130
132
|
|
131
133
|
event :failure do
|
132
|
-
transition %i
|
134
|
+
transition %i[running flapping] => :failed
|
133
135
|
end
|
134
136
|
|
135
137
|
event :complete do
|
136
|
-
transition %i
|
138
|
+
transition %i[running flapping validating faulty] => :success
|
137
139
|
end
|
138
140
|
|
139
141
|
event :enter_validation do
|
140
|
-
transition %i
|
142
|
+
transition %i[running flapping] => :validating
|
141
143
|
end
|
142
144
|
|
143
145
|
event :mark_faulty do
|
144
|
-
transition %i
|
146
|
+
transition %i[validating success] => :faulty
|
145
147
|
end
|
146
148
|
|
147
149
|
event :error do
|
@@ -153,7 +155,7 @@ module Shipit
|
|
153
155
|
end
|
154
156
|
|
155
157
|
event :aborting do
|
156
|
-
transition all - %i
|
158
|
+
transition all - %i[aborted] => :aborting
|
157
159
|
end
|
158
160
|
|
159
161
|
event :aborted do
|
@@ -161,7 +163,7 @@ module Shipit
|
|
161
163
|
end
|
162
164
|
|
163
165
|
event :flap do
|
164
|
-
transition %i
|
166
|
+
transition %i[failed error timedout success] => :flapping
|
165
167
|
end
|
166
168
|
|
167
169
|
state :pending
|
@@ -206,7 +208,7 @@ module Shipit
|
|
206
208
|
end
|
207
209
|
|
208
210
|
delegate :acquire_git_cache_lock, :async_refresh_deployed_revision, :async_update_estimated_deploy_duration,
|
209
|
-
|
211
|
+
to: :stack
|
210
212
|
|
211
213
|
delegate :checklist, to: :definition
|
212
214
|
|
@@ -219,16 +221,18 @@ module Shipit
|
|
219
221
|
end
|
220
222
|
|
221
223
|
def spec
|
222
|
-
@spec ||= DeploySpec::FileSystem.new(working_directory, stack
|
224
|
+
@spec ||= DeploySpec::FileSystem.new(working_directory, stack)
|
223
225
|
end
|
224
226
|
|
225
227
|
def enqueue
|
226
228
|
raise "only persisted jobs can be enqueued" unless persisted?
|
229
|
+
|
227
230
|
PerformTaskJob.perform_later(self)
|
228
231
|
end
|
229
232
|
|
230
233
|
def run_now!
|
231
234
|
raise "only persisted jobs can be run" unless persisted?
|
235
|
+
|
232
236
|
PerformTaskJob.perform_now(self)
|
233
237
|
end
|
234
238
|
|
@@ -350,10 +354,10 @@ module Shipit
|
|
350
354
|
end
|
351
355
|
end
|
352
356
|
|
353
|
-
def abort!(rollback_once_aborted: false, rollback_once_aborted_to: nil
|
357
|
+
def abort!(aborted_by:, rollback_once_aborted: false, rollback_once_aborted_to: nil)
|
354
358
|
update!(
|
355
|
-
rollback_once_aborted
|
356
|
-
rollback_once_aborted_to
|
359
|
+
rollback_once_aborted:,
|
360
|
+
rollback_once_aborted_to:,
|
357
361
|
aborted_by_id: aborted_by.id
|
358
362
|
)
|
359
363
|
|
@@ -383,12 +387,13 @@ module Shipit
|
|
383
387
|
|
384
388
|
def emit_hooks_if_status_changed
|
385
389
|
return unless @status_changed
|
390
|
+
|
386
391
|
@status_changed = nil
|
387
392
|
emit_hooks
|
388
393
|
end
|
389
394
|
|
390
395
|
def emit_hooks
|
391
|
-
Hook.emit(hook_event, stack, hook_event => self, status
|
396
|
+
Hook.emit(hook_event, stack, hook_event => self, status:, stack:)
|
392
397
|
end
|
393
398
|
|
394
399
|
def hook_event
|
@@ -427,13 +432,13 @@ module Shipit
|
|
427
432
|
5.minutes.ago
|
428
433
|
end
|
429
434
|
|
430
|
-
ZOMBIE_STATES = %w
|
435
|
+
ZOMBIE_STATES = %w[running aborting].freeze
|
431
436
|
private_constant :ZOMBIE_STATES
|
432
437
|
def self.zombies
|
433
438
|
where(status: ZOMBIE_STATES)
|
434
439
|
.where(
|
435
440
|
"created_at <= :recently",
|
436
|
-
recently: recently_created_at
|
441
|
+
recently: recently_created_at
|
437
442
|
)
|
438
443
|
.reject(&:alive?)
|
439
444
|
end
|
@@ -441,13 +446,13 @@ module Shipit
|
|
441
446
|
def retry_if_necessary
|
442
447
|
return unless retries_configured? && !stack.reload.locked?
|
443
448
|
|
444
|
-
|
445
|
-
retry_task = duplicate_task
|
446
|
-
retry_task.retry_attempt = duplicate_task.retry_attempt + 1
|
447
|
-
retry_task.save!
|
449
|
+
return unless retry_attempt < max_retries
|
448
450
|
|
449
|
-
|
450
|
-
|
451
|
+
retry_task = duplicate_task
|
452
|
+
retry_task.retry_attempt = duplicate_task.retry_attempt + 1
|
453
|
+
retry_task.save!
|
454
|
+
|
455
|
+
retry_task.enqueue
|
451
456
|
end
|
452
457
|
|
453
458
|
def retries_configured?
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Shipit
|
3
4
|
class TaskDefinition
|
4
5
|
NotFound = Class.new(StandardError)
|
@@ -6,18 +7,20 @@ module Shipit
|
|
6
7
|
class << self
|
7
8
|
def load(payload)
|
8
9
|
return if payload.blank?
|
10
|
+
|
9
11
|
json = JSON.parse(payload)
|
10
12
|
new(json.delete('id'), json)
|
11
13
|
end
|
12
14
|
|
13
15
|
def dump(definition)
|
14
16
|
return if definition.blank?
|
17
|
+
|
15
18
|
JSON.dump(definition.as_json)
|
16
19
|
end
|
17
20
|
end
|
18
21
|
|
19
22
|
attr_reader :id, :action, :description, :steps, :checklist, :variables
|
20
|
-
|
23
|
+
alias to_param id
|
21
24
|
|
22
25
|
def initialize(id, config)
|
23
26
|
@id = id
|
@@ -46,14 +49,14 @@ module Shipit
|
|
46
49
|
|
47
50
|
def as_json
|
48
51
|
{
|
49
|
-
id
|
50
|
-
action
|
52
|
+
id:,
|
53
|
+
action:,
|
51
54
|
title: @title,
|
52
|
-
description
|
53
|
-
steps
|
55
|
+
description:,
|
56
|
+
steps:,
|
54
57
|
variables: variables.map(&:to_h),
|
55
|
-
checklist
|
56
|
-
allow_concurrency: allow_concurrency
|
58
|
+
checklist:,
|
59
|
+
allow_concurrency: allow_concurrency?
|
57
60
|
}
|
58
61
|
end
|
59
62
|
|
@@ -21,16 +21,16 @@ module Shipit
|
|
21
21
|
perform_task
|
22
22
|
@task.write("\nCompleted successfully\n")
|
23
23
|
@task.report_complete!
|
24
|
-
rescue Command::TimedOut =>
|
25
|
-
@task.write("\n#{
|
26
|
-
@task.report_timeout!(
|
27
|
-
rescue Command::Error =>
|
28
|
-
@task.write("\n#{
|
29
|
-
@task.report_failure!(
|
30
|
-
rescue StandardError =>
|
31
|
-
@task.report_error!(
|
32
|
-
rescue Exception =>
|
33
|
-
@task.report_error!(
|
24
|
+
rescue Command::TimedOut => e
|
25
|
+
@task.write("\n#{e.message}\n")
|
26
|
+
@task.report_timeout!(e)
|
27
|
+
rescue Command::Error => e
|
28
|
+
@task.write("\n#{e.message}\n")
|
29
|
+
@task.report_failure!(e)
|
30
|
+
rescue StandardError => e
|
31
|
+
@task.report_error!(e)
|
32
|
+
rescue Exception => e
|
33
|
+
@task.report_error!(e)
|
34
34
|
raise
|
35
35
|
end
|
36
36
|
|
@@ -42,8 +42,8 @@ module Shipit
|
|
42
42
|
else
|
43
43
|
@task.write("Can't abort, no recorded pid, WTF?\n")
|
44
44
|
end
|
45
|
-
rescue SystemCallError =>
|
46
|
-
@task.write("kill: (#{pid}) - #{
|
45
|
+
rescue SystemCallError => e
|
46
|
+
@task.write("kill: (#{pid}) - #{e.message}\n")
|
47
47
|
end
|
48
48
|
|
49
49
|
def check_for_abort
|
@@ -94,7 +94,7 @@ module Shipit
|
|
94
94
|
@task.write(line)
|
95
95
|
end
|
96
96
|
finished_at = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
97
|
-
@task.write("pid: #{command.pid} finished in: #{finished_at - started_at} seconds\n")
|
97
|
+
@task.write("pid: #{command.pid} finished in: #{(finished_at - started_at).round(3)} seconds\n")
|
98
98
|
command.success?
|
99
99
|
end
|
100
100
|
|
data/app/models/shipit/team.rb
CHANGED
@@ -1,32 +1,33 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Shipit
|
3
4
|
class Team < Record
|
4
|
-
REQUIRED_HOOKS = %i
|
5
|
+
REQUIRED_HOOKS = %i[membership].freeze
|
5
6
|
|
6
7
|
has_many :memberships
|
7
8
|
has_many :members, class_name: :User, through: :memberships, source: :user
|
8
9
|
|
9
10
|
has_many :github_hooks,
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
11
|
+
-> { where(event: REQUIRED_HOOKS) },
|
12
|
+
foreign_key: :organization,
|
13
|
+
primary_key: :organization,
|
14
|
+
class_name: 'GithubHook::Organization',
|
15
|
+
inverse_of: false
|
15
16
|
|
16
17
|
class << self
|
17
18
|
def find_or_create_by_handle(handle)
|
18
19
|
organization, slug = handle.split('/').map(&:downcase)
|
19
|
-
find_by(organization
|
20
|
+
find_by(organization:, slug:) || fetch_and_create_from_github(organization, slug)
|
20
21
|
end
|
21
22
|
|
22
23
|
def fetch_and_create_from_github(organization, slug)
|
23
|
-
|
24
|
-
|
25
|
-
|
24
|
+
return unless github_team = find_team_on_github(organization, slug)
|
25
|
+
|
26
|
+
create!(github_team:, organization:)
|
26
27
|
end
|
27
28
|
|
28
29
|
def find_team_on_github(organization, slug)
|
29
|
-
gh_api = Shipit.github(organization:
|
30
|
+
gh_api = Shipit.github(organization:).api
|
30
31
|
teams = Shipit::OctokitIterator.new(github_api: gh_api) { gh_api.org_teams(organization, per_page: 100) }
|
31
32
|
teams.find { |t| t.slug == slug }
|
32
33
|
rescue Octokit::NotFound
|
@@ -42,7 +43,7 @@ module Shipit
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def refresh_members!
|
45
|
-
github_api = Shipit.github(organization:
|
46
|
+
github_api = Shipit.github(organization:).api
|
46
47
|
github_members = Shipit::OctokitIterator.new(github_api.get(api_url).rels[:members])
|
47
48
|
members = github_members.map { |u| User.find_or_create_from_github(u) }
|
48
49
|
self.members = members
|
@@ -1,4 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# rubocop:disable Lint/MissingCopEnableDirective, Style/OptionalBooleanParameter
|
4
|
+
# Disabling for now because we need to support the `bypass_safeties` parameter
|
5
|
+
# in the `deploy_state` and `redeploy_state` methods. We can revisit this later.
|
6
|
+
|
7
|
+
require 'delegate'
|
2
8
|
module Shipit
|
3
9
|
class UndeployedCommit < DelegateClass(Commit)
|
4
10
|
attr_reader :index
|
@@ -26,9 +32,7 @@ module Shipit
|
|
26
32
|
|
27
33
|
def redeploy_state(bypass_safeties = false)
|
28
34
|
state = 'allowed'
|
29
|
-
|
30
|
-
state = 'deploying' if stack.active_task?
|
31
|
-
end
|
35
|
+
state = 'deploying' if !bypass_safeties && stack.active_task?
|
32
36
|
state
|
33
37
|
end
|
34
38
|
|
@@ -50,6 +54,7 @@ module Shipit
|
|
50
54
|
|
51
55
|
def blocked?
|
52
56
|
return @blocked if defined?(@blocked)
|
57
|
+
|
53
58
|
@blocked = super
|
54
59
|
end
|
55
60
|
end
|
data/app/models/shipit/user.rb
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Shipit
|
3
4
|
class User < Record
|
4
5
|
DEFAULT_AVATAR = URI.parse('https://avatars.githubusercontent.com/u/583231?')
|
5
6
|
|
6
|
-
self.ignored_columns = %w
|
7
|
+
self.ignored_columns = %w[encrypted_github_access_token_iv]
|
7
8
|
|
8
9
|
has_many :memberships
|
9
10
|
has_many :teams, through: :memberships
|
@@ -19,7 +20,7 @@ module Shipit
|
|
19
20
|
after_find :discard_outdated_credentials!
|
20
21
|
|
21
22
|
def self.find_or_create_by_login!(login)
|
22
|
-
find_or_create_by!(login:
|
23
|
+
find_or_create_by!(login:) do |user|
|
23
24
|
# Users are global, any app can be used
|
24
25
|
# This will not work for users that only exist in an Enterprise install
|
25
26
|
user.github_user = Shipit.github.api.user(login)
|
@@ -31,7 +32,7 @@ module Shipit
|
|
31
32
|
end
|
32
33
|
|
33
34
|
def self.find_or_create_author_from_github_commit(github_commit)
|
34
|
-
if (match_info = github_commit.commit.message.match(/^#{MergeRequest::MERGE_REQUEST_FIELD}: ([\w
|
35
|
+
if (match_info = github_commit.commit.message.match(/^#{MergeRequest::MERGE_REQUEST_FIELD}: ([\w\-.]+)$/))
|
35
36
|
begin
|
36
37
|
return find_or_create_by_login!(match_info[1])
|
37
38
|
rescue Octokit::NotFound
|
@@ -48,11 +49,12 @@ module Shipit
|
|
48
49
|
|
49
50
|
def self.find_from_github(github_user)
|
50
51
|
return unless github_user.id
|
52
|
+
|
51
53
|
find_by(github_id: github_user.id)
|
52
54
|
end
|
53
55
|
|
54
56
|
def self.create_from_github(github_user)
|
55
|
-
create(github_user:
|
57
|
+
create(github_user:)
|
56
58
|
end
|
57
59
|
|
58
60
|
def self.refresh_shard(shard_index, shards_count)
|
@@ -68,7 +70,7 @@ module Shipit
|
|
68
70
|
end
|
69
71
|
|
70
72
|
def identifiers_for_ping
|
71
|
-
{ github_id
|
73
|
+
{ github_id:, name:, email:, github_login: login }
|
72
74
|
end
|
73
75
|
|
74
76
|
def logged_in?
|
@@ -81,12 +83,14 @@ module Shipit
|
|
81
83
|
|
82
84
|
def repositories_contributed_to
|
83
85
|
return [] unless id
|
86
|
+
|
84
87
|
Stack.where(id: stacks_contributed_to).distinct.pluck(:repository_id)
|
85
88
|
end
|
86
89
|
|
87
90
|
def stacks_contributed_to
|
88
91
|
return [] unless id
|
89
|
-
|
92
|
+
|
93
|
+
Commit.where('author_id = :id or committer_id = :id', id:).distinct.pluck(:stack_id)
|
90
94
|
end
|
91
95
|
|
92
96
|
def refresh_from_github!
|
@@ -112,7 +116,7 @@ module Shipit
|
|
112
116
|
email: appropriate_email_for(github_user),
|
113
117
|
login: github_user.login,
|
114
118
|
avatar_url: github_user.avatar_url,
|
115
|
-
api_url: github_user.url
|
119
|
+
api_url: github_user.url
|
116
120
|
)
|
117
121
|
end
|
118
122
|
|
@@ -132,18 +136,19 @@ module Shipit
|
|
132
136
|
private
|
133
137
|
|
134
138
|
def discard_outdated_credentials!
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
139
|
+
return unless encrypted_github_access_token_before_type_cast.present?
|
140
|
+
|
141
|
+
begin
|
142
|
+
encrypted_github_access_token
|
143
|
+
rescue ActiveRecord::Encryption::Errors::Decryption
|
144
|
+
update_column(:encrypted_github_access_token, nil)
|
141
145
|
end
|
142
146
|
end
|
143
147
|
|
144
148
|
def identify_renamed_user!
|
145
149
|
last_commit = commits.last
|
146
150
|
return unless last_commit
|
151
|
+
|
147
152
|
github_author = last_commit.github_commit.author
|
148
153
|
update!(github_user: github_author)
|
149
154
|
rescue Octokit::NotFound
|
@@ -163,9 +168,9 @@ module Shipit
|
|
163
168
|
|
164
169
|
begin
|
165
170
|
github_api.emails
|
166
|
-
|
167
|
-
|
168
|
-
|
171
|
+
.sort_by { |e| e.primary ? 0 : 1 }
|
172
|
+
.map(&:email)
|
173
|
+
.find { |e| email_valid_and_preferred?(e) }
|
169
174
|
rescue Octokit::NotFound, Octokit::Forbidden, Octokit::Unauthorized
|
170
175
|
# If the user hasn't agreed to the necessary permission, we can't access their private emails.
|
171
176
|
Rails.logger.warn("Failed to retrieve emails for user '#{github_user.name || github_user.login}'")
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Shipit
|
3
4
|
class VariableDefinition
|
4
5
|
attr_reader :name, :title, :default, :select
|
@@ -20,7 +21,7 @@ module Shipit
|
|
20
21
|
'name' => @name,
|
21
22
|
'title' => @title,
|
22
23
|
'default' => @default,
|
23
|
-
'select' => @select
|
24
|
+
'select' => @select
|
24
25
|
}
|
25
26
|
end
|
26
27
|
end
|
@@ -52,16 +52,16 @@ module Shipit
|
|
52
52
|
|
53
53
|
def pull_request
|
54
54
|
@pull_request ||= Shipit::PullRequest
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
55
|
+
.joins(:stack, stack: :repository)
|
56
|
+
.find_by(
|
57
|
+
number: params.number,
|
58
|
+
stacks: {
|
59
|
+
repositories:
|
60
|
+
{
|
61
|
+
id: repository.id
|
62
|
+
}
|
63
|
+
}
|
64
|
+
)
|
65
65
|
end
|
66
66
|
|
67
67
|
def repository
|
@@ -55,7 +55,7 @@ module Shipit
|
|
55
55
|
def review_stack
|
56
56
|
@review_stack ||=
|
57
57
|
Shipit::Webhooks::Handlers::PullRequest::ReviewStackAdapter
|
58
|
-
|
58
|
+
.new(params, scope: repository.review_stacks)
|
59
59
|
end
|
60
60
|
|
61
61
|
def respond_to_pull_request_closed?
|
@@ -48,16 +48,16 @@ module Shipit
|
|
48
48
|
|
49
49
|
def pull_request
|
50
50
|
@pull_request ||= Shipit::PullRequest
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
51
|
+
.joins(:stack, stack: :repository)
|
52
|
+
.find_by(
|
53
|
+
number: params.number,
|
54
|
+
stacks: {
|
55
|
+
repositories:
|
56
|
+
{
|
57
|
+
id: repository.id
|
58
|
+
}
|
59
|
+
}
|
60
|
+
)
|
61
61
|
end
|
62
62
|
|
63
63
|
def repository
|
@@ -104,13 +104,13 @@ module Shipit
|
|
104
104
|
def review_stack
|
105
105
|
@review_stack ||=
|
106
106
|
Shipit::Webhooks::Handlers::PullRequest::ReviewStackAdapter
|
107
|
-
|
107
|
+
.new(params, scope: repository.review_stacks)
|
108
108
|
end
|
109
109
|
|
110
110
|
def repository
|
111
111
|
@repository ||=
|
112
112
|
Shipit::Repository
|
113
|
-
|
113
|
+
.from_github_repo_name(params.repository.full_name) || NullRepository.new
|
114
114
|
end
|
115
115
|
|
116
116
|
def stack
|
@@ -59,12 +59,12 @@ module Shipit
|
|
59
59
|
def stack
|
60
60
|
@stack ||=
|
61
61
|
Shipit::Webhooks::Handlers::PullRequest::ReviewStackAdapter
|
62
|
-
|
62
|
+
.new(params, scope: repository.review_stacks)
|
63
63
|
end
|
64
64
|
|
65
65
|
def repository
|
66
66
|
@repository ||= Shipit::Repository.from_github_repo_name(params.repository.full_name) ||
|
67
|
-
|
67
|
+
Shipit::NullRepository.new
|
68
68
|
end
|
69
69
|
|
70
70
|
def pull_request
|