Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
940dfdfee4
commit
d7ad87b535
|
|
@ -1203,6 +1203,12 @@ SidekiqLoadBalancing/WorkerDataConsistency:
|
|||
- 'app/workers/**/*'
|
||||
- 'ee/app/workers/**/*'
|
||||
|
||||
Sidekiq/EnforceDatabaseHealthSignalDeferral:
|
||||
Enabled: true
|
||||
Include:
|
||||
- 'app/workers/**/*'
|
||||
- 'ee/app/workers/**/*'
|
||||
|
||||
Graphql/ResourceNotAvailableError:
|
||||
Exclude:
|
||||
# Definition of `raise_resource_not_available_error!`
|
||||
|
|
|
|||
|
|
@ -2469,7 +2469,6 @@ RSpec/NamedSubject:
|
|||
- 'spec/models/packages/dependency_link_spec.rb'
|
||||
- 'spec/models/packages/dependency_spec.rb'
|
||||
- 'spec/models/packages/npm/metadata_cache_spec.rb'
|
||||
- 'spec/models/packages/package_file_spec.rb'
|
||||
- 'spec/models/packages/package_spec.rb'
|
||||
- 'spec/models/packages/rpm/repository_file_spec.rb'
|
||||
- 'spec/models/plan_limits_spec.rb'
|
||||
|
|
|
|||
|
|
@ -0,0 +1,207 @@
|
|||
---
|
||||
Sidekiq/EnforceDatabaseHealthSignalDeferral:
|
||||
Details: grace period
|
||||
Exclude:
|
||||
- 'app/workers/analytics/usage_trends/count_job_trigger_worker.rb'
|
||||
- 'app/workers/analytics/usage_trends/counter_job_worker.rb'
|
||||
- 'app/workers/anti_abuse/ban_duplicate_users_worker.rb'
|
||||
- 'app/workers/anti_abuse/spam_abuse_events_worker.rb'
|
||||
- 'app/workers/anti_abuse/trust_score_cleanup_worker.rb'
|
||||
- 'app/workers/anti_abuse/trust_score_worker.rb'
|
||||
- 'app/workers/authorized_project_update/enqueue_group_members_refresh_authorized_projects_worker.rb'
|
||||
- 'app/workers/authorized_project_update/periodic_recalculate_worker.rb'
|
||||
- 'app/workers/authorized_project_update/user_refresh_from_replica_worker.rb'
|
||||
- 'app/workers/authorized_project_update/user_refresh_over_user_range_worker.rb'
|
||||
- 'app/workers/authorized_project_update/user_refresh_with_low_urgency_worker.rb'
|
||||
- 'app/workers/chat_notification_worker.rb'
|
||||
- 'app/workers/ci/cancel_redundant_pipelines_worker.rb'
|
||||
- 'app/workers/ci/catalog/resources/aggregate_last30_day_usage_worker.rb'
|
||||
- 'app/workers/ci/catalog/resources/cleanup_last_usages_worker.rb'
|
||||
- 'app/workers/ci/destroy_old_pipelines_worker.rb'
|
||||
- 'app/workers/ci/execute_build_hooks_worker.rb'
|
||||
- 'app/workers/ci/job_token/log_authorization_worker.rb'
|
||||
- 'app/workers/ci/low_urgency_cancel_redundant_pipelines_worker.rb'
|
||||
- 'app/workers/ci/merge_requests/add_todo_when_build_fails_worker.rb'
|
||||
- 'app/workers/ci/parse_secure_file_metadata_worker.rb'
|
||||
- 'app/workers/ci/pipeline_cleanup_ref_worker.rb'
|
||||
- 'app/workers/ci/pipeline_finished_worker.rb'
|
||||
- 'app/workers/ci/runners/process_runner_version_update_worker.rb'
|
||||
- 'app/workers/ci/runners/reconcile_existing_runner_versions_cron_worker.rb'
|
||||
- 'app/workers/ci/runners/stale_machines_cleanup_cron_worker.rb'
|
||||
- 'app/workers/ci/schedule_old_pipelines_removal_cron_worker.rb'
|
||||
- 'app/workers/ci/track_failed_build_worker.rb'
|
||||
- 'app/workers/cleanup_container_repository_worker.rb'
|
||||
- 'app/workers/clusters/agents/notify_git_push_worker.rb'
|
||||
- 'app/workers/clusters/migration/install_agent_worker.rb'
|
||||
- 'app/workers/concurrency_limit/resume_worker.rb'
|
||||
- 'app/workers/container_expiration_policies/cleanup_container_repository_worker.rb'
|
||||
- 'app/workers/container_registry/delete_container_repository_worker.rb'
|
||||
- 'app/workers/container_registry/record_data_repair_detail_worker.rb'
|
||||
- 'app/workers/counters/cleanup_refresh_worker.rb'
|
||||
- 'app/workers/dependency_proxy/cleanup_blob_worker.rb'
|
||||
- 'app/workers/dependency_proxy/cleanup_manifest_worker.rb'
|
||||
- 'app/workers/design_management/copy_design_collection_worker.rb'
|
||||
- 'app/workers/emails_on_push_worker.rb'
|
||||
- 'app/workers/file_hook_worker.rb'
|
||||
- 'app/workers/flush_counter_increments_worker.rb'
|
||||
- 'app/workers/gitlab/version/version_check_cron_worker.rb'
|
||||
- 'app/workers/google_cloud/fetch_google_ip_list_worker.rb'
|
||||
- 'app/workers/incident_management/close_incident_worker.rb'
|
||||
- 'app/workers/integrations/create_external_cross_reference_worker.rb'
|
||||
- 'app/workers/integrations/execute_worker.rb'
|
||||
- 'app/workers/integrations/group_mention_worker.rb'
|
||||
- 'app/workers/integrations/irker_worker.rb'
|
||||
- 'app/workers/integrations/jira_connect/remove_branch_worker.rb'
|
||||
- 'app/workers/integrations/propagate_integration_descendant_worker.rb'
|
||||
- 'app/workers/integrations/slack_event_worker.rb'
|
||||
- 'app/workers/issuables/clear_groups_issue_counter_worker.rb'
|
||||
- 'app/workers/issues/rebalancing_worker.rb'
|
||||
- 'app/workers/issues/reschedule_stuck_issue_rebalances_worker.rb'
|
||||
- 'app/workers/jira_connect/forward_event_worker.rb'
|
||||
- 'app/workers/jira_connect/jira_cloud_app_deactivation_worker.rb'
|
||||
- 'app/workers/jira_connect/retry_request_worker.rb'
|
||||
- 'app/workers/jira_connect/send_uninstalled_hook_worker.rb'
|
||||
- 'app/workers/jira_connect/sync_branch_worker.rb'
|
||||
- 'app/workers/jira_connect/sync_builds_worker.rb'
|
||||
- 'app/workers/jira_connect/sync_deployments_worker.rb'
|
||||
- 'app/workers/jira_connect/sync_feature_flags_worker.rb'
|
||||
- 'app/workers/jira_connect/sync_merge_request_worker.rb'
|
||||
- 'app/workers/jira_connect/sync_project_worker.rb'
|
||||
- 'app/workers/member_invitation_reminder_emails_worker.rb'
|
||||
- 'app/workers/members/expiring_email_notification_worker.rb'
|
||||
- 'app/workers/members/expiring_worker.rb'
|
||||
- 'app/workers/members/prune_deletions_worker.rb'
|
||||
- 'app/workers/members/schedule_prune_deletions_worker.rb'
|
||||
- 'app/workers/merge_requests/cleanup_ref_worker.rb'
|
||||
- 'app/workers/merge_requests/close_issue_worker.rb'
|
||||
- 'app/workers/merge_requests/create_approval_event_worker.rb'
|
||||
- 'app/workers/merge_requests/create_approval_note_worker.rb'
|
||||
- 'app/workers/merge_requests/execute_approval_hooks_worker.rb'
|
||||
- 'app/workers/merge_requests/resolve_todos_after_approval_worker.rb'
|
||||
- 'app/workers/metrics/patched_files_worker.rb'
|
||||
- 'app/workers/ml/experiment_tracking/associate_ml_candidate_to_package_worker.rb'
|
||||
- 'app/workers/packages/cleanup/delete_orphaned_dependencies_worker.rb'
|
||||
- 'app/workers/packages/cleanup/execute_policy_worker.rb'
|
||||
- 'app/workers/packages/cleanup_package_file_worker.rb'
|
||||
- 'app/workers/packages/mark_package_files_for_destruction_worker.rb'
|
||||
- 'app/workers/packages/npm/deprecate_package_worker.rb'
|
||||
- 'app/workers/packages/terraform_module/process_package_file_worker.rb'
|
||||
- 'app/workers/pages/deactivate_mr_deployments_worker.rb'
|
||||
- 'app/workers/pause_control/resume_worker.rb'
|
||||
- 'app/workers/pipeline_metrics_worker.rb'
|
||||
- 'app/workers/project_export_worker.rb'
|
||||
- 'app/workers/projects/after_import_worker.rb'
|
||||
- 'app/workers/projects/finalize_project_statistics_refresh_worker.rb'
|
||||
- 'app/workers/projects/import_export/after_import_merge_requests_worker.rb'
|
||||
- 'app/workers/projects/import_export/import_completion_notification_worker.rb'
|
||||
- 'app/workers/projects/import_export/parallel_project_export_worker.rb'
|
||||
- 'app/workers/projects/import_export/relation_export_worker.rb'
|
||||
- 'app/workers/projects/import_export/relation_import_worker.rb'
|
||||
- 'app/workers/projects/inactive_projects_deletion_cron_worker.rb'
|
||||
- 'app/workers/projects/record_target_platforms_worker.rb'
|
||||
- 'app/workers/propagate_integration_group_worker.rb'
|
||||
- 'app/workers/propagate_integration_inherit_descendant_worker.rb'
|
||||
- 'app/workers/propagate_integration_inherit_worker.rb'
|
||||
- 'app/workers/propagate_integration_project_worker.rb'
|
||||
- 'app/workers/propagate_integration_worker.rb'
|
||||
- 'app/workers/reactive_caching_worker.rb'
|
||||
- 'app/workers/remove_unaccepted_member_invites_worker.rb'
|
||||
- 'app/workers/terraform/states/destroy_worker.rb'
|
||||
- 'app/workers/update_container_registry_info_worker.rb'
|
||||
- 'app/workers/virtual_registries/packages/cache/destroy_orphan_entries_worker.rb'
|
||||
- 'app/workers/web_hook_worker.rb'
|
||||
- 'app/workers/web_hooks/log_destroy_worker.rb'
|
||||
- 'app/workers/web_hooks/log_execution_worker.rb'
|
||||
- 'app/workers/work_items/user_preferences/destroy_worker.rb'
|
||||
- 'app/workers/x509_issuer_crl_check_worker.rb'
|
||||
- 'ee/app/workers/ai/active_context/bulk_process_worker.rb'
|
||||
- 'ee/app/workers/ai/active_context/migration_worker.rb'
|
||||
- 'ee/app/workers/ai/repository_xray/scan_dependencies_worker.rb'
|
||||
- 'ee/app/workers/analytics/code_suggestions_events_backfill_worker.rb'
|
||||
- 'ee/app/workers/analytics/duo_chat_events_backfill_worker.rb'
|
||||
- 'ee/app/workers/anti_abuse/new_abuse_report_worker.rb'
|
||||
- 'ee/app/workers/app_config/cascade_duo_features_enabled_worker.rb'
|
||||
- 'ee/app/workers/ci/minutes/update_project_and_namespace_usage_worker.rb'
|
||||
- 'ee/app/workers/ci/runners/stale_group_runners_prune_cron_worker.rb'
|
||||
- 'ee/app/workers/ci/update_approval_rules_for_related_mrs_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/chain_of_custody_report_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/compliance_framework/project_compliance_statuses_removal_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/compliance_framework/project_requirement_statuses_export_mailer_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/framework_export_mailer_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/merge_requests/compliance_violations_consistency_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/pipl/block_pipl_users_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/pipl/delete_pipl_users_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/pipl/send_recurring_notifications_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/pipl/update_user_country_access_logs_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/pipl/user_paid_status_check_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/project_compliance_evaluator_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/project_framework_export_mailer_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/base_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/gitlab/at_least_two_approvals_group_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/gitlab/at_least_two_approvals_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/gitlab/dast_group_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/gitlab/dast_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/gitlab/prevent_approval_by_author_group_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/gitlab/prevent_approval_by_author_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/gitlab/prevent_approval_by_committer_group_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/gitlab/prevent_approval_by_committer_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/gitlab/sast_group_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/gitlab/sast_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/group_base_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/refresh_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/soc2/at_least_one_non_author_approval_group_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards/soc2/at_least_one_non_author_approval_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/standards_adherence_export_mailer_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/timeout_pending_external_controls_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/update_default_framework_worker.rb'
|
||||
- 'ee/app/workers/compliance_management/violation_export_mailer_worker.rb'
|
||||
- 'ee/app/workers/elastic/migration_worker.rb'
|
||||
- 'ee/app/workers/elastic_index_bulk_cron_worker.rb'
|
||||
- 'ee/app/workers/elastic_index_initial_bulk_cron_worker.rb'
|
||||
- 'ee/app/workers/gitlab_subscriptions/add_on_purchases/bulk_refresh_user_assignments_worker.rb'
|
||||
- 'ee/app/workers/gitlab_subscriptions/add_on_purchases/cleanup_user_add_on_assignment_worker.rb'
|
||||
- 'ee/app/workers/gitlab_subscriptions/add_on_purchases/refresh_user_assignments_worker.rb'
|
||||
- 'ee/app/workers/gitlab_subscriptions/add_on_purchases/schedule_bulk_refresh_user_assignments_worker.rb'
|
||||
- 'ee/app/workers/gitlab_subscriptions/member_management/apply_pending_member_approvals_worker.rb'
|
||||
- 'ee/app/workers/gitlab_subscriptions/members/added_worker.rb'
|
||||
- 'ee/app/workers/gitlab_subscriptions/members/destroyed_worker.rb'
|
||||
- 'ee/app/workers/gitlab_subscriptions/members/record_last_activity_worker.rb'
|
||||
- 'ee/app/workers/gitlab_subscriptions/refresh_seats_worker.rb'
|
||||
- 'ee/app/workers/gitlab_subscriptions/schedule_refresh_seats_worker.rb'
|
||||
- 'ee/app/workers/llm/completion_worker.rb'
|
||||
- 'ee/app/workers/llm/namespace_access_cache_reset_worker.rb'
|
||||
- 'ee/app/workers/members/delete_pending_members_worker.rb'
|
||||
- 'ee/app/workers/merge_requests/approval_metrics_event_worker.rb'
|
||||
- 'ee/app/workers/merge_requests/capture_suggested_reviewers_accepted_worker.rb'
|
||||
- 'ee/app/workers/merge_requests/create_approvals_reset_note_worker.rb'
|
||||
- 'ee/app/workers/merge_requests/duo_code_review_chat_worker.rb'
|
||||
- 'ee/app/workers/merge_requests/fetch_suggested_reviewers_worker.rb'
|
||||
- 'ee/app/workers/merge_requests/notify_approvers_worker.rb'
|
||||
- 'ee/app/workers/merge_requests/process_merge_audit_event_worker.rb'
|
||||
- 'ee/app/workers/merge_requests/stream_approval_audit_event_worker.rb'
|
||||
- 'ee/app/workers/namespaces/cascade_duo_features_enabled_worker.rb'
|
||||
- 'ee/app/workers/namespaces/remove_dormant_members_worker.rb'
|
||||
- 'ee/app/workers/namespaces/schedule_dormant_member_removal_worker.rb'
|
||||
- 'ee/app/workers/namespaces/storage_usage_export_worker.rb'
|
||||
- 'ee/app/workers/onboarding/progress_tracking_worker.rb'
|
||||
- 'ee/app/workers/package_metadata/advisories_sync_worker.rb'
|
||||
- 'ee/app/workers/package_metadata/cve_enrichment_sync_worker.rb'
|
||||
- 'ee/app/workers/package_metadata/global_advisory_scan_worker.rb'
|
||||
- 'ee/app/workers/package_metadata/licenses_sync_worker.rb'
|
||||
- 'ee/app/workers/projects/deregister_suggested_reviewers_project_worker.rb'
|
||||
- 'ee/app/workers/projects/disable_legacy_open_source_license_for_inactive_projects_worker.rb'
|
||||
- 'ee/app/workers/projects/register_suggested_reviewers_project_worker.rb'
|
||||
- 'ee/app/workers/sbom/create_occurrences_vulnerabilities_worker.rb'
|
||||
- 'ee/app/workers/sbom/process_vulnerabilities_worker.rb'
|
||||
- 'ee/app/workers/search/elastic_default_branch_changed_worker.rb'
|
||||
- 'ee/app/workers/search/elastic_index_embedding_bulk_cron_worker.rb'
|
||||
- 'ee/app/workers/search/zoekt/default_branch_changed_worker.rb'
|
||||
- 'ee/app/workers/security/policies/report_security_policies_metrics_worker.rb'
|
||||
- 'ee/app/workers/security/scan_result_policies/sync_any_merge_request_approval_rules_worker.rb'
|
||||
- 'ee/app/workers/security/scan_result_policies/sync_merge_request_approvals_worker.rb'
|
||||
- 'ee/app/workers/security/scans/purge_by_job_id_worker.rb'
|
||||
- 'ee/app/workers/system_access/group_saml_microsoft_group_sync_worker.rb'
|
||||
- 'ee/app/workers/system_access/saml_microsoft_group_sync_worker.rb'
|
||||
- 'ee/app/workers/vulnerabilities/orphaned_remediations_cleanup_worker.rb'
|
||||
- 'ee/app/workers/vulnerabilities/remove_all_vulnerabilities_worker.rb'
|
||||
- 'ee/app/workers/work_items/validate_epic_work_item_sync_worker.rb'
|
||||
2
Gemfile
2
Gemfile
|
|
@ -653,7 +653,7 @@ gem 'spamcheck', '~> 1.3.0', feature_category: :insider_threat
|
|||
gem 'gitaly', '~> 17.8.0', feature_category: :gitaly
|
||||
|
||||
# KAS GRPC protocol definitions
|
||||
gem 'gitlab-kas-grpc', '~> 17.9.0.pre.rc2', feature_category: :deployment_management
|
||||
gem 'gitlab-kas-grpc', '~> 17.10.4', feature_category: :deployment_management
|
||||
|
||||
# Lock the version before issues below are resolved:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/issues/473169#note_2028352939
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@
|
|||
{"name":"fog-google","version":"1.24.1","platform":"ruby","checksum":"dcd64ec5d12ed53f269afd7a88738b453e5150ef72b451900bb7abf3678358e0"},
|
||||
{"name":"fog-json","version":"1.2.0","platform":"ruby","checksum":"dd4f5ab362dbc72b687240bba9d2dd841d5dfe888a285797533f85c03ea548fe"},
|
||||
{"name":"fog-local","version":"0.8.0","platform":"ruby","checksum":"263b2d09e54c69d1b87ad7f235a1a1e53c8a674edcedf7512c1715765ad7ef79"},
|
||||
{"name":"fog-xml","version":"0.1.3","platform":"ruby","checksum":"5604c42649ebb0d8a31bd973aa000c2dd0127f1c1c4c174b69266a2e78e37410"},
|
||||
{"name":"fog-xml","version":"0.1.5","platform":"ruby","checksum":"52b9fea10701461dd3eaf9d9839702169b418dbbf50426786b9b74fade373bd6"},
|
||||
{"name":"formatador","version":"0.2.5","platform":"ruby","checksum":"80821869ddacb79e72870ff4bb1531efacd278c04f2df26bc6b4529ee13582bd"},
|
||||
{"name":"forwardable","version":"1.3.3","platform":"ruby","checksum":"f17df4bd6afa6f46a003217023fe5716ef88ce261f5c4cf0edbdeed6470cafac"},
|
||||
{"name":"fugit","version":"1.11.1","platform":"ruby","checksum":"e89485e7be22226d8e9c6da411664d0660284b4b1c08cacb540f505907869868"},
|
||||
|
|
@ -230,7 +230,7 @@
|
|||
{"name":"gitlab-glfm-markdown","version":"0.0.29","platform":"x86_64-darwin","checksum":"1e322c51ec338a6958010a062005285f335318c2a4b2dee71c2848468498c08d"},
|
||||
{"name":"gitlab-glfm-markdown","version":"0.0.29","platform":"x86_64-linux-gnu","checksum":"e8086a21a4e3187d76fa89eecac88aa57a89627de2a3b789d70d4844efe881db"},
|
||||
{"name":"gitlab-glfm-markdown","version":"0.0.29","platform":"x86_64-linux-musl","checksum":"f934efe5efc53d36ea00a030cc0d530bad81901ef782b7774dd0bfaef73f1c37"},
|
||||
{"name":"gitlab-kas-grpc","version":"17.9.1","platform":"ruby","checksum":"fd480c1669c741ceab8d5f86b7e5e32b71f4f25af8b523725382dae425aaa958"},
|
||||
{"name":"gitlab-kas-grpc","version":"17.10.4","platform":"ruby","checksum":"eef69a52b39ea69f7c79ba1785b37f985187a8609744d2b17336b738402858b1"},
|
||||
{"name":"gitlab-labkit","version":"0.37.0","platform":"ruby","checksum":"d2dd0a60db2149a9a8eebf2975dc23f54ac3ceb01bdba732eb1b26b86dfffa70"},
|
||||
{"name":"gitlab-license","version":"2.6.0","platform":"ruby","checksum":"2c1f8ae73835640ec77bf758c1d0c9730635043c01cf77902f7976e826d7d016"},
|
||||
{"name":"gitlab-mail_room","version":"0.0.27","platform":"ruby","checksum":"05c07db892094cf5747ea00afb0a95c5a5406e05f34ae779f4388f2ddf962316"},
|
||||
|
|
@ -282,7 +282,7 @@
|
|||
{"name":"google-protobuf","version":"3.25.6","platform":"x86_64-darwin","checksum":"0ddac5fcfa104531891fc15d26706e168397e0cc4ab4f9f8e1869035ab4768da"},
|
||||
{"name":"google-protobuf","version":"3.25.6","platform":"x86_64-linux","checksum":"5334ae993505fb1e409563f95afd720a868d0f2182865d05280943f9be6c22df"},
|
||||
{"name":"googleapis-common-protos","version":"1.4.0","platform":"ruby","checksum":"da2380fb5ab1563580816c74e8d684ac17512c3654c829a3ee84f6d6139de382"},
|
||||
{"name":"googleapis-common-protos-types","version":"1.18.0","platform":"ruby","checksum":"280d19dcf431f86b9ff7ed8b23994915c5f4f7a0282ad3e870a2d3595976559f"},
|
||||
{"name":"googleapis-common-protos-types","version":"1.19.0","platform":"ruby","checksum":"aecb76ca5326f8bcc47ab083259bbc4971d07e87f56808af7e210669d9765694"},
|
||||
{"name":"googleauth","version":"1.8.1","platform":"ruby","checksum":"814adadaaa1221dce72a67131e3ecbd6d23491a161ec84fb15fd353b87d8c9e7"},
|
||||
{"name":"gpgme","version":"2.0.24","platform":"ruby","checksum":"53eccd7042abb4fd5c78f30bc9ed075b1325e6450eab207f2f6a1e7e28ae3b64"},
|
||||
{"name":"grape","version":"2.0.0","platform":"ruby","checksum":"3aeff94c17e84ccead4ff98833df691e7da0c108878cc128ca31f80c1047494a"},
|
||||
|
|
|
|||
|
|
@ -700,7 +700,7 @@ GEM
|
|||
multi_json (~> 1.10)
|
||||
fog-local (0.8.0)
|
||||
fog-core (>= 1.27, < 3.0)
|
||||
fog-xml (0.1.3)
|
||||
fog-xml (0.1.5)
|
||||
fog-core
|
||||
nokogiri (>= 1.5.11, < 2.0.0)
|
||||
formatador (0.2.5)
|
||||
|
|
@ -762,7 +762,7 @@ GEM
|
|||
nokogiri (~> 1, >= 1.10.8)
|
||||
gitlab-glfm-markdown (0.0.29)
|
||||
rb_sys (~> 0.9.109)
|
||||
gitlab-kas-grpc (17.9.1)
|
||||
gitlab-kas-grpc (17.10.4)
|
||||
grpc (~> 1.0)
|
||||
gitlab-labkit (0.37.0)
|
||||
actionpack (>= 5.0.0, < 8.1.0)
|
||||
|
|
@ -913,7 +913,7 @@ GEM
|
|||
google-protobuf (~> 3.14)
|
||||
googleapis-common-protos-types (~> 1.2)
|
||||
grpc (~> 1.27)
|
||||
googleapis-common-protos-types (1.18.0)
|
||||
googleapis-common-protos-types (1.19.0)
|
||||
google-protobuf (>= 3.18, < 5.a)
|
||||
googleauth (1.8.1)
|
||||
faraday (>= 0.17.3, < 3.a)
|
||||
|
|
@ -2135,7 +2135,7 @@ DEPENDENCIES
|
|||
gitlab-glfm-markdown (~> 0.0.29)
|
||||
gitlab-housekeeper!
|
||||
gitlab-http!
|
||||
gitlab-kas-grpc (~> 17.9.0.pre.rc2)
|
||||
gitlab-kas-grpc (~> 17.10.4)
|
||||
gitlab-labkit (~> 0.37.0)
|
||||
gitlab-license (~> 2.6)
|
||||
gitlab-mail_room (~> 0.0.24)
|
||||
|
|
|
|||
|
|
@ -204,7 +204,7 @@
|
|||
{"name":"fog-google","version":"1.24.1","platform":"ruby","checksum":"dcd64ec5d12ed53f269afd7a88738b453e5150ef72b451900bb7abf3678358e0"},
|
||||
{"name":"fog-json","version":"1.2.0","platform":"ruby","checksum":"dd4f5ab362dbc72b687240bba9d2dd841d5dfe888a285797533f85c03ea548fe"},
|
||||
{"name":"fog-local","version":"0.8.0","platform":"ruby","checksum":"263b2d09e54c69d1b87ad7f235a1a1e53c8a674edcedf7512c1715765ad7ef79"},
|
||||
{"name":"fog-xml","version":"0.1.3","platform":"ruby","checksum":"5604c42649ebb0d8a31bd973aa000c2dd0127f1c1c4c174b69266a2e78e37410"},
|
||||
{"name":"fog-xml","version":"0.1.5","platform":"ruby","checksum":"52b9fea10701461dd3eaf9d9839702169b418dbbf50426786b9b74fade373bd6"},
|
||||
{"name":"formatador","version":"0.2.5","platform":"ruby","checksum":"80821869ddacb79e72870ff4bb1531efacd278c04f2df26bc6b4529ee13582bd"},
|
||||
{"name":"forwardable","version":"1.3.3","platform":"ruby","checksum":"f17df4bd6afa6f46a003217023fe5716ef88ce261f5c4cf0edbdeed6470cafac"},
|
||||
{"name":"fugit","version":"1.11.1","platform":"ruby","checksum":"e89485e7be22226d8e9c6da411664d0660284b4b1c08cacb540f505907869868"},
|
||||
|
|
@ -230,7 +230,7 @@
|
|||
{"name":"gitlab-glfm-markdown","version":"0.0.29","platform":"x86_64-darwin","checksum":"1e322c51ec338a6958010a062005285f335318c2a4b2dee71c2848468498c08d"},
|
||||
{"name":"gitlab-glfm-markdown","version":"0.0.29","platform":"x86_64-linux-gnu","checksum":"e8086a21a4e3187d76fa89eecac88aa57a89627de2a3b789d70d4844efe881db"},
|
||||
{"name":"gitlab-glfm-markdown","version":"0.0.29","platform":"x86_64-linux-musl","checksum":"f934efe5efc53d36ea00a030cc0d530bad81901ef782b7774dd0bfaef73f1c37"},
|
||||
{"name":"gitlab-kas-grpc","version":"17.9.1","platform":"ruby","checksum":"fd480c1669c741ceab8d5f86b7e5e32b71f4f25af8b523725382dae425aaa958"},
|
||||
{"name":"gitlab-kas-grpc","version":"17.10.4","platform":"ruby","checksum":"eef69a52b39ea69f7c79ba1785b37f985187a8609744d2b17336b738402858b1"},
|
||||
{"name":"gitlab-labkit","version":"0.37.0","platform":"ruby","checksum":"d2dd0a60db2149a9a8eebf2975dc23f54ac3ceb01bdba732eb1b26b86dfffa70"},
|
||||
{"name":"gitlab-license","version":"2.6.0","platform":"ruby","checksum":"2c1f8ae73835640ec77bf758c1d0c9730635043c01cf77902f7976e826d7d016"},
|
||||
{"name":"gitlab-mail_room","version":"0.0.27","platform":"ruby","checksum":"05c07db892094cf5747ea00afb0a95c5a5406e05f34ae779f4388f2ddf962316"},
|
||||
|
|
@ -282,7 +282,7 @@
|
|||
{"name":"google-protobuf","version":"3.25.6","platform":"x86_64-darwin","checksum":"0ddac5fcfa104531891fc15d26706e168397e0cc4ab4f9f8e1869035ab4768da"},
|
||||
{"name":"google-protobuf","version":"3.25.6","platform":"x86_64-linux","checksum":"5334ae993505fb1e409563f95afd720a868d0f2182865d05280943f9be6c22df"},
|
||||
{"name":"googleapis-common-protos","version":"1.4.0","platform":"ruby","checksum":"da2380fb5ab1563580816c74e8d684ac17512c3654c829a3ee84f6d6139de382"},
|
||||
{"name":"googleapis-common-protos-types","version":"1.18.0","platform":"ruby","checksum":"280d19dcf431f86b9ff7ed8b23994915c5f4f7a0282ad3e870a2d3595976559f"},
|
||||
{"name":"googleapis-common-protos-types","version":"1.19.0","platform":"ruby","checksum":"aecb76ca5326f8bcc47ab083259bbc4971d07e87f56808af7e210669d9765694"},
|
||||
{"name":"googleauth","version":"1.8.1","platform":"ruby","checksum":"814adadaaa1221dce72a67131e3ecbd6d23491a161ec84fb15fd353b87d8c9e7"},
|
||||
{"name":"gpgme","version":"2.0.24","platform":"ruby","checksum":"53eccd7042abb4fd5c78f30bc9ed075b1325e6450eab207f2f6a1e7e28ae3b64"},
|
||||
{"name":"grape","version":"2.0.0","platform":"ruby","checksum":"3aeff94c17e84ccead4ff98833df691e7da0c108878cc128ca31f80c1047494a"},
|
||||
|
|
|
|||
|
|
@ -712,7 +712,7 @@ GEM
|
|||
multi_json (~> 1.10)
|
||||
fog-local (0.8.0)
|
||||
fog-core (>= 1.27, < 3.0)
|
||||
fog-xml (0.1.3)
|
||||
fog-xml (0.1.5)
|
||||
fog-core
|
||||
nokogiri (>= 1.5.11, < 2.0.0)
|
||||
formatador (0.2.5)
|
||||
|
|
@ -774,7 +774,7 @@ GEM
|
|||
nokogiri (~> 1, >= 1.10.8)
|
||||
gitlab-glfm-markdown (0.0.29)
|
||||
rb_sys (~> 0.9.109)
|
||||
gitlab-kas-grpc (17.9.1)
|
||||
gitlab-kas-grpc (17.10.4)
|
||||
grpc (~> 1.0)
|
||||
gitlab-labkit (0.37.0)
|
||||
actionpack (>= 5.0.0, < 8.1.0)
|
||||
|
|
@ -925,7 +925,7 @@ GEM
|
|||
google-protobuf (~> 3.14)
|
||||
googleapis-common-protos-types (~> 1.2)
|
||||
grpc (~> 1.27)
|
||||
googleapis-common-protos-types (1.18.0)
|
||||
googleapis-common-protos-types (1.19.0)
|
||||
google-protobuf (>= 3.18, < 5.a)
|
||||
googleauth (1.8.1)
|
||||
faraday (>= 0.17.3, < 3.a)
|
||||
|
|
@ -2169,7 +2169,7 @@ DEPENDENCIES
|
|||
gitlab-glfm-markdown (~> 0.0.29)
|
||||
gitlab-housekeeper!
|
||||
gitlab-http!
|
||||
gitlab-kas-grpc (~> 17.9.0.pre.rc2)
|
||||
gitlab-kas-grpc (~> 17.10.4)
|
||||
gitlab-labkit (~> 0.37.0)
|
||||
gitlab-license (~> 2.6)
|
||||
gitlab-mail_room (~> 0.0.24)
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@ module Packages
|
|||
def package_files
|
||||
files = by_conan_file_type(super)
|
||||
files = by_recipe_revision(files)
|
||||
files = by_package_revision(files)
|
||||
by_conan_package_reference(files)
|
||||
end
|
||||
|
||||
|
|
@ -32,6 +33,16 @@ module Packages
|
|||
files.with_conan_recipe_revision(params[:recipe_revision])
|
||||
end
|
||||
end
|
||||
|
||||
def by_package_revision(files)
|
||||
return files unless params[:package_revision]
|
||||
|
||||
if params[:package_revision] == Packages::Conan::FileMetadatum::DEFAULT_REVISION
|
||||
files.without_conan_package_revision.with_conan_file_type(:package_file)
|
||||
else
|
||||
files.with_conan_package_revision(params[:package_revision])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,17 +13,22 @@ module Clusters
|
|||
validates :template_name, length: { maximum: 1024 }
|
||||
validates :tracked_objects, json_schema: { filename: 'clusters_agents_managed_resource_tracked_objects' }
|
||||
|
||||
scope :order_id_desc, -> { order(id: :desc) }
|
||||
|
||||
enum :status, {
|
||||
processing: 0,
|
||||
completed: 1,
|
||||
failed: 2
|
||||
failed: 2,
|
||||
deleting: 3,
|
||||
deleted: 4,
|
||||
delete_failed: 5
|
||||
}
|
||||
|
||||
enum :deletion_strategy, {
|
||||
never: 0,
|
||||
on_stop: 1,
|
||||
on_delete: 2
|
||||
}
|
||||
}, prefix: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -30,6 +30,7 @@ class Environment < ApplicationRecord
|
|||
has_many :successful_deployments, -> { success }, class_name: 'Deployment'
|
||||
has_many :active_deployments, -> { active }, class_name: 'Deployment'
|
||||
has_many :alert_management_alerts, class_name: 'AlertManagement::Alert', inverse_of: :environment
|
||||
has_many :managed_resources, class_name: 'Clusters::Agents::ManagedResource', inverse_of: :environment
|
||||
|
||||
# NOTE: If you preload multiple last deployments of environments, use Preloaders::Environments::DeploymentPreloader.
|
||||
has_one :last_deployment, -> { success.ordered }, class_name: 'Deployment', inverse_of: :environment
|
||||
|
|
|
|||
|
|
@ -113,6 +113,16 @@ class Packages::PackageFile < ApplicationRecord
|
|||
.where(packages_conan_file_metadata: { recipe_revision_id: nil })
|
||||
end
|
||||
|
||||
scope :with_conan_package_revision, ->(package_revision) do
|
||||
joins(conan_file_metadatum: :package_revision)
|
||||
.where(packages_conan_package_revisions: { revision: package_revision })
|
||||
end
|
||||
|
||||
scope :without_conan_package_revision, -> do
|
||||
joins(:conan_file_metadatum)
|
||||
.where(packages_conan_file_metadata: { package_revision_id: nil })
|
||||
end
|
||||
|
||||
def self.most_recent!
|
||||
recent.first!
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,65 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Clusters
|
||||
module Agents
|
||||
module ManagedResources
|
||||
class DeleteService
|
||||
POLLING_SCHEDULE = [
|
||||
10.seconds,
|
||||
30.seconds,
|
||||
5.minutes,
|
||||
30.minutes,
|
||||
1.hour
|
||||
].freeze
|
||||
|
||||
def initialize(managed_resource, attempt_count: nil)
|
||||
@managed_resource = managed_resource
|
||||
@attempt_count = attempt_count || 0
|
||||
end
|
||||
|
||||
def execute
|
||||
return unless managed_resource.deleting?
|
||||
|
||||
response = kas_client.delete_environment(managed_resource:)
|
||||
|
||||
if response.errors.any?
|
||||
requeue!
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
managed_resource.update!(tracked_objects: response.in_progress.map(&:to_h))
|
||||
|
||||
if managed_resource.tracked_objects.any?
|
||||
requeue!
|
||||
else
|
||||
update_status!(:deleted)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :managed_resource, :attempt_count
|
||||
|
||||
def requeue!
|
||||
if attempt_count >= POLLING_SCHEDULE.length
|
||||
update_status!(:delete_failed)
|
||||
else
|
||||
next_attempt_in = POLLING_SCHEDULE[attempt_count]
|
||||
|
||||
Clusters::Agents::ManagedResources::DeleteWorker.perform_in(next_attempt_in, managed_resource.id,
|
||||
attempt_count + 1)
|
||||
end
|
||||
end
|
||||
|
||||
def update_status!(status)
|
||||
managed_resource.update!(status: status)
|
||||
end
|
||||
|
||||
def kas_client
|
||||
@kas_client ||= Gitlab::Kas::Client.new
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Environments
|
||||
class DeleteManagedResourcesService
|
||||
include Gitlab::Utils::StrongMemoize
|
||||
|
||||
def initialize(environment)
|
||||
@environment = environment
|
||||
end
|
||||
|
||||
def execute
|
||||
return unless can_delete_resources?
|
||||
|
||||
managed_resource.update!(status: :deleting)
|
||||
|
||||
Clusters::Agents::ManagedResources::DeleteWorker.perform_async(managed_resource.id)
|
||||
|
||||
ServiceResponse.success
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :environment
|
||||
|
||||
def can_delete_resources?
|
||||
environment.stopped? &&
|
||||
managed_resource.present? &&
|
||||
managed_resource.cluster_agent.resource_management_enabled? &&
|
||||
managed_resource.deletion_strategy_on_stop?
|
||||
end
|
||||
|
||||
def managed_resource
|
||||
environment.managed_resources.completed.order_id_desc.first
|
||||
end
|
||||
strong_memoize_attr :managed_resource
|
||||
end
|
||||
end
|
||||
|
|
@ -29,6 +29,8 @@ module Environments
|
|||
end
|
||||
|
||||
if environment.stopped? || environment.stopping?
|
||||
delete_managed_resources(environment)
|
||||
|
||||
ServiceResponse.success(payload: { environment: environment, actions: actions })
|
||||
else
|
||||
ServiceResponse.error(
|
||||
|
|
@ -74,5 +76,9 @@ module Environments
|
|||
.new(project, current_user, ref: @ref, recently_updated: true)
|
||||
.execute
|
||||
end
|
||||
|
||||
def delete_managed_resources(environment)
|
||||
Environments::DeleteManagedResourcesService.new(environment).execute
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
- project_link = link_to(_("%{project_name}") % { project_name: @project.name }, @project.http_url_to_repo)
|
||||
- projects_api_link = link_to(_("Projects API"), help_page_url('api/projects.md'))
|
||||
- events_api_link = link_to(_("Events API"), help_page_url('api/events.md', anchor: 'list-a-projects-visible-events'))
|
||||
- events_api_link = link_to(_("Events API"), help_page_url('api/events.md', anchor: 'list-all-visible-events-for-a-project'))
|
||||
|
||||
%p
|
||||
= _('Hi %{username},') % { username: sanitize_name(@user.name) }
|
||||
|
|
|
|||
|
|
@ -12,6 +12,6 @@
|
|||
|
||||
<%= _("- Go to the Activity page for %{project_name}.") % { project_name: @project.name } %>
|
||||
<%= _("- View the last_activity_at attribute for %{project_name} using the Project API %{projects_api_link}.") % { project_name: @project.name, projects_api_link: help_page_url('api/projects.md') } %>
|
||||
<%= _("- List the visible events for %{project_name} using the Events API %{events_api_link}.") % { project_name: @project.name, events_api_link: help_page_url('api/events.md', anchor: 'list-a-projects-visible-events') } %>
|
||||
<%= _("- List the visible events for %{project_name} using the Events API %{events_api_link}.") % { project_name: @project.name, events_api_link: help_page_url('api/events.md', anchor: 'list-all-visible-events-for-a-project') } %>
|
||||
|
||||
<%= _("This email supersedes any previous emails about scheduled deletion you may have received for %{project_name}.") % { project_name: @project.name } %>
|
||||
|
|
|
|||
|
|
@ -173,6 +173,16 @@
|
|||
:idempotent: true
|
||||
:tags: []
|
||||
:queue_namespace: :cluster_agent
|
||||
- :name: cluster_agent:clusters_agents_managed_resources_delete
|
||||
:worker_name: Clusters::Agents::ManagedResources::DeleteWorker
|
||||
:feature_category: :deployment_management
|
||||
:has_external_dependencies: false
|
||||
:urgency: :low
|
||||
:resource_boundary: :unknown
|
||||
:weight: 1
|
||||
:idempotent: true
|
||||
:tags: []
|
||||
:queue_namespace: :cluster_agent
|
||||
- :name: cluster_agent:clusters_agents_notify_git_push
|
||||
:worker_name: Clusters::Agents::NotifyGitPushWorker
|
||||
:feature_category: :deployment_management
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Clusters
|
||||
module Agents
|
||||
module ManagedResources
|
||||
class DeleteWorker
|
||||
include ApplicationWorker
|
||||
include ClusterAgentQueue
|
||||
|
||||
deduplicate :until_executed, including_scheduled: true
|
||||
idempotent!
|
||||
|
||||
urgency :low
|
||||
data_consistency :delayed
|
||||
|
||||
def perform(managed_resource_id, attempt = nil)
|
||||
managed_resource = Clusters::Agents::ManagedResource.find_by_id(managed_resource_id)
|
||||
return unless managed_resource.present?
|
||||
|
||||
Clusters::Agents::ManagedResources::DeleteService.new(managed_resource, attempt_count: attempt).execute
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -279,6 +279,9 @@ dast_site_profiles_builds:
|
|||
- table: p_ci_builds
|
||||
column: ci_build_id
|
||||
on_delete: async_delete
|
||||
- table: projects
|
||||
column: project_id
|
||||
on_delete: async_delete
|
||||
dast_site_tokens:
|
||||
- table: projects
|
||||
column: project_id
|
||||
|
|
|
|||
|
|
@ -8,14 +8,6 @@ description: Join table between DAST Site Profiles and CI Builds
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63362
|
||||
milestone: '14.1'
|
||||
gitlab_schema: gitlab_sec
|
||||
desired_sharding_key:
|
||||
project_id:
|
||||
references: projects
|
||||
backfill_via:
|
||||
parent:
|
||||
foreign_key: dast_site_profile_id
|
||||
table: dast_site_profiles
|
||||
sharding_key: project_id
|
||||
belongs_to: dast_site_profile
|
||||
desired_sharding_key_migration_job_name: BackfillDastSiteProfilesBuildsProjectId
|
||||
sharding_key:
|
||||
project_id: projects
|
||||
table_size: small
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddDastSiteProfilesBuildsProjectIdNotNull < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.11'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_not_null_constraint :dast_site_profiles_builds, :project_id
|
||||
end
|
||||
|
||||
def down
|
||||
remove_not_null_constraint :dast_site_profiles_builds, :project_id
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
ec3e3399c4c66133b4323b6432f9fc21061625ce883e0ef6c54e0f20d605c097
|
||||
|
|
@ -13421,7 +13421,8 @@ CREATE TABLE dast_site_profiles (
|
|||
CREATE TABLE dast_site_profiles_builds (
|
||||
dast_site_profile_id bigint NOT NULL,
|
||||
ci_build_id bigint NOT NULL,
|
||||
project_id bigint
|
||||
project_id bigint,
|
||||
CONSTRAINT check_581c9bb699 CHECK ((project_id IS NOT NULL))
|
||||
);
|
||||
|
||||
COMMENT ON TABLE dast_site_profiles_builds IS '{"owner":"group::dynamic analysis","description":"Join table between DAST Site Profiles and CI Builds"}';
|
||||
|
|
|
|||
|
|
@ -85,5 +85,5 @@ You can view a project's activities and determine when the project was last acti
|
|||
- Go to the [activity page](../user/project/working_with_projects.md#view-project-activity) for the project and view
|
||||
the date of the latest event.
|
||||
- View the `last_activity_at` attribute for the project using the [Projects API](../api/projects.md).
|
||||
- List the visible events for the project using the [Events API](../api/events.md#list-a-projects-visible-events).
|
||||
- List the visible events for the project using the [Events API](../api/events.md#list-all-visible-events-for-a-project).
|
||||
View the `created_at` attribute of the latest event.
|
||||
|
|
|
|||
|
|
@ -257,7 +257,7 @@ Example response:
|
|||
]
|
||||
```
|
||||
|
||||
## List a project's visible events
|
||||
## List all visible events for a project
|
||||
|
||||
Lists all visible events for a specified project.
|
||||
|
||||
|
|
|
|||
|
|
@ -15278,7 +15278,87 @@ paths:
|
|||
- conan_packages
|
||||
operationId: getApiV4ProjectsIdPackagesConanV2ConansPackageNamePackageVersionPackageUsernamePackageChannelRevisionsRecipeRevisionPackagesConanPackageReferenceLatest
|
||||
? "/api/v4/projects/{id}/packages/conan/v2/conans/{package_name}/{package_version}/{package_username}/{package_channel}/revisions/{recipe_revision}/packages/{conan_package_reference}/revisions/{package_revision}/files/{file_name}"
|
||||
: put:
|
||||
: get:
|
||||
summary: Download package files
|
||||
description: This feature was introduced in GitLab 17.11
|
||||
produces:
|
||||
- application/json
|
||||
parameters:
|
||||
- in: path
|
||||
name: id
|
||||
description: The ID or URL-encoded path of the project
|
||||
type: string
|
||||
required: true
|
||||
- in: path
|
||||
name: package_name
|
||||
description: Package name
|
||||
type: string
|
||||
required: true
|
||||
example: my-package
|
||||
- in: path
|
||||
name: package_version
|
||||
description: Package version
|
||||
type: string
|
||||
required: true
|
||||
example: '1.0'
|
||||
- in: path
|
||||
name: package_username
|
||||
description: Package username
|
||||
type: string
|
||||
required: true
|
||||
example: my-group+my-project
|
||||
- in: path
|
||||
name: package_channel
|
||||
description: Package channel
|
||||
type: string
|
||||
required: true
|
||||
example: stable
|
||||
- in: path
|
||||
name: recipe_revision
|
||||
description: Recipe revision
|
||||
type: string
|
||||
required: true
|
||||
example: df28fd816be3a119de5ce4d374436b25
|
||||
- in: path
|
||||
name: conan_package_reference
|
||||
description: Package reference
|
||||
type: string
|
||||
required: true
|
||||
example: 5ab84d6acfe1f23c4fae0ab88f26e3a396351ac9
|
||||
- in: path
|
||||
name: package_revision
|
||||
description: Package revision
|
||||
type: string
|
||||
required: true
|
||||
example: 3bdd2d8c8e76c876ebd1ac0469a4e72c
|
||||
- in: path
|
||||
name: file_name
|
||||
description: Package file name
|
||||
type: string
|
||||
enum:
|
||||
- conanfile.py
|
||||
- conanmanifest.txt
|
||||
- conan_sources.tgz
|
||||
- conan_export.tgz
|
||||
- conaninfo.txt
|
||||
- conan_package.tgz
|
||||
required: true
|
||||
example: conaninfo.txt
|
||||
responses:
|
||||
'200':
|
||||
description: Download package files
|
||||
'400':
|
||||
description: Bad Request
|
||||
'401':
|
||||
description: Unauthorized
|
||||
'403':
|
||||
description: Forbidden
|
||||
'404':
|
||||
description: Not Found
|
||||
tags:
|
||||
- conan_packages
|
||||
operationId: getApiV4ProjectsIdPackagesConanV2ConansPackageNamePackageVersionPackageUsernamePackageChannelRevisionsRecipeRevisionPackagesConanPackageReferenceRevisionsPackageRevisionFilesFileName
|
||||
put:
|
||||
summary: Upload package files
|
||||
description: This feature was introduced in GitLab 17.11
|
||||
produces:
|
||||
|
|
|
|||
|
|
@ -336,6 +336,43 @@ Example response:
|
|||
}
|
||||
```
|
||||
|
||||
## Get a package file
|
||||
|
||||
Gets a package file from the package registry.
|
||||
|
||||
```plaintext
|
||||
GET /projects/:id/packages/conan/v2/conans/:package_name/:package_version/:package_username/:package_channel/revisions/:recipe_revision/packages/:conan_package_reference/revisions/:package_revision/files/:file_name
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| ------------------------- | ---- | -------- | ----------- |
|
||||
| `id` | string | yes | The project ID or full project path. |
|
||||
| `package_name` | string | yes | Name of a package. |
|
||||
| `package_version` | string | yes | Version of a package. |
|
||||
| `package_username` | string | yes | Conan username of a package. This attribute is the `+`-separated full path of your project. |
|
||||
| `package_channel` | string | yes | Channel of a package. |
|
||||
| `recipe_revision` | string | yes | Revision of the recipe. Does not accept a value of `0`. |
|
||||
| `conan_package_reference` | string | yes | Reference hash of a Conan package. Conan generates this value. |
|
||||
| `package_revision` | string | yes | Revision of the package. Does not accept a value of `0`. |
|
||||
| `file_name` | string | yes | The name and file extension of the requested file. |
|
||||
|
||||
```shell
|
||||
curl --request GET \
|
||||
--header "Authorization: Bearer <authenticate_token>" \
|
||||
--url "https://gitlab.example.com/api/v4/projects/9/packages/conan/v2/conans/my-package/1.0/my-group+my-project/stable/revisions/75151329520e7685dcf5da49ded2fec0/packages/103f6067a947f366ef91fc1b7da351c588d1827f/revisions/3bdd2d8c8e76c876ebd1ac0469a4e72c/files/conaninfo.txt"
|
||||
```
|
||||
|
||||
You can also write the output to a file by using:
|
||||
|
||||
```shell
|
||||
curl --request GET \
|
||||
--header "Authorization: Bearer <authenticate_token>" \
|
||||
--url "https://gitlab.example.com/api/v4/projects/9/packages/conan/v2/conans/my-package/1.0/my-group+my-project/stable/revisions/75151329520e7685dcf5da49ded2fec0/packages/103f6067a947f366ef91fc1b7da351c588d1827f/revisions/3bdd2d8c8e76c876ebd1ac0469a4e72c/files/conaninfo.txt" \
|
||||
>> conaninfo.txt
|
||||
```
|
||||
|
||||
This example writes to `conaninfo.txt` in the current directory.
|
||||
|
||||
## Upload a package file
|
||||
|
||||
Uploads a package file to the package registry.
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@ The following endpoints are available for CI/CD job tokens.
|
|||
| Packages: Read | `READ_PACKAGES` | `GET /projects/:id/packages/conan/v2/conans/:package_name/:package_version/:package_username/:package_channel/revisions/:recipe_revision/files/:file_name` | Download recipe files |
|
||||
| Packages: Read | `READ_PACKAGES` | `GET /projects/:id/packages/conan/v2/conans/:package_name/:package_version/:package_username/:package_channel/revisions/:recipe_revision/files` | List recipe files |
|
||||
| Packages: Read | `READ_PACKAGES` | `GET /projects/:id/packages/conan/v2/conans/:package_name/:package_version/:package_username/:package_channel/revisions/:recipe_revision/packages/:conan_package_reference/latest` | Get the latest package revision |
|
||||
| Packages: Read | `READ_PACKAGES` | `GET /projects/:id/packages/conan/v2/conans/:package_name/:package_version/:package_username/:package_channel/revisions/:recipe_revision/packages/:conan_package_reference/revisions/:package_revision/files/:file_name` | Download package files |
|
||||
| Packages: Read | `READ_PACKAGES` | `GET /projects/:id/packages/conan/v2/conans/:package_name/:package_version/:package_username/:package_channel/revisions` | Get the list of revisions |
|
||||
| Packages: Read | `READ_PACKAGES` | `GET /projects/:id/packages/generic/:package_name/*package_version/(*path/):file_name` | Download package file |
|
||||
| Packages: Read | `READ_PACKAGES` | `GET /projects/:id/packages/go/*module_name/@v/:module_version.info` | Version metadata |
|
||||
|
|
|
|||
|
|
@ -9,7 +9,8 @@ title: JetBrains troubleshooting
|
|||
If the steps on this page don't solve your problem, check the
|
||||
[list of open issues](https://gitlab.com/gitlab-org/editor-extensions/gitlab-jetbrains-plugin/-/issues/?sort=created_date&state=opened&first_page_size=100)
|
||||
in the JetBrains plugin's project. If an issue matches your problem, update the issue.
|
||||
If no issues match your problem, [create a new issue](https://gitlab.com/gitlab-org/editor-extensions/gitlab-jetbrains-plugin/-/issues/new).
|
||||
If no issues match your problem, [create a new issue](https://gitlab.com/gitlab-org/editor-extensions/gitlab-jetbrains-plugin/-/issues/new)
|
||||
and provide the [required information for Support](#required-information-for-support).
|
||||
|
||||
For troubleshooting JetBrains IDEs for GitLab Duo Code Suggestions,
|
||||
see [Troubleshooting Code Suggestions](../../user/project/repository/code_suggestions/troubleshooting.md#jetbrains-ides-troubleshooting).
|
||||
|
|
@ -23,8 +24,6 @@ To enable debug logs in JetBrains:
|
|||
1. Add this line: `com.gitlab.plugin`
|
||||
1. Select **OK** or **Save**.
|
||||
|
||||
## Use an HTTP proxy
|
||||
|
||||
If you experience [certificate errors](#certificate-errors) or other connection errors, and
|
||||
use a HTTP proxy to connect to your GitLab instance, you must
|
||||
[configure the Language Server to use a proxy](../language_server/_index.md#configure-the-language-server-to-use-a-proxy)
|
||||
|
|
@ -43,6 +42,8 @@ To enable GitLab Language Server debug logs:
|
|||
1. Select **Apply**.
|
||||
1. Below **Enable GitLab Language Server**, select **Restart Language Server**.
|
||||
|
||||
## Get debug logs
|
||||
|
||||
The debug logs are available in the `idea.log` log file. To view this file, either:
|
||||
|
||||
<!-- vale gitlab_base.SubstitutionWarning = NO -->
|
||||
|
|
@ -74,7 +75,8 @@ To do this:
|
|||
### Ignore certificate errors
|
||||
|
||||
If GitLab Duo still fails to connect, you might need to
|
||||
ignore certificate errors. You might see errors in the GitLab Language Server logs after enabling [debug mode](jetbrains_troubleshooting.md#enable-debug-mode):
|
||||
ignore certificate errors. You might see errors in the GitLab Language Server logs after enabling
|
||||
[debug mode](jetbrains_troubleshooting.md#enable-debug-mode):
|
||||
|
||||
```plaintext
|
||||
2024-10-31T10:32:54:165 [error]: fetch: request to https://gitlab.com/api/v4/personal_access_tokens/self failed with:
|
||||
|
|
@ -124,3 +126,32 @@ If you experience issues with GitLab Duo Chat related to JCEF (Java Chromium Emb
|
|||
1. Select the boot java runtime version that's the same as your current IDE version, but with JCEF bundled:
|
||||

|
||||
1. Restart your IDE.
|
||||
|
||||
## Required information for support
|
||||
|
||||
Before contacting Support, make sure the latest GitLab Workflow extension is installed. All releases
|
||||
are available in the [JetBrains Marketplace](https://plugins.jetbrains.com/plugin/22325-gitlab-duo/versions),
|
||||
on the **Versions** tab.
|
||||
|
||||
Gather this information from affected users, and provide it in your bug report:
|
||||
|
||||
1. The error message shown to the user.
|
||||
1. Workflow and Language Server logs:
|
||||
- [Debug logs](#enable-debug-mode).
|
||||
- [Language Server debug logs](#enable-gitlab-language-server-debug-logs).
|
||||
- [Logs output](#get-debug-logs)
|
||||
1. Diagnostics output. In your IntelliJ product, go to **Help > Diagnostics Tools > Collect Troubleshooting Information**.
|
||||
- In the **About** section, copy the **Build Version**.
|
||||
- For plugin-specific versions: in the **Plugins** section, copy the output.
|
||||
1. System details. In your IntelliJ product, go to **Help > Diagnostics Tools > Collect Troubleshooting Information**.
|
||||
- For the operating system type and version: in the dialog, copy **Operating System**.
|
||||
- For the machine specifications, copy the `System` section.
|
||||
1. Describe the scope of impact. How many users are affected?
|
||||
1. Describe how to reproduce the error. Include a screen recording, if possible.
|
||||
1. Describe how other GitLab Duo features are affected:
|
||||
- Is **GitLab Quick Chat** functional?
|
||||
- Is **Code Suggestions** working?
|
||||
- Does **Web IDE Duo Chat** return responses?
|
||||
1. Perform extension isolation testing. Try disabling (or uninstalling) all other extensions to determine
|
||||
if another extension is causing the issue. This helps determine if the problem is with our extension,
|
||||
or from an external source.
|
||||
|
|
|
|||
|
|
@ -42,14 +42,24 @@ When you view a GitLab project in VS Code, the extension shows you information a
|
|||
|
||||
## Switch GitLab accounts in VS Code
|
||||
|
||||
The GitLab Workflow extension uses one account for each [VS Code Workspace](https://code.visualstudio.com/docs/editor/workspaces) (window). The extension automatically selects the account when:
|
||||
The GitLab Workflow extension uses one account for each
|
||||
[VS Code Workspace](https://code.visualstudio.com/docs/editor/workspaces) (window). The extension
|
||||
automatically selects the account when:
|
||||
|
||||
- You have added only one GitLab account to the extension.
|
||||
- All workspaces in your VS Code window use the same GitLab account, based on the `git remote` configuration.
|
||||
|
||||
In other cases, you must select a GitLab account for the active VS Code window.
|
||||
What the extension shows in the status bar depends on your account setup:
|
||||
|
||||
To change the account selection:
|
||||

|
||||
|
||||
- If only one GitLab account exists, the status bar shows no information.
|
||||
- If multiple GitLab accounts exist, and the extension can determine which account to use,
|
||||
the status bar shows the account name next to the tanuki ({{< icon name="tanuki">}}) icon.
|
||||
- If multiple GitLab accounts exist, and the extension can't determine which account to use,
|
||||
the status bar shows **Multiple GitLab Accounts** ({{< icon name="question-o">}}).
|
||||
|
||||
To select a GitLab account for the active VS Code window, select the status bar item, or:
|
||||
|
||||
1. Open the Command Palette:
|
||||
- For macOS, press <kbd>Command</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>.
|
||||
|
|
@ -57,11 +67,10 @@ To change the account selection:
|
|||
1. Run the command `GitLab: Select Account for this Workspace`.
|
||||
1. Select your desired account from the list.
|
||||
|
||||
You can also change accounts by selecting the GitLab account status bar item.
|
||||
|
||||
## Select your GitLab project
|
||||
|
||||
When your Git repository can be associated with multiple GitLab projects, the extension cannot determine which account to use. This can happen when you have multiple remotes, for example:
|
||||
When your Git repository can be associated with multiple GitLab projects, the extension cannot
|
||||
determine which account to use. This can happen when you have multiple remotes, for example:
|
||||
|
||||
- `origin`: `git@gitlab.com:gitlab-org/gitlab-vscode-extension.git`
|
||||
- `personal-fork`: `git@gitlab.com:myusername/gitlab-vscode-extension.git`
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 10 KiB |
|
|
@ -11,6 +11,7 @@ If you encounter any issues with the GitLab Workflow extension for VS Code, or h
|
|||
for known issues and solutions.
|
||||
1. Report bugs or request features in the
|
||||
[`gitlab-vscode-extension` issue tracker](https://gitlab.com/gitlab-org/gitlab-vscode-extension/-/issues).
|
||||
Provide the [required information for Support](#required-information-for-support).
|
||||
|
||||
For troubleshooting VS Code for GitLab Duo Code Suggestions,
|
||||
see [Troubleshooting Code Suggestions for VS Code](../../user/project/repository/code_suggestions/troubleshooting.md#vs-code-troubleshooting).
|
||||
|
|
@ -167,3 +168,33 @@ hosted on `https`.
|
|||
|
||||
To resolve this, manually enter an `http` URL for your instance when you run the
|
||||
`GitLab: Authenticate` command.
|
||||
|
||||
## Required information for support
|
||||
|
||||
Before contacting Support, make sure the latest GitLab Workflow extension is installed. All releases
|
||||
are available on the [VS Code Marketplace](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow)
|
||||
under the **Version History** tab.
|
||||
|
||||
Gather this information from affected users, and provide it in your bug report:
|
||||
|
||||
1. The error message shown to the user.
|
||||
1. Workflow and Language Server logs:
|
||||
1. [Enable debug logs](#enable-debug-logs).
|
||||
1. [Retrieve log files](#view-log-files) for the extension, and the Language Server.
|
||||
1. Diagnostics output.
|
||||
1. Open the Command Palette with <kbd>Command</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd> or
|
||||
<kbd>Control</kbd>+<kbd>Shift</kbd>+<kbd>P</kbd>
|
||||
1. Run the command `GitLab: Diagnostics`, and note the extension version.
|
||||
1. System details:
|
||||
- In VS Code, go to **Code > About Visual Studio Code** and find **OS**.
|
||||
- Machine specifications (CPU, RAM): Provide these from your machine. They are not accessible in the IDE.
|
||||
1. Describe the scope of impact. How many users are affected?
|
||||
1. Describe how to reproduce the error. Include a screen recording, if possible.
|
||||
1. Describe how other GitLab Duo features are affected:
|
||||
- Is **GitLab Quick Chat** functional?
|
||||
- Is **Code Suggestions** working?
|
||||
- Does **Web IDE Duo Chat** return responses?
|
||||
1. Perform extension isolation testing as described in the
|
||||
[GitLab Workflow Extension Isolation Guide](https://gitlab.com/gitlab-org/editor-extensions/gitlab-lsp/-/issues/814#step-2-extension-isolation-testing).
|
||||
Try disabling (or uninstalling) all other extensions to determine if another extension is causing
|
||||
the issue. This helps determine if the problem is with our extension, or from an external source.
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ and crawls the site using an embedded browser.
|
|||
- This template was [updated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87183) to DAST_VERSION: 3 in GitLab 15.0.
|
||||
- This template was updated to DAST_VERSION: 4 in GitLab 16.0.
|
||||
- This template was [updated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151910) to DAST_VERSION: 5 in GitLab 17.0.
|
||||
- This template was [updated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/188703) to DAST_VERSION: 6 in GitLab 18.0.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,27 @@ The following variables are available:
|
|||
All variables should be referenced using the double curly brace syntax, for example: `{{ .project.id }}`.
|
||||
See [`text/template`](https://pkg.go.dev/text/template) documentation for more information on the templating system used.
|
||||
|
||||
### Resource lifecycle management
|
||||
|
||||
{{< history >}}
|
||||
|
||||
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/507486) in GitLab 18.0.
|
||||
|
||||
{{< /history >}}
|
||||
|
||||
Use the following settings to configure when Kubernetes resources should be removed:
|
||||
|
||||
```yaml
|
||||
# Never delete resources
|
||||
delete_resources: never
|
||||
|
||||
# Delete resources when environment is stopped
|
||||
delete_resources: on_stop
|
||||
```
|
||||
|
||||
The default value is `on_stop`, which is specified in the
|
||||
[default environment template](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/internal/module/managed_resources/server/default_template.yaml).
|
||||
|
||||
### Managed resource labels and annotations
|
||||
|
||||
The resources created by GitLab use a series of labels and annotations for tracking and troubleshooting purposes.
|
||||
|
|
|
|||
|
|
@ -230,6 +230,25 @@ module API
|
|||
documentation: { example: 'conaninfo.txt' }
|
||||
end
|
||||
namespace ':file_name', requirements: FILE_NAME_REQUIREMENTS do
|
||||
desc 'Download package files' do
|
||||
detail 'This feature was introduced in GitLab 17.11'
|
||||
success code: 200
|
||||
failure [
|
||||
{ code: 400, message: 'Bad Request' },
|
||||
{ code: 401, message: 'Unauthorized' },
|
||||
{ code: 403, message: 'Forbidden' },
|
||||
{ code: 404, message: 'Not Found' }
|
||||
]
|
||||
tags %w[conan_packages]
|
||||
end
|
||||
route_setting :authentication, job_token_allowed: true,
|
||||
basic_auth_personal_access_token: true
|
||||
route_setting :authorization, job_token_policies: :read_packages,
|
||||
allow_public_access_for_enabled_project_features: :package_registry
|
||||
get urgency: :low do
|
||||
download_package_file(:package_file)
|
||||
end
|
||||
|
||||
desc 'Upload package files' do
|
||||
detail 'This feature was introduced in GitLab 17.11'
|
||||
success code: 200
|
||||
|
|
|
|||
|
|
@ -170,7 +170,8 @@ module API
|
|||
file_name: params[:file_name].to_s,
|
||||
conan_file_type: file_type,
|
||||
conan_package_reference: declared(params)[:conan_package_reference],
|
||||
recipe_revision: params[:recipe_revision]
|
||||
recipe_revision: params[:recipe_revision],
|
||||
package_revision: declared(params)[:package_revision]
|
||||
).execute!
|
||||
|
||||
track_package_event('pull_package', :conan, category: 'API::ConanPackages', project: project, namespace: project.namespace) if params[:file_name] == ::Packages::Conan::FileMetadatum::PACKAGE_BINARY
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ variables:
|
|||
# (SAST, Dependency Scanning, ...)
|
||||
SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
|
||||
#
|
||||
FUZZAPI_VERSION: "5"
|
||||
FUZZAPI_VERSION: "6"
|
||||
FUZZAPI_IMAGE_SUFFIX: ""
|
||||
FUZZAPI_IMAGE: api-security
|
||||
|
||||
|
|
|
|||
|
|
@ -28,7 +28,7 @@ variables:
|
|||
AST_ENABLE_MR_PIPELINES: "true"
|
||||
#
|
||||
|
||||
FUZZAPI_VERSION: "5"
|
||||
FUZZAPI_VERSION: "6"
|
||||
FUZZAPI_IMAGE_SUFFIX: ""
|
||||
FUZZAPI_IMAGE: api-security
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ variables:
|
|||
# (SAST, Dependency Scanning, ...)
|
||||
SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
|
||||
#
|
||||
APISEC_VERSION: "5"
|
||||
APISEC_VERSION: "6"
|
||||
APISEC_IMAGE_SUFFIX: ""
|
||||
APISEC_IMAGE: api-security
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ variables:
|
|||
SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
|
||||
AST_ENABLE_MR_PIPELINES: "true"
|
||||
#
|
||||
APISEC_VERSION: "5"
|
||||
APISEC_VERSION: "6"
|
||||
APISEC_IMAGE_SUFFIX: ""
|
||||
APISEC_IMAGE: api-security
|
||||
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ variables:
|
|||
# (SAST, Dependency Scanning, ...)
|
||||
SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
|
||||
#
|
||||
DAST_API_VERSION: "5"
|
||||
DAST_API_VERSION: "6"
|
||||
DAST_API_IMAGE_SUFFIX: ""
|
||||
DAST_API_IMAGE: api-security
|
||||
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ variables:
|
|||
SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
|
||||
AST_ENABLE_MR_PIPELINES: "true"
|
||||
#
|
||||
DAST_API_VERSION: "5"
|
||||
DAST_API_VERSION: "6"
|
||||
DAST_API_IMAGE_SUFFIX: ""
|
||||
DAST_API_IMAGE: api-security
|
||||
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@ stages:
|
|||
|
||||
variables:
|
||||
SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
|
||||
DAST_API_VERSION: "5"
|
||||
DAST_API_VERSION: "6"
|
||||
DAST_API_IMAGE_SUFFIX: ""
|
||||
DAST_API_IMAGE: api-security
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ stages:
|
|||
- dast
|
||||
|
||||
variables:
|
||||
DAST_VERSION: 5
|
||||
DAST_VERSION: 6
|
||||
# Setting this variable will affect all Security templates
|
||||
# (SAST, Dependency Scanning, ...)
|
||||
SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
# List of available variables: https://docs.gitlab.com/ee/user/application_security/dast/#available-variables
|
||||
|
||||
variables:
|
||||
DAST_VERSION: 5
|
||||
DAST_VERSION: 6
|
||||
# Setting this variable affects all Security templates
|
||||
# (SAST, Dependency Scanning, ...)
|
||||
SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@
|
|||
# List of available variables: https://docs.gitlab.com/user/application_security/dast/browser/configuration/variables/
|
||||
|
||||
variables:
|
||||
DAST_VERSION: 5
|
||||
DAST_VERSION: 6
|
||||
# Setting these variables affect all Security templates
|
||||
# (SAST, Dependency Scanning, ...)
|
||||
SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
|
||||
|
|
|
|||
|
|
@ -219,7 +219,7 @@ license-finder:
|
|||
dast:
|
||||
extends: .download_images
|
||||
variables:
|
||||
SECURE_BINARIES_ANALYZER_VERSION: "5"
|
||||
SECURE_BINARIES_ANALYZER_VERSION: "6"
|
||||
rules:
|
||||
- if: '$SECURE_BINARIES_DOWNLOAD_IMAGES == "true" && $SECURE_BINARIES_ANALYZERS =~ /\bdast\b/'
|
||||
|
||||
|
|
@ -234,6 +234,6 @@ dast-runner-validation:
|
|||
api-security:
|
||||
extends: .download_images
|
||||
variables:
|
||||
SECURE_BINARIES_ANALYZER_VERSION: "5"
|
||||
SECURE_BINARIES_ANALYZER_VERSION: "6"
|
||||
rules:
|
||||
- if: '$SECURE_BINARIES_DOWNLOAD_IMAGES == "true" && $SECURE_BINARIES_ANALYZERS =~ /\bapi-security\b/'
|
||||
|
|
|
|||
|
|
@ -146,6 +146,17 @@ module Gitlab
|
|||
.ensure_environment(request, metadata: metadata)
|
||||
end
|
||||
|
||||
def delete_environment(managed_resource:)
|
||||
request = ::Gitlab::Agent::ManagedResources::Rpc::DeleteEnvironmentRequest.new(
|
||||
agent_id: managed_resource.cluster_agent_id,
|
||||
project_id: managed_resource.project_id,
|
||||
environment_slug: managed_resource.environment.slug,
|
||||
objects: managed_resource.tracked_objects
|
||||
)
|
||||
|
||||
stub_for(:managed_resources).delete_environment(request, metadata: metadata)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def stub_for(service)
|
||||
|
|
|
|||
|
|
@ -59835,12 +59835,6 @@ msgstr ""
|
|||
msgid "TargetedMessages|Failed to assign namespaces due to error processing CSV: %{error_message}"
|
||||
msgstr ""
|
||||
|
||||
msgid "TargetedMessages|Failed to create targeted message: %{error_message}"
|
||||
msgstr ""
|
||||
|
||||
msgid "TargetedMessages|Failed to update targeted message: %{error_message}"
|
||||
msgstr ""
|
||||
|
||||
msgid "TargetedMessages|New targeted message"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -59853,15 +59847,21 @@ msgstr ""
|
|||
msgid "TargetedMessages|Targeted message was successfully created."
|
||||
msgstr ""
|
||||
|
||||
msgid "TargetedMessages|Targeted message was successfully created. But %{invalid_namespace_ids_message}"
|
||||
msgstr ""
|
||||
|
||||
msgid "TargetedMessages|Targeted message was successfully updated."
|
||||
msgstr ""
|
||||
|
||||
msgid "TargetedMessages|The following namespace ids were invalid and have been ignored: %{invalid_ids_message}"
|
||||
msgid "TargetedMessages|Targeted message was successfully updated. But %{invalid_namespace_ids_message}"
|
||||
msgstr ""
|
||||
|
||||
msgid "TargetedMessages|Upload a csv file for targeted namespaces"
|
||||
msgstr ""
|
||||
|
||||
msgid "TargetedMessages|the following namespace ids were invalid and have been ignored: %{invalid_ids_message}"
|
||||
msgstr ""
|
||||
|
||||
msgid "Task"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -305,7 +305,7 @@
|
|||
"swagger-cli": "^4.0.4",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"timezone-mock": "^1.0.8",
|
||||
"vite": "^6.3.0",
|
||||
"vite": "^6.3.1",
|
||||
"vite-plugin-ruby": "^5.1.1",
|
||||
"vue-loader-vue3": "npm:vue-loader@17.4.2",
|
||||
"vue-test-utils-compat": "0.0.14",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,53 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module RuboCop
|
||||
module Cop
|
||||
module Sidekiq
|
||||
# This cop enforces the use of `defer_on_database_health_signal` for low urgency workers
|
||||
#
|
||||
# @example
|
||||
#
|
||||
# # bad
|
||||
# module Workers
|
||||
# class MyWorker
|
||||
# include ApplicationWorker
|
||||
#
|
||||
# urgency :low
|
||||
# end
|
||||
# end
|
||||
#
|
||||
# # good
|
||||
# module Workers
|
||||
# class MyWorker
|
||||
# include ApplicationWorker
|
||||
#
|
||||
# urgency :low
|
||||
# defer_on_database_health_signal :gitlab_main, [:users], 2.minutes
|
||||
# end
|
||||
# end
|
||||
class EnforceDatabaseHealthSignalDeferral < RuboCop::Cop::Base
|
||||
URL = 'https://docs.gitlab.com/development/sidekiq/#deferring-sidekiq-workers'
|
||||
MSG = "Low urgency workers should have the option to be deferred based on the database health condition. " \
|
||||
"Consider using `defer_on_database_health_signal`, check #{URL} for more information.".freeze
|
||||
|
||||
# @!method low_urgency?(node)
|
||||
def_node_matcher :low_urgency?, <<~PATTERN
|
||||
`(send nil? :urgency (sym :low) ...)
|
||||
PATTERN
|
||||
|
||||
# @!method defers_on_database_health_signal?(node)
|
||||
def_node_matcher :defers_on_database_health_signal?, <<~PATTERN
|
||||
`(send nil? :defer_on_database_health_signal ...)
|
||||
PATTERN
|
||||
|
||||
def on_class(node)
|
||||
return unless low_urgency?(node)
|
||||
|
||||
return if defers_on_database_health_signal?(node)
|
||||
|
||||
add_offense(node)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -5,6 +5,30 @@ FactoryBot.define do
|
|||
project
|
||||
environment
|
||||
association :cluster_agent
|
||||
association :build
|
||||
association :build, factory: :ci_build
|
||||
deletion_strategy { :on_stop }
|
||||
|
||||
tracked_objects do
|
||||
[
|
||||
{
|
||||
'kind' => 'Namespace',
|
||||
'name' => 'production',
|
||||
'group' => '',
|
||||
'version' => 'v1',
|
||||
'namespace' => ''
|
||||
},
|
||||
{
|
||||
'kind' => 'RoleBinding',
|
||||
'name' => 'bind-ci-job-production',
|
||||
'group' => 'rbac.authorization.k8s.io',
|
||||
'version' => 'v1',
|
||||
'namespace' => 'production'
|
||||
}
|
||||
]
|
||||
end
|
||||
|
||||
trait :completed do
|
||||
status { :completed }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -178,7 +178,7 @@ RSpec.describe 'Admin Mode Login', feature_category: :system_access do
|
|||
end
|
||||
|
||||
def enable_admin_mode_using_saml!
|
||||
gitlab_enable_admin_mode_sign_in_via('saml', user, 'my-uid', mock_saml_response)
|
||||
gitlab_enable_admin_mode_sign_in_via('saml', user, 'my-uid', saml_response: mock_saml_response)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,191 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Step-up authentication', :js, feature_category: :shared do
|
||||
let_it_be(:extern_uid) { 'my-uid' }
|
||||
let_it_be(:provider_oidc) { 'openid_connect' }
|
||||
|
||||
let(:provider_oidc_config_with_step_up_auth) do
|
||||
GitlabSettings::Options.new(
|
||||
name: provider_oidc,
|
||||
step_up_auth: {
|
||||
admin_mode: {
|
||||
id_token: {
|
||||
required: { acr: 'gold' }
|
||||
}
|
||||
}
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
let(:additional_info_rejected_step_up_auth) { { extra: { raw_info: { acr: 'bronze' } } } }
|
||||
let(:additional_info_success_step_up_auth) { { extra: { raw_info: { acr: 'gold' } } } }
|
||||
|
||||
around do |example|
|
||||
with_omniauth_full_host { example.run }
|
||||
end
|
||||
|
||||
context 'for admin mode' do
|
||||
let_it_be(:admin) do
|
||||
create(:omniauth_user, :admin, password_automatically_set: false, extern_uid: extern_uid, provider: provider_oidc)
|
||||
end
|
||||
|
||||
before do
|
||||
stub_omniauth_setting(enabled: true, auto_link_user: true, providers: [provider_oidc_config_with_step_up_auth])
|
||||
end
|
||||
|
||||
context 'when step-up auth conditions fulfilled' do
|
||||
before do
|
||||
sign_in(admin)
|
||||
end
|
||||
|
||||
it 'user enters admin mode successfully' do
|
||||
gitlab_enable_admin_mode_sign_in_via(provider_oidc, admin, extern_uid,
|
||||
additional_info: additional_info_success_step_up_auth)
|
||||
|
||||
expect(page).to have_current_path admin_root_path, ignore_query: true
|
||||
expect(page).to have_content('Admin mode enabled')
|
||||
end
|
||||
|
||||
it 'user enters admin mode, leaves admin mode and cannot re-enter admin mode without re-authentication' do
|
||||
gitlab_enable_admin_mode_sign_in_via(provider_oidc, admin, extern_uid,
|
||||
additional_info: additional_info_success_step_up_auth)
|
||||
|
||||
expect(page).to have_current_path admin_root_path, ignore_query: true
|
||||
expect(page).to have_content('Admin mode enabled')
|
||||
|
||||
# Leave admin mode
|
||||
find_by_testid('user-menu-toggle').click
|
||||
click_link('Leave Admin Mode', href: destroy_admin_session_path)
|
||||
|
||||
wait_for_requests
|
||||
expect(page).to have_text 'Admin mode disabled'
|
||||
|
||||
# Attempt to access the admin area again
|
||||
visit admin_root_path
|
||||
|
||||
# Ensure re-authentication is required
|
||||
expect(page).to have_current_path new_admin_session_path
|
||||
expect(page).to have_content('Re-authentication required')
|
||||
end
|
||||
|
||||
it 'user enters admin mode and navigates successfully between non-admin and admin areas' do
|
||||
gitlab_enable_admin_mode_sign_in_via(provider_oidc, admin, extern_uid,
|
||||
additional_info: additional_info_success_step_up_auth)
|
||||
|
||||
expect(page).to have_current_path admin_root_path, ignore_query: true
|
||||
expect(page).to have_content('Admin mode enabled')
|
||||
|
||||
# Go to non-admin page
|
||||
visit root_path
|
||||
wait_for_requests
|
||||
expect(page).to have_current_path root_path, ignore_query: true
|
||||
|
||||
# Return to admin area
|
||||
visit admin_root_path
|
||||
wait_for_requests
|
||||
expect(page).to have_current_path admin_root_path, ignore_query: true
|
||||
expect(page).not_to have_content('Admin mode enabled')
|
||||
end
|
||||
|
||||
context 'when feature flag :omniauth_step_up_auth_for_admin_mode is disabled' do
|
||||
before do
|
||||
stub_feature_flags(omniauth_step_up_auth_for_admin_mode: false)
|
||||
end
|
||||
|
||||
it 'user enters admin mode' do
|
||||
gitlab_enable_admin_mode_sign_in_via(provider_oidc, admin, extern_uid,
|
||||
additional_info: additional_info_success_step_up_auth)
|
||||
|
||||
expect(page).to have_current_path admin_root_path, ignore_query: true
|
||||
expect(page).to have_content('Admin mode enabled')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when step-up auth conditions not fulfilled' do
|
||||
before do
|
||||
sign_in(admin)
|
||||
end
|
||||
|
||||
it 'user cannot enter admin mode and shows correct info message' do
|
||||
gitlab_enable_admin_mode_sign_in_via(provider_oidc, admin, extern_uid,
|
||||
additional_info: additional_info_rejected_step_up_auth)
|
||||
|
||||
expect(page).to have_current_path new_admin_session_path
|
||||
expect(page).to have_content('Step-up auth not successful')
|
||||
end
|
||||
|
||||
context 'when feature flag :omniauth_step_up_auth_for_admin_mode is disabled' do
|
||||
before do
|
||||
stub_feature_flags(omniauth_step_up_auth_for_admin_mode: false)
|
||||
end
|
||||
|
||||
it 'user enters admin mode successfully' do
|
||||
gitlab_enable_admin_mode_sign_in_via(provider_oidc, admin, extern_uid,
|
||||
additional_info: additional_info_rejected_step_up_auth)
|
||||
|
||||
expect(page).to have_current_path admin_root_path
|
||||
expect(page).to have_content('Admin mode enabled')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'for different initial sign-in methods' do
|
||||
shared_examples 'successful step-up auth process' do
|
||||
it 'user enters admin mode with successful step-up auth process' do
|
||||
wait_for_requests
|
||||
expect(page).to have_current_path root_path, ignore_query: true
|
||||
|
||||
gitlab_enable_admin_mode_sign_in_via(provider_oidc, admin, extern_uid,
|
||||
additional_info: additional_info_rejected_step_up_auth)
|
||||
|
||||
wait_for_requests
|
||||
expect(page).to have_current_path new_admin_session_path
|
||||
expect(page).to have_content('Step-up auth not successful')
|
||||
|
||||
gitlab_enable_admin_mode_sign_in_via(provider_oidc, admin, extern_uid,
|
||||
additional_info: additional_info_success_step_up_auth)
|
||||
|
||||
expect(page).to have_current_path admin_root_path
|
||||
expect(page).to have_content('Admin mode enabled')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when user signed in initially with username and password' do
|
||||
before do
|
||||
gitlab_sign_in(admin)
|
||||
end
|
||||
|
||||
it_behaves_like 'successful step-up auth process'
|
||||
end
|
||||
|
||||
context 'when user signed in initially with same omniauth provider (openid_connect)' do
|
||||
before do
|
||||
gitlab_sign_in_via(provider_oidc, admin, extern_uid)
|
||||
end
|
||||
|
||||
it_behaves_like 'successful step-up auth process'
|
||||
end
|
||||
|
||||
context 'when user signed in initially with another omniauth provider (github)' do
|
||||
let(:provider_github) { 'github' }
|
||||
let(:provider_github_config) { GitlabSettings::Options.new(name: provider_github) }
|
||||
|
||||
before do
|
||||
# Add github identity to admin user
|
||||
admin.identities << create(:identity, provider: provider_github, extern_uid: extern_uid)
|
||||
|
||||
# Enable github provider
|
||||
stub_omniauth_setting(enabled: true, auto_link_user: true,
|
||||
providers: [provider_oidc_config_with_step_up_auth, provider_github_config])
|
||||
|
||||
gitlab_sign_in_via(provider_github, admin, extern_uid)
|
||||
end
|
||||
|
||||
it_behaves_like 'successful step-up auth process'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -5,15 +5,25 @@ require 'spec_helper'
|
|||
RSpec.describe Packages::Conan::PackageFilesFinder, feature_category: :package_registry do
|
||||
let_it_be(:package) { create(:conan_package) }
|
||||
let_it_be(:aditional_recipe_revision) { create(:conan_recipe_revision, package: package) }
|
||||
let_it_be(:aditional_package_revision) { create(:conan_package_revision, package: package) }
|
||||
let_it_be(:recipe_file_without_revision) do
|
||||
create(:conan_package_file, :conan_recipe_file,
|
||||
package: package, conan_recipe_revision: nil, conan_package_revision: nil)
|
||||
end
|
||||
|
||||
let_it_be(:package_file_without_revision) do
|
||||
create(:conan_package_file, :conan_recipe_file,
|
||||
package: package, conan_recipe_revision: nil)
|
||||
create(:conan_package_file, :conan_package_manifest,
|
||||
package: package, conan_recipe_revision: nil, conan_package_revision: nil)
|
||||
end
|
||||
|
||||
let_it_be(:aditional_recipe_file) do
|
||||
create(:conan_package_file, :conan_recipe_file, package: package,
|
||||
conan_recipe_revision: aditional_recipe_revision)
|
||||
end
|
||||
|
||||
let_it_be(:aditional_package_file) do
|
||||
create(:conan_package_file, :conan_recipe_file, package: package,
|
||||
conan_recipe_revision: aditional_recipe_revision)
|
||||
create(:conan_package_file, :conan_package_manifest, package: package,
|
||||
conan_recipe_revision: aditional_recipe_revision, conan_package_revision: aditional_package_revision)
|
||||
end
|
||||
|
||||
let(:package_files) { package.package_files }
|
||||
|
|
@ -84,7 +94,7 @@ RSpec.describe Packages::Conan::PackageFilesFinder, feature_category: :package_r
|
|||
let(:recipe_revision_value) { Packages::Conan::FileMetadatum::DEFAULT_REVISION }
|
||||
|
||||
it 'returns package files without recipe revision' do
|
||||
expect(found_package_files).to match_array([package_file_without_revision])
|
||||
expect(found_package_files).to match_array([recipe_file_without_revision, package_file_without_revision])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -102,6 +112,31 @@ RSpec.describe Packages::Conan::PackageFilesFinder, feature_category: :package_r
|
|||
end
|
||||
end
|
||||
|
||||
context 'with package_revision' do
|
||||
let(:params) { { package_revision: package_revision_value } }
|
||||
|
||||
context 'with default revision' do
|
||||
let(:package_revision_value) { Packages::Conan::FileMetadatum::DEFAULT_REVISION }
|
||||
|
||||
it 'returns package files without package revision' do
|
||||
expect(found_package_files).to match_array([package_file_without_revision])
|
||||
end
|
||||
end
|
||||
|
||||
context 'with specific revision' do
|
||||
let(:package_revision_value) { package.conan_package_revisions.first.revision }
|
||||
let(:expected_package_files) do
|
||||
package_files.select do |file|
|
||||
file.conan_file_metadatum.package_revision_value == package_revision_value
|
||||
end
|
||||
end
|
||||
|
||||
it 'returns package files with matching package revision' do
|
||||
expect(found_package_files).to match_array(expected_package_files)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when no files exist' do
|
||||
let_it_be(:package) { create(:conan_package, without_package_files: true) }
|
||||
|
||||
|
|
|
|||
|
|
@ -384,5 +384,35 @@ RSpec.describe Gitlab::Kas::Client, feature_category: :deployment_management do
|
|||
|
||||
it { expect(subject).to eq(response) }
|
||||
end
|
||||
|
||||
describe '#delete_environment' do
|
||||
let_it_be(:managed_resource) { create(:managed_resource) }
|
||||
|
||||
let(:stub) { instance_double(Gitlab::Agent::ManagedResources::Rpc::Provisioner::Stub) }
|
||||
let(:request) { instance_double(Gitlab::Agent::ManagedResources::Rpc::DeleteEnvironmentRequest) }
|
||||
let(:response) { double(Gitlab::Agent::ManagedResources::Rpc::DeleteEnvironmentResponse) }
|
||||
|
||||
subject { client.delete_environment(managed_resource: managed_resource) }
|
||||
|
||||
before do
|
||||
expect(Gitlab::Agent::ManagedResources::Rpc::Provisioner::Stub).to receive(:new)
|
||||
.with('example.kas.internal', :this_channel_is_insecure, timeout: client.send(:timeout))
|
||||
.and_return(stub)
|
||||
|
||||
expect(Gitlab::Agent::ManagedResources::Rpc::DeleteEnvironmentRequest).to receive(:new)
|
||||
.with(
|
||||
agent_id: managed_resource.cluster_agent_id,
|
||||
project_id: managed_resource.project_id,
|
||||
environment_slug: managed_resource.environment.slug,
|
||||
objects: managed_resource.tracked_objects
|
||||
).and_return(request)
|
||||
|
||||
expect(stub).to receive(:delete_environment)
|
||||
.with(request, metadata: { 'authorization' => 'bearer test-token' })
|
||||
.and_return(response)
|
||||
end
|
||||
|
||||
it { expect(subject).to eq(response) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,4 +9,32 @@ RSpec.describe Clusters::Agents::ManagedResource, feature_category: :deployment_
|
|||
it { is_expected.to belong_to(:environment) }
|
||||
|
||||
it { is_expected.to validate_length_of(:template_name).is_at_most(1024) }
|
||||
|
||||
describe '.order_id_desc' do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:environment) { create(:environment, project:) }
|
||||
let_it_be(:cluster_agent) { create(:cluster_agent, project:) }
|
||||
let_it_be(:build1) { create(:ci_build, project:) }
|
||||
let_it_be(:build2) { create(:ci_build, project:) }
|
||||
let_it_be(:build3) { create(:ci_build, project:) }
|
||||
|
||||
let!(:record1) do
|
||||
create(:managed_resource, id: 111, build: build1, project: project, environment: environment,
|
||||
cluster_agent: cluster_agent)
|
||||
end
|
||||
|
||||
let!(:record3) do
|
||||
create(:managed_resource, id: 333, build: build3, project: project, environment: environment,
|
||||
cluster_agent: cluster_agent)
|
||||
end
|
||||
|
||||
let!(:record2) do
|
||||
create(:managed_resource, id: 222, build: build2, project: project, environment: environment,
|
||||
cluster_agent: cluster_agent)
|
||||
end
|
||||
|
||||
subject { described_class.order_id_desc }
|
||||
|
||||
it { is_expected.to eq([record3, record2, record1]) }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@ RSpec.describe Environment, :use_clean_rails_memory_store_caching, feature_categ
|
|||
|
||||
it { is_expected.to have_many(:deployments) }
|
||||
it { is_expected.to have_many(:alert_management_alerts) }
|
||||
it { is_expected.to have_many(:managed_resources) }
|
||||
it { is_expected.to have_one(:upcoming_deployment) }
|
||||
it { is_expected.to have_one(:latest_opened_most_severe_alert) }
|
||||
|
||||
|
|
|
|||
|
|
@ -39,20 +39,20 @@ RSpec.describe Packages::PackageFile, type: :model, feature_category: :package_r
|
|||
let(:file) { fixture_file_upload('spec/fixtures/dk.png') }
|
||||
let(:params) { { file: file, file_name: file_name, status: status } }
|
||||
|
||||
subject { package.package_files.create!(params) }
|
||||
subject(:create_package_file) { package.package_files.create!(params) }
|
||||
|
||||
context 'file_name' do
|
||||
let(:file_name) { package_file.file_name }
|
||||
|
||||
it 'can not save a duplicated file' do
|
||||
expect { subject }.to raise_error(ActiveRecord::RecordInvalid, "Validation failed: File name has already been taken")
|
||||
expect { create_package_file }.to raise_error(ActiveRecord::RecordInvalid, "Validation failed: File name has already been taken")
|
||||
end
|
||||
|
||||
context 'with a pending destruction package duplicated file' do
|
||||
let(:status) { :pending_destruction }
|
||||
|
||||
it 'can save it' do
|
||||
expect { subject }.to change { package.package_files.count }.from(1).to(2)
|
||||
expect { create_package_file }.to change { package.package_files.count }.from(1).to(2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -72,9 +72,9 @@ RSpec.describe Packages::PackageFile, type: :model, feature_category: :package_r
|
|||
|
||||
it 'does not allow invalid sha256 characters' do
|
||||
if expected_success
|
||||
expect { subject }.not_to raise_error
|
||||
expect { create_package_file }.not_to raise_error
|
||||
else
|
||||
expect { subject }.to raise_error(ActiveRecord::RecordInvalid, "Validation failed: File sha256 is invalid")
|
||||
expect { create_package_file }.to raise_error(ActiveRecord::RecordInvalid, "Validation failed: File sha256 is invalid")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -162,13 +162,13 @@ RSpec.describe Packages::PackageFile, type: :model, feature_category: :package_r
|
|||
conan_package_reference: other_package_reference)
|
||||
end
|
||||
|
||||
subject { described_class.with_conan_package_reference(reference) }
|
||||
subject(:result) { described_class.with_conan_package_reference(reference) }
|
||||
|
||||
context 'with existing reference' do
|
||||
let(:reference) { matching_package_file.conan_file_metadatum.package_reference.reference }
|
||||
|
||||
it 'returns package files with matching reference' do
|
||||
expect(subject).to contain_exactly(matching_package_file)
|
||||
expect(result).to contain_exactly(matching_package_file)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -176,7 +176,7 @@ RSpec.describe Packages::PackageFile, type: :model, feature_category: :package_r
|
|||
let(:reference) { non_existing_record_id.to_s }
|
||||
|
||||
it 'returns empty relation' do
|
||||
expect(subject).to be_empty
|
||||
expect(result).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -203,13 +203,13 @@ RSpec.describe Packages::PackageFile, type: :model, feature_category: :package_r
|
|||
end
|
||||
|
||||
describe '.with_conan_recipe_revision' do
|
||||
subject { described_class.with_conan_recipe_revision(revision) }
|
||||
subject(:result) { described_class.with_conan_recipe_revision(revision) }
|
||||
|
||||
context 'with existing revision' do
|
||||
let(:revision) { recipe_revision.revision }
|
||||
|
||||
it 'returns package files with matching recipe revision' do
|
||||
expect(subject).to contain_exactly(package_file_with_revision)
|
||||
expect(result).to contain_exactly(package_file_with_revision)
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -217,16 +217,66 @@ RSpec.describe Packages::PackageFile, type: :model, feature_category: :package_r
|
|||
let(:revision) { 'nonexistent' }
|
||||
|
||||
it 'returns empty relation' do
|
||||
expect(subject).to be_empty
|
||||
expect(result).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.without_conan_recipe_revision' do
|
||||
subject { described_class.without_conan_recipe_revision }
|
||||
subject(:result) { described_class.without_conan_recipe_revision }
|
||||
|
||||
it 'returns only package files without recipe revision' do
|
||||
expect(subject).to contain_exactly(package_file_without_revision)
|
||||
expect(result).to contain_exactly(package_file_without_revision)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'package revision scopes' do
|
||||
let_it_be(:package_revision) { package.conan_package_revisions.first }
|
||||
let_it_be(:other_package_revision) { create(:conan_package_revision, package_reference: package.conan_package_references.first) }
|
||||
|
||||
let_it_be(:package_file_with_revision) do
|
||||
create(:conan_package_file, :conan_package,
|
||||
package: package,
|
||||
conan_package_revision: package_revision)
|
||||
end
|
||||
|
||||
let_it_be(:package_file_with_other_revision) do
|
||||
create(:conan_package_file, :conan_package,
|
||||
package: package,
|
||||
conan_package_revision: other_package_revision)
|
||||
end
|
||||
|
||||
let_it_be(:package_file_without_revision) do
|
||||
create(:conan_package_file, :conan_package,
|
||||
package: package, conan_recipe_revision: nil, conan_package_revision: nil)
|
||||
end
|
||||
|
||||
describe '.with_conan_package_revision' do
|
||||
subject(:result) { described_class.with_conan_package_revision(revision) }
|
||||
|
||||
context 'with existing revision' do
|
||||
let(:revision) { package_revision.revision }
|
||||
|
||||
it 'returns package files with matching package revision' do
|
||||
expect(result).to contain_exactly(package_file_with_revision)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when revision does not exist' do
|
||||
let(:revision) { 'nonexistent' }
|
||||
|
||||
it 'returns empty relation' do
|
||||
expect(result).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '.without_conan_package_revision' do
|
||||
subject(:result) { described_class.without_conan_package_revision }
|
||||
|
||||
it 'returns only package files without package revision' do
|
||||
expect(result).to contain_exactly(package_file_without_revision)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -364,13 +414,13 @@ RSpec.describe Packages::PackageFile, type: :model, feature_category: :package_r
|
|||
end
|
||||
|
||||
with_them do
|
||||
subject { described_class.where(package:).order_by(column_name, order) }
|
||||
subject(:ordered_files) { described_class.where(package:).order_by(column_name, order) }
|
||||
|
||||
it 'returns the package files in the expected order' do
|
||||
if expected_order
|
||||
expect(subject.first(2)).to eq(expected_order.call(older_file, newer_file))
|
||||
expect(ordered_files.first(2)).to eq(expected_order.call(older_file, newer_file))
|
||||
else
|
||||
expect(subject.order_values).to be_empty
|
||||
expect(ordered_files.order_values).to be_empty
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -386,17 +436,17 @@ RSpec.describe Packages::PackageFile, type: :model, feature_category: :package_r
|
|||
let(:extra_join) { :helm_file_metadatum }
|
||||
let(:extra_where) { { packages_helm_file_metadata: { channel: 'alpha' } } }
|
||||
|
||||
subject { described_class.most_recent_for(Packages::Package.id_in(helm_package.id), extra_join: extra_join, extra_where: extra_where) }
|
||||
subject(:joined_result) { described_class.most_recent_for(Packages::Package.id_in(helm_package.id), extra_join: extra_join, extra_where: extra_where) }
|
||||
|
||||
it 'returns the most recent package for the selected channel' do
|
||||
expect(subject).to contain_exactly(helm_package_file2)
|
||||
expect(joined_result).to contain_exactly(helm_package_file2)
|
||||
end
|
||||
|
||||
context 'with package files pending destruction' do
|
||||
let_it_be(:package_file_pending_destruction) { create(:helm_package_file, :pending_destruction, package: helm_package, channel: 'alpha') }
|
||||
|
||||
it 'does not return them' do
|
||||
expect(subject).to contain_exactly(helm_package_file2)
|
||||
expect(joined_result).to contain_exactly(helm_package_file2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -427,26 +477,26 @@ RSpec.describe Packages::PackageFile, type: :model, feature_category: :package_r
|
|||
describe '#update_file_store callback' do
|
||||
let_it_be(:package_file) { build(:package_file, :nuget, size: nil) }
|
||||
|
||||
subject { package_file.save! }
|
||||
subject(:save_result) { package_file.save! }
|
||||
|
||||
it 'updates metadata columns' do
|
||||
expect(package_file)
|
||||
.to receive(:update_file_store)
|
||||
.and_call_original
|
||||
|
||||
expect { subject }.to change { package_file.size }.from(nil).to(3513)
|
||||
expect { save_result }.to change { package_file.size }.from(nil).to(3513)
|
||||
end
|
||||
end
|
||||
|
||||
context 'update callbacks' do
|
||||
subject { package_file.save! }
|
||||
subject(:save_result) { package_file.save! }
|
||||
|
||||
shared_examples 'executing the default callback' do
|
||||
it 'executes the default callback' do
|
||||
expect(package_file).to receive(:remove_previously_stored_file)
|
||||
expect(package_file).not_to receive(:move_in_object_storage)
|
||||
|
||||
subject
|
||||
save_result
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -499,7 +549,7 @@ RSpec.describe Packages::PackageFile, type: :model, feature_category: :package_r
|
|||
expect(package_file.file.file).to receive(:copy_to).and_call_original
|
||||
expect(package_file.file.file).to receive(:delete).and_call_original
|
||||
|
||||
subject
|
||||
save_result
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -145,6 +145,56 @@ RSpec.describe API::Conan::V2::ProjectPackages, feature_category: :package_regis
|
|||
end
|
||||
end
|
||||
|
||||
describe 'GET /api/v4/projects/:id/packages/conan/v2/conans/:package_name/:package_version/:package_username/' \
|
||||
':package_channel/revisions/:recipe_revision/packages/:conan_package_reference/revisions/:package_revision/' \
|
||||
'files/:file_name' do
|
||||
include_context 'for conan file download endpoints'
|
||||
|
||||
let(:file_name) { package_file.file_name }
|
||||
let(:recipe_revision) { package_file_metadata.recipe_revision_value }
|
||||
let(:package_revision) { package_file_metadata.package_revision_value }
|
||||
let(:conan_package_reference) { package_file_metadata.package_reference_value }
|
||||
let(:url_suffix) do
|
||||
"#{recipe_path}/revisions/#{recipe_revision}/packages/#{conan_package_reference}/revisions/#{package_revision}/" \
|
||||
"files/#{file_name}"
|
||||
end
|
||||
|
||||
subject(:request) { get api(url), headers: headers }
|
||||
|
||||
it_behaves_like 'conan package revisions feature flag check'
|
||||
it_behaves_like 'packages feature check'
|
||||
it_behaves_like 'package file download endpoint'
|
||||
it_behaves_like 'accept get request on private project with access to package registry for everyone'
|
||||
it_behaves_like 'project not found by project id'
|
||||
|
||||
it_behaves_like 'enforcing job token policies', :read_packages,
|
||||
allow_public_access_for_enabled_project_features: :package_registry do
|
||||
let(:headers) { job_basic_auth_header(target_job) }
|
||||
end
|
||||
|
||||
describe 'parameter validation for package file endpoints' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:url_suffix) do
|
||||
"#{recipe_path}/revisions/#{recipe_revision}/packages/#{url_package_reference}/revisions/" \
|
||||
"#{url_package_revision}/files/#{url_file_name}"
|
||||
end
|
||||
|
||||
# rubocop:disable Layout/LineLength -- Avoid formatting to keep one-line table syntax
|
||||
where(:error, :url_package_reference, :url_package_revision, :url_file_name) do
|
||||
/conan_package_reference/ | 'invalid_package_reference$' | ref(:package_revision) | ref(:file_name)
|
||||
/package_revision/ | ref(:conan_package_reference) | 'invalid_package_revi$ion' | ref(:file_name)
|
||||
/package_revision/ | ref(:conan_package_reference) | Packages::Conan::FileMetadatum::DEFAULT_REVISION | ref(:file_name)
|
||||
/file_name/ | ref(:conan_package_reference) | ref(:package_revision) | 'invalid_file.txt'
|
||||
end
|
||||
# rubocop:enable Layout/LineLength
|
||||
|
||||
with_them do
|
||||
it_behaves_like 'returning response status with error', status: :bad_request, error: params[:error]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with file upload endpoints' do
|
||||
include_context 'for conan file upload endpoints'
|
||||
let(:file_name) { 'conanfile.py' }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'rubocop_spec_helper'
|
||||
require_relative '../../../../rubocop/cop/sidekiq/enforce_database_health_signal_deferral'
|
||||
|
||||
RSpec.describe RuboCop::Cop::Sidekiq::EnforceDatabaseHealthSignalDeferral, feature_category: :database do
|
||||
it 'adds an offense when worker has low urgency and does not defer to database health signal' do
|
||||
expect_offense(<<~RUBY)
|
||||
class SomeWorker
|
||||
^^^^^^^^^^^^^^^^ Low urgency workers should have the option to be deferred based on the database health [...]
|
||||
include ApplicationWorker
|
||||
|
||||
urgency :low
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it 'adds no offense when worker has low urgency and defer to database health signal' do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class SomeWorker
|
||||
include ApplicationWorker
|
||||
|
||||
urgency :low
|
||||
defer_on_database_health_signal :gitlab_main, [:my_table], 1.minute
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
it 'adds no offense when worker urgency is other than low' do
|
||||
expect_no_offenses(<<~RUBY)
|
||||
class SomeWorker
|
||||
include ApplicationWorker
|
||||
|
||||
urgency :high
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,127 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Clusters::Agents::ManagedResources::DeleteService, feature_category: :deployment_management do
|
||||
let_it_be_with_reload(:managed_resource) { create(:managed_resource, status: :deleting) }
|
||||
|
||||
describe '#execute' do
|
||||
let(:kas_client) { instance_double(Gitlab::Kas::Client) }
|
||||
|
||||
subject(:execute) { described_class.new(managed_resource).execute }
|
||||
|
||||
before do
|
||||
allow(Gitlab::Kas::Client).to receive(:new).and_return(kas_client)
|
||||
end
|
||||
|
||||
context 'when the managed resource is not in the correct initial state' do
|
||||
before do
|
||||
managed_resource.update!(status: :completed)
|
||||
end
|
||||
|
||||
it 'does not delete resources' do
|
||||
expect(kas_client).not_to receive(:delete_environment)
|
||||
|
||||
execute
|
||||
|
||||
expect(managed_resource.status).to eq('completed')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when KAS returns an error' do
|
||||
let(:attempt_count) { 1 }
|
||||
let(:kas_response) do
|
||||
Gitlab::Agent::ManagedResources::Rpc::DeleteEnvironmentResponse.new(
|
||||
errors: [Gitlab::Agent::ManagedResources::Rpc::ObjectError.new(error: 'error message', object: {})],
|
||||
in_progress: []
|
||||
)
|
||||
end
|
||||
|
||||
before do
|
||||
allow(kas_client).to receive(:delete_environment).with(managed_resource: managed_resource)
|
||||
.and_return(kas_response)
|
||||
end
|
||||
|
||||
it 'queues a worker for the next deletion attempt' do
|
||||
expect(Clusters::Agents::ManagedResources::DeleteWorker).to receive(:perform_in)
|
||||
.with(described_class::POLLING_SCHEDULE.first, managed_resource.id, attempt_count)
|
||||
.and_call_original
|
||||
|
||||
execute
|
||||
|
||||
expect(managed_resource.status).to eq('deleting')
|
||||
end
|
||||
end
|
||||
|
||||
context 'when all resources are deleted' do
|
||||
let(:kas_response) do
|
||||
Gitlab::Agent::ManagedResources::Rpc::DeleteEnvironmentResponse.new(
|
||||
errors: [],
|
||||
in_progress: []
|
||||
)
|
||||
end
|
||||
|
||||
it 'sets the status to deleted' do
|
||||
expect(kas_client).to receive(:delete_environment).with(managed_resource: managed_resource)
|
||||
.and_return(kas_response)
|
||||
|
||||
execute
|
||||
|
||||
expect(managed_resource.status).to eq('deleted')
|
||||
expect(managed_resource.tracked_objects).to be_empty
|
||||
end
|
||||
end
|
||||
|
||||
context 'when deletion is still in progress' do
|
||||
let(:attempt_count) { 1 }
|
||||
let(:in_progress_object) do
|
||||
{
|
||||
kind: 'Namespace',
|
||||
name: 'production',
|
||||
group: '',
|
||||
version: 'v1',
|
||||
namespace: ''
|
||||
}.stringify_keys
|
||||
end
|
||||
|
||||
let(:kas_response) do
|
||||
Gitlab::Agent::ManagedResources::Rpc::DeleteEnvironmentResponse.new(
|
||||
errors: [],
|
||||
in_progress: [Gitlab::Agent::ManagedResources::Rpc::Object.new(**in_progress_object)]
|
||||
)
|
||||
end
|
||||
|
||||
it 'queues a worker for the next deletion attempt' do
|
||||
expect(kas_client).to receive(:delete_environment).with(managed_resource: managed_resource)
|
||||
.and_return(kas_response)
|
||||
|
||||
expect(Clusters::Agents::ManagedResources::DeleteWorker).to receive(:perform_in)
|
||||
.with(described_class::POLLING_SCHEDULE.first, managed_resource.id, attempt_count)
|
||||
.and_call_original
|
||||
|
||||
execute
|
||||
|
||||
expect(managed_resource.status).to eq('deleting')
|
||||
expect(managed_resource.tracked_objects).to contain_exactly(in_progress_object)
|
||||
end
|
||||
|
||||
context 'when the attempt limit is reached' do
|
||||
let(:attempt_count) { described_class::POLLING_SCHEDULE.length }
|
||||
|
||||
subject(:execute) { described_class.new(managed_resource, attempt_count: attempt_count).execute }
|
||||
|
||||
it 'sets the status to delete_failed' do
|
||||
expect(kas_client).to receive(:delete_environment).with(managed_resource: managed_resource)
|
||||
.and_return(kas_response)
|
||||
|
||||
expect(Clusters::Agents::ManagedResources::DeleteWorker).not_to receive(:perform_in)
|
||||
|
||||
execute
|
||||
|
||||
expect(managed_resource.status).to eq('delete_failed')
|
||||
expect(managed_resource.tracked_objects).to contain_exactly(in_progress_object)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,82 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Environments::DeleteManagedResourcesService, feature_category: :deployment_management do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:environment) { create(:environment, :stopped, project: project) }
|
||||
let_it_be(:agent) { create(:cluster_agent, project: project) }
|
||||
let_it_be(:build) { create(:ci_build, project: project) }
|
||||
|
||||
let!(:managed_resource) do
|
||||
create(:managed_resource, :completed, project: project, environment: environment, cluster_agent: agent,
|
||||
build: build)
|
||||
end
|
||||
|
||||
before do
|
||||
allow_next_found_instance_of(Clusters::Agent) do |agent|
|
||||
allow(agent).to receive(:resource_management_enabled?).and_return(true)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
subject(:execute) { described_class.new(environment).execute }
|
||||
|
||||
it 'sets the status to :deleting and queues the deletion worker' do
|
||||
expect(Clusters::Agents::ManagedResources::DeleteWorker).to receive(:perform_async)
|
||||
.with(managed_resource.id).once.and_call_original
|
||||
|
||||
expect(execute.status).to eq(:success)
|
||||
expect(managed_resource.reload.status).to eq('deleting')
|
||||
end
|
||||
|
||||
shared_examples 'resources can not be deleted' do
|
||||
it 'does not attempt to delete resources' do
|
||||
expect(Clusters::Agents::ManagedResources::DeleteWorker).not_to receive(:perform_async)
|
||||
expect(execute).to be_nil
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the environment is not stopped' do
|
||||
before do
|
||||
environment.update!(state: :available)
|
||||
end
|
||||
|
||||
it_behaves_like 'resources can not be deleted'
|
||||
end
|
||||
|
||||
context 'when there is no associated managed resource' do
|
||||
before do
|
||||
managed_resource.destroy!
|
||||
end
|
||||
|
||||
it_behaves_like 'resources can not be deleted'
|
||||
end
|
||||
|
||||
context 'when the managed resource is not in the correct state' do
|
||||
before do
|
||||
managed_resource.update!(status: :failed)
|
||||
end
|
||||
|
||||
it_behaves_like 'resources can not be deleted'
|
||||
end
|
||||
|
||||
context 'when resource management is disabled' do
|
||||
before do
|
||||
allow_next_found_instance_of(Clusters::Agent) do |agent|
|
||||
allow(agent).to receive(:resource_management_enabled?).and_return(false)
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'resources can not be deleted'
|
||||
end
|
||||
|
||||
context 'when the deletion strategy is not on_stop' do
|
||||
before do
|
||||
managed_resource.update!(deletion_strategy: :never)
|
||||
end
|
||||
|
||||
it_behaves_like 'resources can not be deleted'
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -24,6 +24,14 @@ RSpec.describe Environments::StopService, feature_category: :continuous_delivery
|
|||
review_job.success!
|
||||
end
|
||||
|
||||
it 'calls the managed resource deletion service' do
|
||||
expect_next_instance_of(Environments::DeleteManagedResourcesService, environment) do |service|
|
||||
expect(service).to receive(:execute).and_call_original
|
||||
end
|
||||
|
||||
subject
|
||||
end
|
||||
|
||||
context 'without stop action' do
|
||||
let!(:environment) { create(:environment, :available, project: project) }
|
||||
|
||||
|
|
|
|||
|
|
@ -55,8 +55,10 @@ module LoginHelpers
|
|||
click_button Gitlab::Auth::OAuth::Provider.label_for(provider)
|
||||
end
|
||||
|
||||
def gitlab_enable_admin_mode_sign_in_via(provider, user, uid, saml_response = nil)
|
||||
mock_auth_hash_with_saml_xml(provider, uid, user.email, saml_response)
|
||||
def gitlab_enable_admin_mode_sign_in_via(provider, user, uid, saml_response: nil, additional_info: {})
|
||||
response_object = { document: saml_xml(saml_response) } if saml_response.present?
|
||||
mock_auth_hash(provider, uid, user.email, response_object: response_object, additional_info: additional_info)
|
||||
|
||||
visit new_admin_session_path
|
||||
click_button Gitlab::Auth::OAuth::Provider.label_for(provider)
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,49 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Clusters::Agents::ManagedResources::DeleteWorker, feature_category: :deployment_management do
|
||||
let_it_be(:managed_resource) { create(:managed_resource) }
|
||||
|
||||
it_behaves_like 'an idempotent worker' do
|
||||
let(:job_args) { managed_resource.id }
|
||||
end
|
||||
|
||||
describe '#perform' do
|
||||
let(:managed_resource_id) { managed_resource.id }
|
||||
|
||||
subject(:perform) { described_class.new.perform(managed_resource_id) }
|
||||
|
||||
it 'calls the deletion service' do
|
||||
expect_next_instance_of(Clusters::Agents::ManagedResources::DeleteService, managed_resource,
|
||||
attempt_count: nil) do |service|
|
||||
expect(service).to receive(:execute).once
|
||||
end
|
||||
|
||||
perform
|
||||
end
|
||||
|
||||
context 'when an attempt number is provided' do
|
||||
let(:attempt) { 123 }
|
||||
|
||||
subject(:perform) { described_class.new.perform(managed_resource_id, attempt) }
|
||||
|
||||
it 'calls the deletion service with the supplied attempt number' do
|
||||
expect_next_instance_of(Clusters::Agents::ManagedResources::DeleteService, managed_resource,
|
||||
attempt_count: attempt) do |service|
|
||||
expect(service).to receive(:execute).once
|
||||
end
|
||||
|
||||
perform
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the managed resource record no longer exists' do
|
||||
let(:managed_resource_id) { non_existing_record_id }
|
||||
|
||||
it 'completes without raising an error' do
|
||||
expect { perform }.not_to raise_error
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -15035,10 +15035,10 @@ vite-plugin-ruby@^5.1.1:
|
|||
debug "^4.3.4"
|
||||
fast-glob "^3.3.2"
|
||||
|
||||
vite@^6.3.0:
|
||||
version "6.3.0"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-6.3.0.tgz#17c86b3a0f4d20b210fe89f22f7b27d5926fcce5"
|
||||
integrity sha512-9aC0n4pr6hIbvi1YOpFjwQ+QOTGssvbJKoeYkuHHGWwlXfdxQlI8L2qNMo9awEEcCPSiS+5mJZk5jH1PAqoDeQ==
|
||||
vite@^6.3.1:
|
||||
version "6.3.1"
|
||||
resolved "https://registry.yarnpkg.com/vite/-/vite-6.3.1.tgz#6b080ff907308ca691c5639c095ab6d938734c0d"
|
||||
integrity sha512-kkzzkqtMESYklo96HKKPE5KKLkC1amlsqt+RjFMlX2AvbRB/0wghap19NdBxxwGZ+h/C6DLCrcEphPIItlGrRQ==
|
||||
dependencies:
|
||||
esbuild "^0.25.0"
|
||||
fdir "^6.4.3"
|
||||
|
|
|
|||
Loading…
Reference in New Issue