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/lib/shipit/engine.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Shipit
|
3
4
|
class Engine < ::Rails::Engine
|
4
5
|
isolate_namespace Shipit
|
@@ -11,7 +12,7 @@ module Shipit
|
|
11
12
|
# But if AR Encryption is already configured, we just use that
|
12
13
|
app.credentials[:active_record_encryption] = {
|
13
14
|
primary_key: Shipit.user_access_tokens_key,
|
14
|
-
key_derivation_salt: Digest::SHA256.digest("salt:".b + Shipit.user_access_tokens_key)
|
15
|
+
key_derivation_salt: Digest::SHA256.digest("salt:".b + Shipit.user_access_tokens_key)
|
15
16
|
}
|
16
17
|
end
|
17
18
|
end
|
@@ -24,16 +25,16 @@ module Shipit
|
|
24
25
|
Rails.application.credentials.deep_symbolize_keys!
|
25
26
|
|
26
27
|
app.config.assets.paths << Emoji.images_path
|
27
|
-
app.config.assets.precompile += %w
|
28
|
+
app.config.assets.precompile += %w[
|
28
29
|
favicon.ico
|
29
30
|
task.js
|
30
31
|
shipit.js
|
31
32
|
shipit.css
|
32
33
|
merge_status.js
|
33
34
|
merge_status.css
|
34
|
-
|
35
|
+
]
|
35
36
|
app.config.assets.precompile << proc do |path|
|
36
|
-
path =~ %r{\Aplugins/[
|
37
|
+
path =~ %r{\Aplugins/[-\w]+\.(js|css)\Z}
|
37
38
|
end
|
38
39
|
app.config.assets.precompile << proc do |path|
|
39
40
|
path.end_with?('.svg') || (path.start_with?('emoji/') && path.end_with?('.png'))
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Shipit
|
3
4
|
class EnvironmentVariables
|
4
5
|
NotPermitted = Class.new(StandardError)
|
@@ -12,6 +13,7 @@ module Shipit
|
|
12
13
|
def permit(variable_definitions)
|
13
14
|
return {} unless @env
|
14
15
|
raise "A whitelist is required to sanitize environment variables" unless variable_definitions
|
16
|
+
|
15
17
|
sanitize_env_vars(variable_definitions)
|
16
18
|
end
|
17
19
|
|
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Shipit
|
3
4
|
class FirstParentCommitsIterator < OctokitIterator
|
4
5
|
def each
|
@@ -9,9 +10,7 @@ module Shipit
|
|
9
10
|
next
|
10
11
|
end
|
11
12
|
|
12
|
-
if last_ancestor.parents.empty? || last_ancestor.parents.first.sha == commit.sha
|
13
|
-
yield last_ancestor = commit
|
14
|
-
end
|
13
|
+
yield last_ancestor = commit if last_ancestor.parents.empty? || last_ancestor.parents.first.sha == commit.sha
|
15
14
|
end
|
16
15
|
end
|
17
16
|
end
|
data/lib/shipit/flock.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'English'
|
3
4
|
require 'timeout'
|
4
5
|
require 'pathname'
|
@@ -16,19 +17,20 @@ module Shipit
|
|
16
17
|
|
17
18
|
def lock(timeout:)
|
18
19
|
return yield if @acquired
|
20
|
+
|
19
21
|
path.parent.mkpath
|
20
22
|
path.open('w') do |file|
|
21
|
-
|
22
|
-
file.write($PROCESS_ID.to_s)
|
23
|
-
@acquired = true
|
24
|
-
begin
|
25
|
-
yield
|
26
|
-
ensure
|
27
|
-
@acquired = false
|
28
|
-
end
|
29
|
-
else
|
23
|
+
unless retrying(timeout:) { file.flock(File::LOCK_EX | File::LOCK_NB) }
|
30
24
|
raise TimeoutError, "Couldn't acquire lock for #{path} in #{timeout} seconds"
|
31
25
|
end
|
26
|
+
|
27
|
+
file.write($PROCESS_ID.to_s)
|
28
|
+
@acquired = true
|
29
|
+
begin
|
30
|
+
yield
|
31
|
+
ensure
|
32
|
+
@acquired = false
|
33
|
+
end
|
32
34
|
end
|
33
35
|
end
|
34
36
|
|
data/lib/shipit/github_app.rb
CHANGED
@@ -1,8 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
module Shipit
|
3
4
|
class GitHubApp
|
4
|
-
include Mutex_m
|
5
|
-
|
6
5
|
class Token
|
7
6
|
class << self
|
8
7
|
def from_github(github_response)
|
@@ -44,6 +43,7 @@ module Shipit
|
|
44
43
|
|
45
44
|
def initialize(organization, config)
|
46
45
|
super()
|
46
|
+
@mutex = Mutex.new
|
47
47
|
@organization = organization
|
48
48
|
@config = (config || {}).with_indifferent_access
|
49
49
|
@domain = @config[:domain] || DOMAIN
|
@@ -62,9 +62,7 @@ module Shipit
|
|
62
62
|
|
63
63
|
def api
|
64
64
|
client = (Thread.current[:github_client] ||= new_client(access_token: token))
|
65
|
-
if client.access_token != token
|
66
|
-
client.access_token = token
|
67
|
-
end
|
65
|
+
client.access_token = token if client.access_token != token
|
68
66
|
client
|
69
67
|
end
|
70
68
|
|
@@ -88,7 +86,7 @@ module Shipit
|
|
88
86
|
return 't0kEn' if Rails.env.test? # TODO: figure out something cleaner
|
89
87
|
return unless private_key && app_id && installation_id
|
90
88
|
|
91
|
-
@token = @token.presence || synchronize { @token.presence || fetch_new_token }
|
89
|
+
@token = @token.presence || @mutex.synchronize { @token.presence || fetch_new_token }
|
92
90
|
@token.to_s
|
93
91
|
end
|
94
92
|
|
@@ -99,14 +97,15 @@ module Shipit
|
|
99
97
|
Rails.cache.fetch(
|
100
98
|
"github:integration:#{cache_key}access-token",
|
101
99
|
expires_in: GITHUB_TOKEN_RAILS_CACHE_LIFETIME,
|
102
|
-
race_condition_ttl: 4.minutes
|
100
|
+
race_condition_ttl: 4.minutes
|
103
101
|
) do
|
104
102
|
response = new_client(bearer_token: authentication_payload).create_app_installation_access_token(
|
105
|
-
installation_id
|
103
|
+
installation_id
|
106
104
|
)
|
107
105
|
token = Token.from_github(response)
|
108
106
|
raise AuthenticationFailed if token.blank?
|
109
|
-
|
107
|
+
|
108
|
+
Rails.logger.info("Created GitHub access token ending #{token.to_s[-5..]}, expires at #{token.expires_at}"\
|
110
109
|
" and will be refreshed at #{token&.refresh_at}")
|
111
110
|
token
|
112
111
|
end
|
@@ -122,14 +121,14 @@ module Shipit
|
|
122
121
|
options = {
|
123
122
|
site: api_endpoint,
|
124
123
|
authorize_url: url('/login/oauth/authorize'),
|
125
|
-
token_url: url('/login/oauth/access_token')
|
124
|
+
token_url: url('/login/oauth/access_token')
|
126
125
|
}
|
127
126
|
end
|
128
127
|
|
129
128
|
[
|
130
129
|
oauth_id,
|
131
130
|
oauth_secret,
|
132
|
-
client_options: options
|
131
|
+
{ client_options: options }
|
133
132
|
]
|
134
133
|
end
|
135
134
|
|
@@ -153,8 +152,8 @@ module Shipit
|
|
153
152
|
def new_client(options = {})
|
154
153
|
if enterprise?
|
155
154
|
options = options.reverse_merge(
|
156
|
-
api_endpoint
|
157
|
-
web_endpoint:
|
155
|
+
api_endpoint:,
|
156
|
+
web_endpoint:
|
158
157
|
)
|
159
158
|
end
|
160
159
|
client = Octokit::Client.new(options)
|
@@ -173,7 +172,7 @@ module Shipit
|
|
173
172
|
shared_cache: false,
|
174
173
|
store: Rails.cache,
|
175
174
|
logger: Rails.logger,
|
176
|
-
serializer: NullSerializer
|
175
|
+
serializer: NullSerializer
|
177
176
|
)
|
178
177
|
builder.use(GitHubHTTPCacheMiddleware)
|
179
178
|
builder.use(Octokit::Response::RaiseError)
|
@@ -197,7 +196,7 @@ module Shipit
|
|
197
196
|
payload = {
|
198
197
|
iat: Time.now.to_i,
|
199
198
|
exp: 10.minutes.from_now.to_i,
|
200
|
-
iss: app_id
|
199
|
+
iss: app_id
|
201
200
|
}
|
202
201
|
key = OpenSSL::PKey::RSA.new(private_key)
|
203
202
|
JWT.encode(payload, key, 'RS256')
|
data/lib/shipit/paginator.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
# rubocop:disable Lint/MissingCopEnableDirective, Lint/MissingSuper
|
3
4
|
require 'pathname'
|
4
5
|
require 'fileutils'
|
5
6
|
|
@@ -16,26 +17,26 @@ module Shipit
|
|
16
17
|
def fetch_commit(commit)
|
17
18
|
create_directories
|
18
19
|
if valid_git_repository?(@stack.git_path)
|
19
|
-
git('fetch', 'origin', '--
|
20
|
+
git('fetch', 'origin', *quiet_git_arg, '--tags', '--force', commit.sha, env:, chdir: @stack.git_path)
|
20
21
|
else
|
21
22
|
@stack.clear_git_cache!
|
22
|
-
git_clone(@stack.repo_git_url, @stack.git_path, branch: @stack.branch, env
|
23
|
+
git_clone(@stack.repo_git_url, @stack.git_path, branch: @stack.branch, env:, chdir: @stack.deploys_path)
|
23
24
|
end
|
24
25
|
end
|
25
26
|
|
26
27
|
def fetch
|
27
28
|
create_directories
|
28
29
|
if valid_git_repository?(@stack.git_path)
|
29
|
-
git('fetch', 'origin', '--
|
30
|
+
git('fetch', 'origin', *quiet_git_arg, '--tags', '--force', @stack.branch, env:, chdir: @stack.git_path)
|
30
31
|
else
|
31
32
|
@stack.clear_git_cache!
|
32
|
-
git_clone(@stack.repo_git_url, @stack.git_path, branch: @stack.branch, env
|
33
|
+
git_clone(@stack.repo_git_url, @stack.git_path, branch: @stack.branch, env:, chdir: @stack.deploys_path)
|
33
34
|
end
|
34
35
|
end
|
35
36
|
|
36
37
|
def fetched?(commit)
|
37
38
|
if valid_git_repository?(@stack.git_path)
|
38
|
-
git('rev-parse',
|
39
|
+
git('rev-parse', *quiet_git_arg, '--verify', "#{commit.sha}^{commit}", env:, chdir: @stack.git_path)
|
39
40
|
else
|
40
41
|
# When the stack's git cache is not valid, the commit is
|
41
42
|
# NOT fetched. To keep the interface of this method
|
@@ -43,53 +44,55 @@ module Shipit
|
|
43
44
|
# method returns false - has a non-zero exit status. We utilize
|
44
45
|
# the POSIX 'test' command with no arguments which should
|
45
46
|
# always have an exit status of 1.
|
46
|
-
Command.new('test', env
|
47
|
+
Command.new('test', env:, chdir: @stack.deploys_path)
|
47
48
|
end
|
48
49
|
end
|
49
50
|
|
50
51
|
def fetch_deployed_revision
|
51
52
|
with_temporary_working_directory(commit: @stack.commits.reachable.last) do |dir|
|
52
|
-
spec = DeploySpec::FileSystem.new(dir, @stack
|
53
|
+
spec = DeploySpec::FileSystem.new(dir, @stack)
|
53
54
|
outputs = spec.fetch_deployed_revision_steps!.map do |command_line|
|
54
|
-
Command.new(command_line, env
|
55
|
+
Command.new(command_line, env:, chdir: dir).run
|
55
56
|
end
|
56
57
|
outputs.find(&:present?).try(:strip)
|
57
58
|
end
|
58
59
|
end
|
59
60
|
|
60
61
|
def build_cacheable_deploy_spec
|
61
|
-
with_temporary_working_directory do |dir|
|
62
|
-
DeploySpec::FileSystem.new(dir, @stack
|
62
|
+
with_temporary_working_directory(recursive: false) do |dir|
|
63
|
+
DeploySpec::FileSystem.new(dir, @stack).cacheable
|
63
64
|
end
|
64
65
|
end
|
65
66
|
|
66
|
-
def with_temporary_working_directory(commit: nil)
|
67
|
+
def with_temporary_working_directory(commit: nil, recursive: true)
|
67
68
|
commit ||= @stack.last_deployed_commit.presence || @stack.commits.reachable.last
|
68
69
|
|
69
70
|
if !commit || !fetched?(commit).tap(&:run).success?
|
70
71
|
@stack.acquire_git_cache_lock do
|
71
|
-
unless fetched?(commit).tap(&:run).success?
|
72
|
-
fetch.run!
|
73
|
-
end
|
72
|
+
fetch.run! unless fetched?(commit).tap(&:run).success?
|
74
73
|
end
|
75
74
|
end
|
76
75
|
|
76
|
+
git_args = []
|
77
|
+
git_args << '--recursive' if recursive
|
77
78
|
Dir.mktmpdir do |dir|
|
78
79
|
git(
|
79
80
|
'clone', @stack.git_path, @stack.repo_name,
|
80
|
-
|
81
|
+
*git_args, '--origin', 'cache',
|
81
82
|
chdir: dir
|
82
83
|
).run!
|
83
84
|
|
84
85
|
git_dir = File.join(dir, @stack.repo_name)
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
86
|
+
if commit
|
87
|
+
git(
|
88
|
+
'-c',
|
89
|
+
'advice.detachedHead=false',
|
90
|
+
'checkout',
|
91
|
+
*quiet_git_arg,
|
92
|
+
commit.sha,
|
93
|
+
chdir: git_dir
|
94
|
+
).run!
|
95
|
+
end
|
93
96
|
yield Pathname.new(git_dir)
|
94
97
|
end
|
95
98
|
end
|
@@ -107,18 +110,23 @@ module Shipit
|
|
107
110
|
end
|
108
111
|
|
109
112
|
def git_clone(url, path, branch: 'main', **kwargs)
|
110
|
-
git('clone',
|
113
|
+
git('clone', *quiet_git_arg, *modern_git_args, '--recursive', '--branch', branch, url, path, **kwargs)
|
111
114
|
end
|
112
115
|
|
113
116
|
def modern_git_args
|
114
117
|
return [] unless git_version >= Gem::Version.new('1.7.10')
|
115
|
-
|
118
|
+
|
119
|
+
%w[--single-branch]
|
116
120
|
end
|
117
121
|
|
118
122
|
def create_directories
|
119
123
|
FileUtils.mkdir_p(@stack.deploys_path)
|
120
124
|
end
|
121
125
|
|
126
|
+
def quiet_git_arg
|
127
|
+
Shipit.git_progress_output ? [] : ['--quiet']
|
128
|
+
end
|
129
|
+
|
122
130
|
private
|
123
131
|
|
124
132
|
def github
|
data/lib/shipit/stat.rb
CHANGED
data/lib/shipit/task_commands.rb
CHANGED
@@ -1,5 +1,6 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
|
2
|
+
|
3
|
+
# rubocop:disable Lint/MissingCopEnableDirective, Lint/MissingSuper
|
3
4
|
module Shipit
|
4
5
|
class TaskCommands < Commands
|
5
6
|
delegate :fetch_commit, :fetch, :fetched?, to: :stack_commands
|
@@ -10,18 +11,18 @@ module Shipit
|
|
10
11
|
end
|
11
12
|
|
12
13
|
def deploy_spec
|
13
|
-
@deploy_spec ||= DeploySpec::FileSystem.new(@task.working_directory, @stack
|
14
|
+
@deploy_spec ||= DeploySpec::FileSystem.new(@task.working_directory, @stack)
|
14
15
|
end
|
15
16
|
|
16
17
|
def install_dependencies
|
17
18
|
deploy_spec.dependencies_steps!.map do |command_line|
|
18
|
-
Command.new(command_line, env
|
19
|
+
Command.new(command_line, env:, chdir: steps_directory)
|
19
20
|
end
|
20
21
|
end
|
21
22
|
|
22
23
|
def perform
|
23
24
|
steps.map do |command_line|
|
24
|
-
Command.new(command_line, env
|
25
|
+
Command.new(command_line, env:, chdir: steps_directory)
|
25
26
|
end
|
26
27
|
end
|
27
28
|
|
@@ -40,7 +41,7 @@ module Shipit
|
|
40
41
|
'TASK_ID' => @task.id.to_s,
|
41
42
|
'IGNORED_SAFETIES' => @task.ignored_safeties? ? '1' : '0',
|
42
43
|
'GIT_COMMITTER_NAME' => @task.user&.name || Shipit.committer_name,
|
43
|
-
'GIT_COMMITTER_EMAIL' => @task.user&.email || Shipit.committer_email
|
44
|
+
'GIT_COMMITTER_EMAIL' => @task.user&.email || Shipit.committer_email
|
44
45
|
)
|
45
46
|
.merge(deploy_spec.machine_env)
|
46
47
|
.merge(@task.env)
|
@@ -68,7 +69,7 @@ module Shipit
|
|
68
69
|
@task.working_directory,
|
69
70
|
chdir: @stack.deploys_path
|
70
71
|
),
|
71
|
-
git('remote', 'add', 'origin', @stack.repo_git_url, chdir: @task.working_directory)
|
72
|
+
git('remote', 'add', 'origin', @stack.repo_git_url, chdir: @task.working_directory)
|
72
73
|
]
|
73
74
|
end
|
74
75
|
|
data/lib/shipit/version.rb
CHANGED
data/lib/shipit.rb
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
require 'active_support/all'
|
3
4
|
require 'active_model_serializers'
|
4
5
|
require 'state_machines-activerecord'
|
@@ -60,17 +61,17 @@ module Shipit
|
|
60
61
|
extend self
|
61
62
|
|
62
63
|
GithubOrganizationUnknown = Class.new(StandardError)
|
63
|
-
TOP_LEVEL_GH_KEYS = [:app_id, :installation_id, :webhook_secret, :private_key, :oauth, :domain]
|
64
|
+
TOP_LEVEL_GH_KEYS = [:app_id, :installation_id, :webhook_secret, :private_key, :oauth, :domain].freeze
|
64
65
|
|
65
66
|
delegate :table_name_prefix, to: :secrets
|
66
67
|
|
67
68
|
attr_accessor :disable_api_authentication, :timeout_exit_codes, :deployment_checks, :respect_bare_shipit_file,
|
68
|
-
|
69
|
+
:database_serializer
|
69
70
|
attr_writer(
|
70
71
|
:internal_hook_receivers,
|
71
72
|
:preferred_org_emails,
|
72
73
|
:task_execution_strategy,
|
73
|
-
:task_logger
|
74
|
+
:task_logger
|
74
75
|
)
|
75
76
|
|
76
77
|
def task_execution_strategy
|
@@ -80,7 +81,7 @@ module Shipit
|
|
80
81
|
self.timeout_exit_codes = [].freeze
|
81
82
|
self.respect_bare_shipit_file = true
|
82
83
|
|
83
|
-
|
84
|
+
alias respect_bare_shipit_file? respect_bare_shipit_file
|
84
85
|
|
85
86
|
def authentication_disabled?
|
86
87
|
ENV['SHIPIT_DISABLE_AUTH'].present?
|
@@ -95,7 +96,7 @@ module Shipit
|
|
95
96
|
end
|
96
97
|
|
97
98
|
def redis_url
|
98
|
-
secrets.redis_url.present? ? URI(secrets.redis_url) :
|
99
|
+
secrets.redis_url.present? ? URI(secrets.redis_url) : ENV["REDIS_URL"]
|
99
100
|
end
|
100
101
|
|
101
102
|
def redis
|
@@ -104,14 +105,19 @@ module Shipit
|
|
104
105
|
logger: Rails.logger,
|
105
106
|
reconnect_attempts: 3,
|
106
107
|
reconnect_delay: 0.5,
|
107
|
-
reconnect_delay_max: 1
|
108
|
+
reconnect_delay_max: 1
|
108
109
|
)
|
109
110
|
end
|
110
111
|
|
112
|
+
def redis=(client)
|
113
|
+
@redis ||= client
|
114
|
+
end
|
115
|
+
|
111
116
|
module SafeJSON
|
112
117
|
class << self
|
113
118
|
def load(serial)
|
114
119
|
return nil if serial.nil?
|
120
|
+
|
115
121
|
# JSON.load is unsafe, we should use parse instead
|
116
122
|
JSON.parse(serial)
|
117
123
|
end
|
@@ -136,6 +142,7 @@ module Shipit
|
|
136
142
|
|
137
143
|
def dump(object)
|
138
144
|
return if object.nil?
|
145
|
+
|
139
146
|
JSON.dump(object)
|
140
147
|
end
|
141
148
|
end
|
@@ -144,7 +151,7 @@ module Shipit
|
|
144
151
|
self.database_serializer = TransitionalSerializer
|
145
152
|
|
146
153
|
def serialized_column(attribute_name, type: nil, coder: nil)
|
147
|
-
column = Paquito::SerializedColumn.new(database_serializer, type, attribute_name:
|
154
|
+
column = Paquito::SerializedColumn.new(database_serializer, type, attribute_name:)
|
148
155
|
if coder
|
149
156
|
Paquito.chain(coder, column)
|
150
157
|
else
|
@@ -167,12 +174,14 @@ module Shipit
|
|
167
174
|
|
168
175
|
def github_default_organization
|
169
176
|
return nil unless secrets&.github
|
177
|
+
|
170
178
|
org = secrets.github.keys.first
|
171
179
|
TOP_LEVEL_GH_KEYS.include?(org) ? nil : org
|
172
180
|
end
|
173
181
|
|
174
182
|
def github_organizations
|
175
183
|
return [nil] unless github_default_organization
|
184
|
+
|
176
185
|
secrets.github.keys
|
177
186
|
end
|
178
187
|
|
@@ -183,9 +192,9 @@ module Shipit
|
|
183
192
|
end
|
184
193
|
|
185
194
|
def legacy_github_api
|
186
|
-
|
187
|
-
|
188
|
-
|
195
|
+
return unless secrets&.github_api.present?
|
196
|
+
|
197
|
+
@legacy_github_api ||= github.new_client(access_token: secrets.github_api[:access_token])
|
189
198
|
end
|
190
199
|
|
191
200
|
def user
|
@@ -204,7 +213,7 @@ module Shipit
|
|
204
213
|
if secrets.user_access_tokens_key.present?
|
205
214
|
secrets.user_access_tokens_key
|
206
215
|
elsif secrets.secret_key_base
|
207
|
-
Digest::SHA256.digest("user_access_tokens_key
|
216
|
+
Digest::SHA256.digest("user_access_tokens_key#{secrets.secret_key_base}")
|
208
217
|
end
|
209
218
|
end
|
210
219
|
|
@@ -220,6 +229,10 @@ module Shipit
|
|
220
229
|
secrets.update_latest_deployed_ref
|
221
230
|
end
|
222
231
|
|
232
|
+
def git_progress_output
|
233
|
+
secrets.git_progress_output || false
|
234
|
+
end
|
235
|
+
|
223
236
|
def enforce_publish_config
|
224
237
|
secrets.enforce_publish_config.presence
|
225
238
|
end
|
@@ -240,7 +253,7 @@ module Shipit
|
|
240
253
|
@all_settings_present ||= [
|
241
254
|
secrets.github, # TODO: handle GitHub settings
|
242
255
|
redis_url,
|
243
|
-
host
|
256
|
+
host
|
244
257
|
].all?(&:present?)
|
245
258
|
end
|
246
259
|
|
@@ -254,10 +267,10 @@ module Shipit
|
|
254
267
|
|
255
268
|
def revision
|
256
269
|
@revision ||= if revision_file.exist?
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
270
|
+
revision_file.read
|
271
|
+
else
|
272
|
+
`git rev-parse HEAD`
|
273
|
+
end.strip
|
261
274
|
end
|
262
275
|
|
263
276
|
def default_inactivity_timeout
|
data/lib/tasks/cron.rake
CHANGED
@@ -1,4 +1,5 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
namespace :cron do
|
3
4
|
desc "Updates deployed revisions"
|
4
5
|
task minutely: :environment do
|
@@ -10,7 +11,7 @@ namespace :cron do
|
|
10
11
|
Shipit::ReviewStackProvisioningQueue.work
|
11
12
|
end
|
12
13
|
|
13
|
-
task hourly: %i
|
14
|
+
task hourly: %i[rollup refresh_users clear_stale_caches delete_old_deployment_directories]
|
14
15
|
|
15
16
|
desc "Rolls-up output chunks for completed deploys older than an hour"
|
16
17
|
task rollup: :environment do
|
data/lib/tasks/dev.rake
CHANGED
@@ -1,9 +1,10 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
+
|
2
3
|
namespace :dev do
|
3
4
|
desc "Appends chunks to the last deploy, or specify with DEPLOY=id"
|
4
5
|
task stream: :environment do
|
5
6
|
require 'faker'
|
6
|
-
logger = Logger.new(
|
7
|
+
logger = Logger.new($stdout)
|
7
8
|
|
8
9
|
deploy = Shipit::Deploy.find(ENV['DEPLOY']) if ENV['DEPLOY']
|
9
10
|
deploy ||= Deploy.last
|
@@ -25,7 +26,7 @@ namespace :dev do
|
|
25
26
|
|
26
27
|
logger.error(sentence)
|
27
28
|
|
28
|
-
deploy.chunks.create(text: sentence
|
29
|
+
deploy.chunks.create(text: "#{sentence}\n")
|
29
30
|
sleep 1
|
30
31
|
end
|
31
32
|
end
|