Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
44d4b37b52
commit
7c41737ae5
|
@ -308,10 +308,18 @@ Rails/RakeEnvironment:
|
||||||
# Context on why it's disabled: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93419#note_1048223982
|
# Context on why it's disabled: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/93419#note_1048223982
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/94064#note_1157289970
|
||||||
|
Rails/SquishedSQLHeredocs:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96675#note_1094403693
|
# See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96675#note_1094403693
|
||||||
Rails/WhereExists:
|
Rails/WhereExists:
|
||||||
Enabled: false
|
Enabled: false
|
||||||
|
|
||||||
|
# See https://gitlab.com/gitlab-org/gitlab/-/issues/378105#note_1138487716
|
||||||
|
Rails/HasManyOrHasOneDependent:
|
||||||
|
Enabled: false
|
||||||
|
|
||||||
# GitLab ###################################################################
|
# GitLab ###################################################################
|
||||||
|
|
||||||
Gitlab/ModuleWithInstanceVariables:
|
Gitlab/ModuleWithInstanceVariables:
|
||||||
|
|
|
@ -1,154 +0,0 @@
|
||||||
---
|
|
||||||
Rails/HasManyOrHasOneDependent:
|
|
||||||
# Offense count: 593
|
|
||||||
# Temporarily disabled due to too many offenses
|
|
||||||
Enabled: false
|
|
||||||
Exclude:
|
|
||||||
- 'app/models/alert_management/alert.rb'
|
|
||||||
- 'app/models/analytics/cycle_analytics/project_value_stream.rb'
|
|
||||||
- 'app/models/analytics/cycle_analytics/stage_event_hash.rb'
|
|
||||||
- 'app/models/application_setting/term.rb'
|
|
||||||
- 'app/models/bulk_import.rb'
|
|
||||||
- 'app/models/bulk_imports/entity.rb'
|
|
||||||
- 'app/models/bulk_imports/export.rb'
|
|
||||||
- 'app/models/ci/bridge.rb'
|
|
||||||
- 'app/models/ci/build.rb'
|
|
||||||
- 'app/models/ci/pipeline.rb'
|
|
||||||
- 'app/models/ci/pipeline_schedule.rb'
|
|
||||||
- 'app/models/ci/processable.rb'
|
|
||||||
- 'app/models/ci/ref.rb'
|
|
||||||
- 'app/models/ci/resource_group.rb'
|
|
||||||
- 'app/models/ci/runner.rb'
|
|
||||||
- 'app/models/ci/stage.rb'
|
|
||||||
- 'app/models/ci/trigger.rb'
|
|
||||||
- 'app/models/ci/trigger_request.rb'
|
|
||||||
- 'app/models/ci/unit_test.rb'
|
|
||||||
- 'app/models/clusters/agent.rb'
|
|
||||||
- 'app/models/clusters/applications/knative.rb'
|
|
||||||
- 'app/models/clusters/cluster.rb'
|
|
||||||
- 'app/models/clusters/project.rb'
|
|
||||||
- 'app/models/commit_status.rb'
|
|
||||||
- 'app/models/concerns/ci/metadatable.rb'
|
|
||||||
- 'app/models/concerns/integrations/has_data_fields.rb'
|
|
||||||
- 'app/models/concerns/issuable.rb'
|
|
||||||
- 'app/models/concerns/label_eventable.rb'
|
|
||||||
- 'app/models/concerns/milestone_eventable.rb'
|
|
||||||
- 'app/models/concerns/packages/debian/distribution.rb'
|
|
||||||
- 'app/models/concerns/protected_ref.rb'
|
|
||||||
- 'app/models/concerns/state_eventable.rb'
|
|
||||||
- 'app/models/concerns/timebox.rb'
|
|
||||||
- 'app/models/concerns/versioned_description.rb'
|
|
||||||
- 'app/models/concerns/with_uploads.rb'
|
|
||||||
- 'app/models/customer_relations/contact.rb'
|
|
||||||
- 'app/models/deploy_key.rb'
|
|
||||||
- 'app/models/deploy_token.rb'
|
|
||||||
- 'app/models/deployment.rb'
|
|
||||||
- 'app/models/design_management/design.rb'
|
|
||||||
- 'app/models/design_management/version.rb'
|
|
||||||
- 'app/models/environment.rb'
|
|
||||||
- 'app/models/error_tracking/error.rb'
|
|
||||||
- 'app/models/event.rb'
|
|
||||||
- 'app/models/experiment.rb'
|
|
||||||
- 'app/models/fork_network.rb'
|
|
||||||
- 'app/models/gpg_key.rb'
|
|
||||||
- 'app/models/group.rb'
|
|
||||||
- 'app/models/hooks/web_hook.rb'
|
|
||||||
- 'app/models/integration.rb'
|
|
||||||
- 'app/models/issue.rb'
|
|
||||||
- 'app/models/jira_connect_installation.rb'
|
|
||||||
- 'app/models/label.rb'
|
|
||||||
- 'app/models/lfs_object.rb'
|
|
||||||
- 'app/models/list.rb'
|
|
||||||
- 'app/models/member.rb'
|
|
||||||
- 'app/models/merge_request.rb'
|
|
||||||
- 'app/models/merge_request_context_commit.rb'
|
|
||||||
- 'app/models/milestone.rb'
|
|
||||||
- 'app/models/namespace.rb'
|
|
||||||
- 'app/models/namespaces/project_namespace.rb'
|
|
||||||
- 'app/models/note.rb'
|
|
||||||
- 'app/models/operations/feature_flag.rb'
|
|
||||||
- 'app/models/operations/feature_flags/strategy.rb'
|
|
||||||
- 'app/models/operations/feature_flags/user_list.rb'
|
|
||||||
- 'app/models/packages/debian/project_distribution.rb'
|
|
||||||
- 'app/models/packages/dependency.rb'
|
|
||||||
- 'app/models/packages/dependency_link.rb'
|
|
||||||
- 'app/models/packages/package.rb'
|
|
||||||
- 'app/models/packages/package_file.rb'
|
|
||||||
- 'app/models/pages_domain.rb'
|
|
||||||
- 'app/models/plan.rb'
|
|
||||||
- 'app/models/pool_repository.rb'
|
|
||||||
- 'app/models/project.rb'
|
|
||||||
- 'app/models/projects/topic.rb'
|
|
||||||
- 'app/models/prometheus_alert.rb'
|
|
||||||
- 'app/models/prometheus_metric.rb'
|
|
||||||
- 'app/models/release.rb'
|
|
||||||
- 'app/models/snippet.rb'
|
|
||||||
- 'app/models/terraform/state.rb'
|
|
||||||
- 'app/models/user.rb'
|
|
||||||
- 'app/models/wiki_page/meta.rb'
|
|
||||||
- 'app/models/work_items/type.rb'
|
|
||||||
- 'app/models/x509_certificate.rb'
|
|
||||||
- 'app/models/x509_issuer.rb'
|
|
||||||
- 'ee/app/models/analytics/devops_adoption/enabled_namespace.rb'
|
|
||||||
- 'ee/app/models/analytics/devops_adoption/snapshot.rb'
|
|
||||||
- 'ee/app/models/approval_merge_request_rule.rb'
|
|
||||||
- 'ee/app/models/approval_project_rule.rb'
|
|
||||||
- 'ee/app/models/boards/epic_board.rb'
|
|
||||||
- 'ee/app/models/boards/epic_list.rb'
|
|
||||||
- 'ee/app/models/compliance_management/framework.rb'
|
|
||||||
- 'ee/app/models/concerns/ee/iteration_eventable.rb'
|
|
||||||
- 'ee/app/models/concerns/ee/protected_branch.rb'
|
|
||||||
- 'ee/app/models/concerns/ee/protected_ref.rb'
|
|
||||||
- 'ee/app/models/concerns/ee/weight_eventable.rb'
|
|
||||||
- 'ee/app/models/concerns/geo/eventable.rb'
|
|
||||||
- 'ee/app/models/concerns/issue_widgets/acts_like_requirement.rb'
|
|
||||||
- 'ee/app/models/concerns/security/scan_execution_policy.rb'
|
|
||||||
- 'ee/app/models/dast/profile.rb'
|
|
||||||
- 'ee/app/models/dast_site.rb'
|
|
||||||
- 'ee/app/models/dast_site_profile.rb'
|
|
||||||
- 'ee/app/models/dast_site_validation.rb'
|
|
||||||
- 'ee/app/models/ee/alert_management/alert.rb'
|
|
||||||
- 'ee/app/models/ee/analytics/cycle_analytics/stage_event_hash.rb'
|
|
||||||
- 'ee/app/models/ee/board.rb'
|
|
||||||
- 'ee/app/models/ee/ci/build.rb'
|
|
||||||
- 'ee/app/models/ee/ci/job_artifact.rb'
|
|
||||||
- 'ee/app/models/ee/ci/pipeline.rb'
|
|
||||||
- 'ee/app/models/ee/deployment.rb'
|
|
||||||
- 'ee/app/models/ee/environment.rb'
|
|
||||||
- 'ee/app/models/ee/epic.rb'
|
|
||||||
- 'ee/app/models/ee/group.rb'
|
|
||||||
- 'ee/app/models/ee/issue.rb'
|
|
||||||
- 'ee/app/models/ee/iteration.rb'
|
|
||||||
- 'ee/app/models/ee/label.rb'
|
|
||||||
- 'ee/app/models/ee/lfs_object.rb'
|
|
||||||
- 'ee/app/models/ee/merge_request.rb'
|
|
||||||
- 'ee/app/models/ee/merge_request_diff.rb'
|
|
||||||
- 'ee/app/models/ee/milestone.rb'
|
|
||||||
- 'ee/app/models/ee/namespace.rb'
|
|
||||||
- 'ee/app/models/ee/pages_deployment.rb'
|
|
||||||
- 'ee/app/models/ee/plan.rb'
|
|
||||||
- 'ee/app/models/ee/project.rb'
|
|
||||||
- 'ee/app/models/ee/upload.rb'
|
|
||||||
- 'ee/app/models/ee/user.rb'
|
|
||||||
- 'ee/app/models/ee/vulnerability.rb'
|
|
||||||
- 'ee/app/models/elastic/reindexing_subtask.rb'
|
|
||||||
- 'ee/app/models/elastic/reindexing_task.rb'
|
|
||||||
- 'ee/app/models/geo/event.rb'
|
|
||||||
- 'ee/app/models/geo_node.rb'
|
|
||||||
- 'ee/app/models/incident_management/escalation_policy.rb'
|
|
||||||
- 'ee/app/models/incident_management/oncall_participant.rb'
|
|
||||||
- 'ee/app/models/incident_management/oncall_rotation.rb'
|
|
||||||
- 'ee/app/models/incident_management/oncall_schedule.rb'
|
|
||||||
- 'ee/app/models/integrations/gitlab_slack_application.rb'
|
|
||||||
- 'ee/app/models/iterations/cadence.rb'
|
|
||||||
- 'ee/app/models/protected_environment.rb'
|
|
||||||
- 'ee/app/models/protected_environments/approval_rule.rb'
|
|
||||||
- 'ee/app/models/push_rule.rb'
|
|
||||||
- 'ee/app/models/saml_provider.rb'
|
|
||||||
- 'ee/app/models/security/finding.rb'
|
|
||||||
- 'ee/app/models/security/scan.rb'
|
|
||||||
- 'ee/app/models/security/training_provider.rb'
|
|
||||||
- 'ee/app/models/vulnerabilities/finding.rb'
|
|
||||||
- 'ee/app/models/vulnerabilities/identifier.rb'
|
|
||||||
- 'ee/app/models/vulnerabilities/remediation.rb'
|
|
||||||
- 'ee/app/models/vulnerabilities/scanner.rb'
|
|
|
@ -1,215 +0,0 @@
|
||||||
---
|
|
||||||
# Cop supports --auto-correct.
|
|
||||||
Rails/SquishedSQLHeredocs:
|
|
||||||
# Offense count: 356
|
|
||||||
# Temporarily disabled due to too many offenses
|
|
||||||
Enabled: false
|
|
||||||
Exclude:
|
|
||||||
- 'app/finders/members_finder.rb'
|
|
||||||
- 'app/models/analytics/cycle_analytics/stage_event_hash.rb'
|
|
||||||
- 'app/models/ci/resource_group.rb'
|
|
||||||
- 'app/models/clusters/clusters_hierarchy.rb'
|
|
||||||
- 'app/models/concerns/analytics/cycle_analytics/stage_event_model.rb'
|
|
||||||
- 'app/models/concerns/has_environment_scope.rb'
|
|
||||||
- 'app/models/customer_relations/contact.rb'
|
|
||||||
- 'app/models/customer_relations/organization.rb'
|
|
||||||
- 'app/models/deployment.rb'
|
|
||||||
- 'app/models/issue/metrics.rb'
|
|
||||||
- 'app/models/merge_request/metrics.rb'
|
|
||||||
- 'app/models/namespace/traversal_hierarchy.rb'
|
|
||||||
- 'app/models/namespaces/traversal/linear.rb'
|
|
||||||
- 'app/models/project.rb'
|
|
||||||
- 'app/models/user.rb'
|
|
||||||
- 'app/services/issuable/destroy_label_links_service.rb'
|
|
||||||
- 'app/services/issues/relative_position_rebalancing_service.rb'
|
|
||||||
- 'app/services/projects/fetch_statistics_increment_service.rb'
|
|
||||||
- 'app/services/todos/destroy/destroyed_issuable_service.rb'
|
|
||||||
- 'app/workers/users/deactivate_dormant_users_worker.rb'
|
|
||||||
- 'db/migrate/20210323155010_populate_dismissal_information_for_vulnerabilities.rb'
|
|
||||||
- 'db/migrate/20210601080039_group_protected_environments_add_index_and_constraint.rb'
|
|
||||||
- 'db/migrate/20210611100359_rebuild_index_for_cadence_iterations_automation.rb'
|
|
||||||
- 'db/migrate/20210617022324_create_incident_management_pending_alert_escalations.rb'
|
|
||||||
- 'db/migrate/20210621043337_rename_services_to_integrations.rb'
|
|
||||||
- 'db/migrate/20210621044000_rename_services_indexes_to_integrations.rb'
|
|
||||||
- 'db/migrate/20210706152139_add_index_type_to_postgres_indexes_view.rb'
|
|
||||||
- 'db/migrate/20210719145532_add_foreign_keys_view.rb'
|
|
||||||
- 'db/migrate/20210721135638_add_triggers_to_integrations_type_new.rb'
|
|
||||||
- 'db/migrate/20210721174453_remove_schedule_and_status_null_constraints_from_pending_escalations_alert.rb'
|
|
||||||
- 'db/migrate/20210722150102_operations_feature_flags_correct_flexible_rollout_values.rb'
|
|
||||||
- 'db/migrate/20210730194555_create_incident_management_pending_issue_escalations.rb'
|
|
||||||
- 'db/migrate/20210818175949_update_integrations_trigger_type_new_on_insert.rb'
|
|
||||||
- 'db/migrate/20210825104656_create_analytics_cycle_analytics_merge_request_stage_events.rb'
|
|
||||||
- 'db/migrate/20210825110016_create_analytics_cycle_analytics_issue_stage_events.rb'
|
|
||||||
- 'db/migrate/20210826122748_create_loose_foreign_keys_deleted_records.rb'
|
|
||||||
- 'db/migrate/20210826145509_add_function_for_inserting_deleted_records.rb'
|
|
||||||
- 'db/migrate/20210903054158_recreate_stage_issue_events_table_with_bigints.rb'
|
|
||||||
- 'db/migrate/20210906100021_delete_project_namespace_trigger.rb'
|
|
||||||
- 'db/migrate/20210929032555_create_verification_codes.rb'
|
|
||||||
- 'db/migrate/20211005092428_drop_time_range_partitioned_loose_fk.rb'
|
|
||||||
- 'db/migrate/20211005093558_add_range_partitioned_loose_fk_table.rb'
|
|
||||||
- 'db/migrate/20211005100112_recreate_loose_fk_insert_function.rb'
|
|
||||||
- 'db/migrate/20211007090229_create_issue_search_table.rb'
|
|
||||||
- 'db/migrate/20211011141242_create_namespaces_sync_trigger.rb'
|
|
||||||
- 'db/migrate/20211011141243_create_projects_sync_trigger.rb'
|
|
||||||
- 'db/migrate/20211012015903_next_traversal_ids_sibling_function.rb'
|
|
||||||
- 'db/migrate/20211018161447_fix_double_entries_in_postgres_index_view.rb'
|
|
||||||
- 'db/migrate/20211112155416_populate_default_value_for_personal_access_tokens_prefix.rb'
|
|
||||||
- 'db/migrate/20211118103439_remove_hardcoded_partition_from_loose_fk_trigger_function.rb'
|
|
||||||
- 'db/migrate/20211123135255_create_batched_background_migration_job_transition_logs.rb'
|
|
||||||
- 'db/migrate/20220106111958_add_insert_or_update_vulnerability_reads_trigger.rb'
|
|
||||||
- 'db/migrate/20220106112043_add_update_vulnerability_reads_trigger.rb'
|
|
||||||
- 'db/migrate/20220106112085_add_update_vulnerability_reads_location_trigger.rb'
|
|
||||||
- 'db/migrate/20220106163326_add_has_issues_on_vulnerability_reads_trigger.rb'
|
|
||||||
- 'db/migrate/20220208171826_update_default_scan_method_of_dast_site_profile.rb'
|
|
||||||
- 'db/migrate/20220211214605_update_integrations_trigger_type_new_on_insert_null_safe.rb'
|
|
||||||
- 'db/migrate/20220213100000_remove_integration_type_triggers.rb'
|
|
||||||
- 'db/migrate/20220304052335_remove_not_null_contraint_on_title_from_sprints.rb'
|
|
||||||
- 'db/migrate/20220321234317_remove_all_issuable_escalation_statuses.rb'
|
|
||||||
- 'db/migrate/20220329110630_add_ci_namespace_mirrors_unnest_index_on_traversal_ids.rb'
|
|
||||||
- 'db/migrate/20220412060931_add_nullify_build_data_trigger_on_merge_request_metrics.rb'
|
|
||||||
- 'db/migrate/20220413124200_add_view_for_per_table_autovacuum_status.rb'
|
|
||||||
- 'db/migrate/20220415015143_replace_iterations_cadence_date_range_constraint.rb'
|
|
||||||
- 'db/migrate/20220422200633_fix_view_for_per_table_autovacuum_status.rb'
|
|
||||||
- 'db/migrate/20220422220507_remove_tmp_index_supporting_leaky_regex_cleanup.rb'
|
|
||||||
- 'db/post_migrate/20210302074524_backfill_namespace_statistics_with_wiki_size.rb'
|
|
||||||
- 'db/post_migrate/20210311045138_set_traversal_ids_for_gitlab_org_group_staging.rb'
|
|
||||||
- 'db/post_migrate/20210311045139_set_traversal_ids_for_gitlab_org_group_com.rb'
|
|
||||||
- 'db/post_migrate/20210311093723_add_partial_index_on_ci_pipelines_by_cancelable_status_and_users.rb'
|
|
||||||
- 'db/post_migrate/20210317104032_set_iteration_cadence_automatic_to_false.rb'
|
|
||||||
- 'db/post_migrate/20210331105335_drop_non_partitioned_audit_events.rb'
|
|
||||||
- 'db/post_migrate/20210430134202_copy_adoption_snapshot_namespace.rb'
|
|
||||||
- 'db/post_migrate/20210430135954_copy_adoption_segments_namespace.rb'
|
|
||||||
- 'db/post_migrate/20210525075724_clean_up_pending_builds_table.rb'
|
|
||||||
- 'db/post_migrate/20210609125005_drop_non_partitioned_web_hook_logs.rb'
|
|
||||||
- 'db/post_migrate/20210610102413_migrate_protected_attribute_to_pending_builds.rb'
|
|
||||||
- 'db/post_migrate/20210610141711_disable_expiration_policies_linked_to_no_container_images.rb'
|
|
||||||
- 'db/post_migrate/20210708011426_finalize_ci_builds_metadata_bigint_conversion.rb'
|
|
||||||
- 'db/post_migrate/20210721174521_add_non_null_constraint_for_escalation_rule_on_pending_alert_escalations.rb'
|
|
||||||
- 'db/post_migrate/20210812013042_remove_duplicate_project_authorizations.rb'
|
|
||||||
- 'db/post_migrate/20210907211557_finalize_ci_builds_bigint_conversion.rb'
|
|
||||||
- 'db/post_migrate/20210910194952_update_report_type_for_existing_approval_project_rules.rb'
|
|
||||||
- 'db/post_migrate/20211105135157_drop_ci_build_trace_sections.rb'
|
|
||||||
- 'db/post_migrate/20211112113300_remove_ci_pipeline_chat_data_fk_on_chat_names.rb'
|
|
||||||
- 'db/post_migrate/20211130165043_backfill_sequence_column_for_sprints_table.rb'
|
|
||||||
- 'db/post_migrate/20211206161271_add_indexes_for_primary_email_cleanup_migration.rb'
|
|
||||||
- 'db/post_migrate/20211220064757_drop_temporary_indexes_for_primary_email_migration.rb'
|
|
||||||
- 'db/post_migrate/20220128155251_remove_dangling_running_builds.rb'
|
|
||||||
- 'db/post_migrate/20220204095121_backfill_namespace_statistics_with_dependency_proxy_size.rb'
|
|
||||||
- 'db/post_migrate/20220204110725_backfill_cycle_analytics_aggregations.rb'
|
|
||||||
- 'db/post_migrate/20220213103859_remove_integrations_type.rb'
|
|
||||||
- 'db/post_migrate/20220309084954_remove_leftover_external_pull_request_deletions.rb'
|
|
||||||
- 'db/post_migrate/20220318111040_add_indexes_for_primary_email_second_cleanup_migration.rb'
|
|
||||||
- 'db/post_migrate/20220318111949_drop_temporary_indexes_for_primary_email_migration_second_cleanup.rb'
|
|
||||||
- 'db/post_migrate/20220329175119_remove_leftover_ci_job_artifact_deletions.rb'
|
|
||||||
- 'db/post_migrate/20220420135946_update_batched_background_migration_arguments.rb'
|
|
||||||
- 'ee/app/models/dora/daily_metrics.rb'
|
|
||||||
- 'ee/app/models/ee/group.rb'
|
|
||||||
- 'ee/app/models/ee/issue.rb'
|
|
||||||
- 'ee/app/models/iterations/cadence.rb'
|
|
||||||
- 'ee/app/models/vulnerabilities/statistic.rb'
|
|
||||||
- 'ee/app/services/analytics/cycle_analytics/consistency_check_service.rb'
|
|
||||||
- 'ee/app/services/security/ingestion/tasks/ingest_vulnerability_statistics.rb'
|
|
||||||
- 'ee/app/services/vulnerabilities/historical_statistics/adjustment_service.rb'
|
|
||||||
- 'ee/app/services/vulnerabilities/statistics/adjustment_service.rb'
|
|
||||||
- 'ee/app/services/vulnerabilities/statistics/update_service.rb'
|
|
||||||
- 'ee/db/geo/migrate/20170906174622_remove_duplicates_from_project_registry.rb'
|
|
||||||
- 'ee/db/geo/migrate/20180510223634_set_resync_flag_for_retried_projects.rb'
|
|
||||||
- 'ee/db/geo/post_migrate/20210217020154_add_unique_index_on_container_repository_registry.rb'
|
|
||||||
- 'ee/db/geo/post_migrate/20210217020156_add_unique_index_on_terraform_state_version_registry.rb'
|
|
||||||
- 'ee/lib/ee/gitlab/background_migration/backfill_iteration_cadence_id_for_boards.rb'
|
|
||||||
- 'ee/lib/ee/gitlab/background_migration/create_security_setting.rb'
|
|
||||||
- 'ee/lib/ee/gitlab/background_migration/populate_latest_pipeline_ids.rb'
|
|
||||||
- 'ee/lib/ee/gitlab/background_migration/populate_resolved_on_default_branch_column.rb'
|
|
||||||
- 'ee/lib/ee/gitlab/background_migration/populate_status_column_of_security_scans.rb'
|
|
||||||
- 'ee/lib/ee/gitlab/background_migration/populate_test_reports_issue_id.rb'
|
|
||||||
- 'ee/lib/ee/gitlab/background_migration/update_vulnerability_occurrences_location.rb'
|
|
||||||
- 'ee/lib/ee/gitlab/usage_data.rb'
|
|
||||||
- 'ee/lib/gitlab/geo/base_batcher.rb'
|
|
||||||
- 'ee/spec/models/ee/user_spec.rb'
|
|
||||||
- 'lib/gitlab/background_migration/backfill_ci_namespace_mirrors.rb'
|
|
||||||
- 'lib/gitlab/background_migration/backfill_ci_project_mirrors.rb'
|
|
||||||
- 'lib/gitlab/background_migration/backfill_group_features.rb'
|
|
||||||
- 'lib/gitlab/background_migration/backfill_integrations_type_new.rb'
|
|
||||||
- 'lib/gitlab/background_migration/backfill_issue_search_data.rb'
|
|
||||||
- 'lib/gitlab/background_migration/backfill_namespace_id_for_project_route.rb'
|
|
||||||
- 'lib/gitlab/background_migration/backfill_namespace_traversal_ids_children.rb'
|
|
||||||
- 'lib/gitlab/background_migration/backfill_project_settings.rb'
|
|
||||||
- 'lib/gitlab/background_migration/backfill_projects_with_coverage.rb'
|
|
||||||
- 'lib/gitlab/background_migration/backfill_upvotes_count_on_issues.rb'
|
|
||||||
- 'lib/gitlab/background_migration/disable_expiration_policies_linked_to_no_container_images.rb'
|
|
||||||
- 'lib/gitlab/background_migration/encrypt_static_object_token.rb'
|
|
||||||
- 'lib/gitlab/background_migration/fix_duplicate_project_name_and_path.rb'
|
|
||||||
- 'lib/gitlab/background_migration/fix_first_mentioned_in_commit_at.rb'
|
|
||||||
- 'lib/gitlab/background_migration/fix_projects_without_project_feature.rb'
|
|
||||||
- 'lib/gitlab/background_migration/fix_projects_without_prometheus_service.rb'
|
|
||||||
- 'lib/gitlab/background_migration/move_container_registry_enabled_to_project_feature.rb'
|
|
||||||
- 'lib/gitlab/background_migration/populate_container_repository_migration_plan.rb'
|
|
||||||
- 'lib/gitlab/background_migration/populate_topics_non_private_projects_count.rb'
|
|
||||||
- 'lib/gitlab/background_migration/populate_topics_total_projects_count_cache.rb'
|
|
||||||
- 'lib/gitlab/background_migration/populate_vulnerability_reads.rb'
|
|
||||||
- 'lib/gitlab/background_migration/project_namespaces/backfill_project_namespaces.rb'
|
|
||||||
- 'lib/gitlab/background_migration/update_timelogs_null_spent_at.rb'
|
|
||||||
- 'lib/gitlab/background_migration/update_timelogs_project_id.rb'
|
|
||||||
- 'lib/gitlab/background_migration/update_users_where_two_factor_auth_required_from_group.rb'
|
|
||||||
- 'lib/gitlab/database/bulk_update.rb'
|
|
||||||
- 'lib/gitlab/database/count/tablesample_count_strategy.rb'
|
|
||||||
- 'lib/gitlab/database/load_balancing/load_balancer.rb'
|
|
||||||
- 'lib/gitlab/database/migration_helpers.rb'
|
|
||||||
- 'lib/gitlab/database/migration_helpers/loose_foreign_key_helpers.rb'
|
|
||||||
- 'lib/gitlab/database/migration_helpers/v2.rb'
|
|
||||||
- 'lib/gitlab/database/migrations/batched_background_migration_helpers.rb'
|
|
||||||
- 'lib/gitlab/database/migrations/observers/query_statistics.rb'
|
|
||||||
- 'lib/gitlab/database/partitioning/replace_table.rb'
|
|
||||||
- 'lib/gitlab/database/partitioning/single_numeric_list_partition.rb'
|
|
||||||
- 'lib/gitlab/database/partitioning/sliding_list_strategy.rb'
|
|
||||||
- 'lib/gitlab/database/partitioning/time_partition.rb'
|
|
||||||
- 'lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table.rb'
|
|
||||||
- 'lib/gitlab/database/partitioning_migration_helpers/table_management_helpers.rb'
|
|
||||||
- 'lib/gitlab/database/postgres_hll/batch_distinct_counter.rb'
|
|
||||||
- 'lib/gitlab/database/schema_helpers.rb'
|
|
||||||
- 'lib/gitlab/database/schema_migrations/migrations.rb'
|
|
||||||
- 'lib/gitlab/database/unidirectional_copy_trigger.rb'
|
|
||||||
- 'lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition.rb'
|
|
||||||
- 'lib/gitlab/graphql/pagination/keyset/conditions/null_condition.rb'
|
|
||||||
- 'lib/gitlab/pagination/keyset/in_operator_optimization/query_builder.rb'
|
|
||||||
- 'lib/gitlab/sql/glob.rb'
|
|
||||||
- 'lib/tasks/dev.rake'
|
|
||||||
- 'qa/qa/service/praefect_manager.rb'
|
|
||||||
- 'spec/db/schema_spec.rb'
|
|
||||||
- 'spec/initializers/00_rails_disable_joins_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/background_migration/copy_column_using_background_migration_job_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/migration_helpers/restrict_gitlab_schema_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/migration_helpers_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/migrations/observers/query_statistics_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/partitioning/detached_partition_dropper_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/partitioning/monthly_strategy_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/partitioning/partition_manager_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/partitioning/replace_table_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/partitioning/sliding_list_strategy_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/partitioning/time_partition_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/partitioning_migration_helpers/backfill_partitioned_table_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/partitioning_migration_helpers/foreign_key_helpers_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/partitioning_migration_helpers/index_helpers_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/partitioning_migration_helpers/table_management_helpers_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/partitioning_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/postgres_foreign_key_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/postgres_index_bloat_estimate_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/postgres_index_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/postgres_partition_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/postgres_partitioned_table_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/reindexing/reindex_concurrently_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/reindexing_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/schema_migrations/migrations_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/similarity_score_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/database/unidirectional_copy_trigger_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/graphql/pagination/keyset/conditions/not_null_condition_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/graphql/pagination/keyset/conditions/null_condition_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/pagination/keyset/in_operator_optimization/strategies/record_loader_strategy_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/pagination/keyset/order_spec.rb'
|
|
||||||
- 'spec/models/application_record_spec.rb'
|
|
||||||
- 'spec/models/concerns/after_commit_queue_spec.rb'
|
|
||||||
- 'spec/support/db_cleaner.rb'
|
|
||||||
- 'spec/support/helpers/database/partitioning_helpers.rb'
|
|
||||||
- 'spec/support/helpers/database/table_schema_helpers.rb'
|
|
||||||
- 'spec/support/helpers/database/trigger_helpers.rb'
|
|
||||||
- 'spec/support/shared_examples/loose_foreign_keys/have_loose_foreign_key.rb'
|
|
|
@ -3,7 +3,6 @@ RSpec/FactoryBot/AvoidCreate:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'ee/spec/presenters/approval_rule_presenter_spec.rb'
|
- 'ee/spec/presenters/approval_rule_presenter_spec.rb'
|
||||||
- 'ee/spec/presenters/audit_event_presenter_spec.rb'
|
- 'ee/spec/presenters/audit_event_presenter_spec.rb'
|
||||||
- 'ee/spec/presenters/ci/build_presenter_spec.rb'
|
|
||||||
- 'ee/spec/presenters/ci/build_runner_presenter_spec.rb'
|
- 'ee/spec/presenters/ci/build_runner_presenter_spec.rb'
|
||||||
- 'ee/spec/presenters/ci/minutes/usage_presenter_spec.rb'
|
- 'ee/spec/presenters/ci/minutes/usage_presenter_spec.rb'
|
||||||
- 'ee/spec/presenters/ci/pipeline_presenter_spec.rb'
|
- 'ee/spec/presenters/ci/pipeline_presenter_spec.rb'
|
||||||
|
|
|
@ -89,6 +89,8 @@ export default {
|
||||||
:default-max-date="maxDate"
|
:default-max-date="maxDate"
|
||||||
:same-day-selection="includeSelectedDate"
|
:same-day-selection="includeSelectedDate"
|
||||||
:tooltip="maxDateRangeTooltip"
|
:tooltip="maxDateRangeTooltip"
|
||||||
|
:from-label="__('From')"
|
||||||
|
:to-label="__('To')"
|
||||||
theme="animate-picker"
|
theme="animate-picker"
|
||||||
start-picker-class="js-daterange-picker-from gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-lg-align-items-center gl-lg-mr-3 gl-mb-2 gl-lg-mb-0"
|
start-picker-class="js-daterange-picker-from gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-lg-align-items-center gl-lg-mr-3 gl-mb-2 gl-lg-mb-0"
|
||||||
end-picker-class="js-daterange-picker-to gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-lg-align-items-center gl-mb-2 gl-lg-mb-0"
|
end-picker-class="js-daterange-picker-to gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-lg-align-items-center gl-mb-2 gl-lg-mb-0"
|
||||||
|
|
|
@ -240,7 +240,7 @@ export default {
|
||||||
</template>
|
</template>
|
||||||
<template #header>
|
<template #header>
|
||||||
<gl-dropdown-section-header>{{ __('Projects') }}</gl-dropdown-section-header>
|
<gl-dropdown-section-header>{{ __('Projects') }}</gl-dropdown-section-header>
|
||||||
<gl-search-box-by-type v-model.trim="searchTerm" />
|
<gl-search-box-by-type v-model.trim="searchTerm" :placeholder="__('Search')" />
|
||||||
</template>
|
</template>
|
||||||
<template #highlighted-items>
|
<template #highlighted-items>
|
||||||
<gl-dropdown-item
|
<gl-dropdown-item
|
||||||
|
|
|
@ -62,7 +62,11 @@ export default {
|
||||||
return {
|
return {
|
||||||
primary: {
|
primary: {
|
||||||
text: __('Yes, delete project'),
|
text: __('Yes, delete project'),
|
||||||
attributes: [{ variant: 'danger' }, { disabled: this.confirmDisabled }],
|
attributes: [
|
||||||
|
{ variant: 'danger' },
|
||||||
|
{ disabled: this.confirmDisabled },
|
||||||
|
{ 'data-qa-selector': 'confirm_delete_button' },
|
||||||
|
],
|
||||||
},
|
},
|
||||||
cancel: {
|
cancel: {
|
||||||
text: __('Cancel, keep project'),
|
text: __('Cancel, keep project'),
|
||||||
|
@ -97,9 +101,13 @@ export default {
|
||||||
<input type="hidden" name="_method" value="delete" />
|
<input type="hidden" name="_method" value="delete" />
|
||||||
<input :value="csrfToken" type="hidden" name="authenticity_token" />
|
<input :value="csrfToken" type="hidden" name="authenticity_token" />
|
||||||
|
|
||||||
<gl-button v-gl-modal="modalId" category="primary" variant="danger">{{
|
<gl-button
|
||||||
$options.strings.deleteProject
|
v-gl-modal="modalId"
|
||||||
}}</gl-button>
|
category="primary"
|
||||||
|
variant="danger"
|
||||||
|
data-qa-selector="delete_button"
|
||||||
|
>{{ $options.strings.deleteProject }}</gl-button
|
||||||
|
>
|
||||||
|
|
||||||
<gl-modal
|
<gl-modal
|
||||||
ref="removeModal"
|
ref="removeModal"
|
||||||
|
@ -168,6 +176,7 @@ export default {
|
||||||
v-model="userInput"
|
v-model="userInput"
|
||||||
name="confirm_name_input"
|
name="confirm_name_input"
|
||||||
type="text"
|
type="text"
|
||||||
|
data-qa-selector="confirm_name_field"
|
||||||
/>
|
/>
|
||||||
<slot name="modal-footer"></slot>
|
<slot name="modal-footer"></slot>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -45,6 +45,9 @@ export default {
|
||||||
if (this.status === 'closed') return 'gl-bg-red-50';
|
if (this.status === 'closed') return 'gl-bg-red-50';
|
||||||
return null;
|
return null;
|
||||||
},
|
},
|
||||||
|
hasActionsSlot() {
|
||||||
|
return this.$scopedSlots.actions?.()?.length;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
@ -72,15 +75,18 @@ export default {
|
||||||
<div class="gl-display-flex gl-w-full">
|
<div class="gl-display-flex gl-w-full">
|
||||||
<div
|
<div
|
||||||
:class="{
|
:class="{
|
||||||
'gl-display-flex': actions.length,
|
'gl-display-flex gl-align-items-center': actions.length,
|
||||||
'gl-md-display-flex gl-align-items-center': !actions.length,
|
'gl-md-display-flex gl-align-items-center': !actions.length,
|
||||||
}"
|
}"
|
||||||
class="media-body"
|
class="media-body"
|
||||||
>
|
>
|
||||||
<slot></slot>
|
<slot></slot>
|
||||||
<div
|
<div
|
||||||
:class="{ 'gl-flex-direction-column-reverse': !actions.length }"
|
:class="{
|
||||||
class="gl-display-flex gl-md-display-block gl-font-size-0 gl-ml-auto"
|
'gl-flex-direction-column-reverse gl-md-flex-direction-row gl-flex-wrap gl-justify-content-end': !actions.length,
|
||||||
|
'gl-md-pt-0 gl-pt-3': hasActionsSlot,
|
||||||
|
}"
|
||||||
|
class="gl-display-flex gl-font-size-0 gl-ml-auto gl-gap-3"
|
||||||
>
|
>
|
||||||
<slot name="actions">
|
<slot name="actions">
|
||||||
<actions v-if="actions.length" :tertiary-buttons="actions" />
|
<actions v-if="actions.length" :tertiary-buttons="actions" />
|
||||||
|
|
|
@ -26,7 +26,7 @@ export default {
|
||||||
<template>
|
<template>
|
||||||
<state-container :mr="mr" status="failed">
|
<state-container :mr="mr" status="failed">
|
||||||
<span
|
<span
|
||||||
class="gl-ml-3 gl-font-weight-bold gl-w-100 gl-flex-grow-1 gl-md-mr-3 gl-ml-0! gl-text-body!"
|
class="gl-ml-3 gl-font-weight-bold gl-w-100 gl-flex-grow-1 gl-md-mr-3 gl-ml-0! gl-text-body! gl-align-self-start"
|
||||||
>
|
>
|
||||||
{{ s__('mrWidget|Merge blocked: all threads must be resolved.') }}
|
{{ s__('mrWidget|Merge blocked: all threads must be resolved.') }}
|
||||||
</span>
|
</span>
|
||||||
|
@ -34,7 +34,7 @@ export default {
|
||||||
<gl-button
|
<gl-button
|
||||||
v-if="mr.createIssueToResolveDiscussionsPath"
|
v-if="mr.createIssueToResolveDiscussionsPath"
|
||||||
:href="mr.createIssueToResolveDiscussionsPath"
|
:href="mr.createIssueToResolveDiscussionsPath"
|
||||||
class="js-create-issue gl-align-self-start gl-vertical-align-top gl-mr-2"
|
class="js-create-issue gl-align-self-start gl-vertical-align-top"
|
||||||
size="small"
|
size="small"
|
||||||
variant="confirm"
|
variant="confirm"
|
||||||
category="secondary"
|
category="secondary"
|
||||||
|
@ -43,7 +43,7 @@ export default {
|
||||||
</gl-button>
|
</gl-button>
|
||||||
<gl-button
|
<gl-button
|
||||||
data-testid="jump-to-first"
|
data-testid="jump-to-first"
|
||||||
class="gl-mb-2 gl-md-mb-0 gl-align-self-start gl-vertical-align-top"
|
class="gl-align-self-start gl-vertical-align-top"
|
||||||
size="small"
|
size="small"
|
||||||
variant="confirm"
|
variant="confirm"
|
||||||
category="primary"
|
category="primary"
|
||||||
|
|
|
@ -8,7 +8,7 @@
|
||||||
.top-area
|
.top-area
|
||||||
= gl_tabs_nav({ class: 'gl-flex-grow-1 gl-border-0' }) do
|
= gl_tabs_nav({ class: 'gl-flex-grow-1 gl-border-0' }) do
|
||||||
= gl_tab_link_to _("Your groups"), dashboard_groups_path
|
= gl_tab_link_to _("Your groups"), dashboard_groups_path
|
||||||
= gl_tab_link_to _("Explore public groups"), explore_groups_path
|
= gl_tab_link_to _("Explore public groups"), explore_groups_path, data: { qa_selector: "public_groups_tab" }
|
||||||
.nav-controls
|
.nav-controls
|
||||||
= render 'shared/groups/search_form'
|
= render 'shared/groups/search_form'
|
||||||
= render 'shared/groups/dropdown'
|
= render 'shared/groups/dropdown'
|
||||||
|
|
|
@ -21,6 +21,8 @@ metadata:
|
||||||
description: Operations related to CI/CD variables
|
description: Operations related to CI/CD variables
|
||||||
- name: cluster_agents
|
- name: cluster_agents
|
||||||
description: Operations related to the GitLab agent for Kubernetes
|
description: Operations related to the GitLab agent for Kubernetes
|
||||||
|
- name: clusters
|
||||||
|
description: Operations related to clusters
|
||||||
- name: ci_resource_groups
|
- name: ci_resource_groups
|
||||||
description: Operations to manage job concurrency with resource groups
|
description: Operations to manage job concurrency with resource groups
|
||||||
- name: deploy_keys
|
- name: deploy_keys
|
||||||
|
|
|
@ -0,0 +1,16 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
|
||||||
|
# for more information on how to write migrations for GitLab.
|
||||||
|
|
||||||
|
class ChangeMemberNamespaceIdNotNull < Gitlab::Database::Migration[2.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
def up
|
||||||
|
add_not_null_constraint :members, :member_namespace_id, validate: false
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_not_null_constraint :members, :member_namespace_id
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,11 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ValidateEnvironmentIdOnDeployments < Gitlab::Database::Migration[2.0]
|
||||||
|
def up
|
||||||
|
validate_foreign_key :deployments, :environment_id
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
# no-op
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,15 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ValidateNotNullConstraintOnMemberNamespaceId < Gitlab::Database::Migration[2.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
CONSTRAINT_NAME = 'check_508774aac0'
|
||||||
|
|
||||||
|
def up
|
||||||
|
validate_not_null_constraint :members, :member_namespace_id, constraint_name: CONSTRAINT_NAME
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
# no-op
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,13 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class ValidateFkMemberNamespaceId < Gitlab::Database::Migration[2.0]
|
||||||
|
CONSTRAINT_NAME = 'fk_2f85abf8f1'
|
||||||
|
|
||||||
|
def up
|
||||||
|
validate_foreign_key :members, :member_namespace_id, name: CONSTRAINT_NAME
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
# no-op
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1,28 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class RemoveOldMemberNamespaceIdFk < Gitlab::Database::Migration[2.0]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
TARGET_COLUMN = :member_namespace_id
|
||||||
|
|
||||||
|
def up
|
||||||
|
with_lock_retries do
|
||||||
|
remove_foreign_key_if_exists(:members, column: TARGET_COLUMN, name: fk_name(TARGET_COLUMN))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
add_concurrent_foreign_key(
|
||||||
|
:members,
|
||||||
|
:namespaces,
|
||||||
|
column: TARGET_COLUMN,
|
||||||
|
name: fk_name(TARGET_COLUMN),
|
||||||
|
on_delete: :nullify
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def fk_name(column_name)
|
||||||
|
# generate a FK name
|
||||||
|
concurrent_foreign_key_name(:members, column_name)
|
||||||
|
end
|
||||||
|
end
|
|
@ -0,0 +1 @@
|
||||||
|
6f0ce1b68310b3194aa7b6219d79570e8179d449f49d828800f90f70d9242f38
|
|
@ -0,0 +1 @@
|
||||||
|
248aecf9fa53146f2c1f7771fd60adf720fa8c0d2bd33d71c6177b185e4248d1
|
|
@ -0,0 +1 @@
|
||||||
|
499f7b3951c9792d2a8f204b72c474a42e8301b487fa9f68080dd5bb5db0c64c
|
|
@ -0,0 +1 @@
|
||||||
|
b633df04851493d7d4b5d7da79ba3057f6f2c302e507b4f963596edf9cbfcb88
|
|
@ -0,0 +1 @@
|
||||||
|
f5295b135cd395a59c7afc6a9d999201f9ea1174aab893d31ead398aa8c0f8bb
|
|
@ -17354,7 +17354,8 @@ CREATE TABLE members (
|
||||||
state smallint DEFAULT 0,
|
state smallint DEFAULT 0,
|
||||||
invite_email_success boolean DEFAULT true NOT NULL,
|
invite_email_success boolean DEFAULT true NOT NULL,
|
||||||
member_namespace_id bigint,
|
member_namespace_id bigint,
|
||||||
member_role_id bigint
|
member_role_id bigint,
|
||||||
|
CONSTRAINT check_508774aac0 CHECK ((member_namespace_id IS NOT NULL))
|
||||||
);
|
);
|
||||||
|
|
||||||
CREATE SEQUENCE members_id_seq
|
CREATE SEQUENCE members_id_seq
|
||||||
|
@ -32623,7 +32624,7 @@ CREATE TRIGGER trigger_update_vulnerability_reads_on_vulnerability_update AFTER
|
||||||
CREATE TRIGGER users_loose_fk_trigger AFTER DELETE ON users REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
|
CREATE TRIGGER users_loose_fk_trigger AFTER DELETE ON users REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
|
||||||
|
|
||||||
ALTER TABLE ONLY deployments
|
ALTER TABLE ONLY deployments
|
||||||
ADD CONSTRAINT fk_009fd21147 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE NOT VALID;
|
ADD CONSTRAINT fk_009fd21147 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
ALTER TABLE ONLY epics
|
ALTER TABLE ONLY epics
|
||||||
ADD CONSTRAINT fk_013c9f36ca FOREIGN KEY (due_date_sourcing_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
|
ADD CONSTRAINT fk_013c9f36ca FOREIGN KEY (due_date_sourcing_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
|
||||||
|
@ -32797,7 +32798,7 @@ ALTER TABLE ONLY vulnerability_merge_request_links
|
||||||
ADD CONSTRAINT fk_2ef3954596 FOREIGN KEY (vulnerability_id) REFERENCES vulnerabilities(id) ON DELETE CASCADE;
|
ADD CONSTRAINT fk_2ef3954596 FOREIGN KEY (vulnerability_id) REFERENCES vulnerabilities(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
ALTER TABLE ONLY members
|
ALTER TABLE ONLY members
|
||||||
ADD CONSTRAINT fk_2f85abf8f1 FOREIGN KEY (member_namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE NOT VALID;
|
ADD CONSTRAINT fk_2f85abf8f1 FOREIGN KEY (member_namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
ALTER TABLE ONLY analytics_cycle_analytics_group_stages
|
ALTER TABLE ONLY analytics_cycle_analytics_group_stages
|
||||||
ADD CONSTRAINT fk_3078345d6d FOREIGN KEY (stage_event_hash_id) REFERENCES analytics_cycle_analytics_stage_event_hashes(id) ON DELETE CASCADE;
|
ADD CONSTRAINT fk_3078345d6d FOREIGN KEY (stage_event_hash_id) REFERENCES analytics_cycle_analytics_stage_event_hashes(id) ON DELETE CASCADE;
|
||||||
|
@ -33210,9 +33211,6 @@ ALTER TABLE ONLY epics
|
||||||
ALTER TABLE ONLY dast_profiles
|
ALTER TABLE ONLY dast_profiles
|
||||||
ADD CONSTRAINT fk_aa76ef30e9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
ADD CONSTRAINT fk_aa76ef30e9 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||||
|
|
||||||
ALTER TABLE ONLY members
|
|
||||||
ADD CONSTRAINT fk_aa82dcc1c6 FOREIGN KEY (member_namespace_id) REFERENCES namespaces(id) ON DELETE SET NULL;
|
|
||||||
|
|
||||||
ALTER TABLE ONLY alert_management_alerts
|
ALTER TABLE ONLY alert_management_alerts
|
||||||
ADD CONSTRAINT fk_aad61aedca FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE SET NULL;
|
ADD CONSTRAINT fk_aad61aedca FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE SET NULL;
|
||||||
|
|
||||||
|
|
|
@ -128,9 +128,7 @@ These additional CI/CD minutes:
|
||||||
- Are carried over to the next month, if any remain at the end of the month.
|
- Are carried over to the next month, if any remain at the end of the month.
|
||||||
- Are valid for 12 months from date of purchase or until all minutes are consumed, whichever comes first. Expiry of minutes is not currently enforced.
|
- Are valid for 12 months from date of purchase or until all minutes are consumed, whichever comes first. Expiry of minutes is not currently enforced.
|
||||||
|
|
||||||
If you use more CI/CD minutes than your monthly quota, when you purchase more,
|
For example, with a GitLab SaaS Premium license:
|
||||||
those CI/CD minutes are deducted from your quota. For example, with a GitLab SaaS
|
|
||||||
Premium license:
|
|
||||||
|
|
||||||
- You have `10,000` monthly minutes.
|
- You have `10,000` monthly minutes.
|
||||||
- You purchase an additional `5,000` minutes.
|
- You purchase an additional `5,000` minutes.
|
||||||
|
@ -271,9 +269,9 @@ the next month.
|
||||||
|
|
||||||
For example:
|
For example:
|
||||||
|
|
||||||
- On **1st April**, you purchase `5,000` CI/CD minutes.
|
- On **1st April**, you purchase `5,000` additional CI/CD minutes.
|
||||||
- During April, you use only `3,000` of the `5,000` minutes.
|
- During April, you use only `3,000` of the `5,000` additional minutes.
|
||||||
- On **1st May**, the remaining `2,000` minutes roll over and are added to your monthly quota.
|
- On **1st May**, the unused minute roll over, so you have `2,000` additional minutes available for May.
|
||||||
|
|
||||||
Additional CI/CD minutes are a one-time purchase and do not renew or refresh each month.
|
Additional CI/CD minutes are a one-time purchase and do not renew or refresh each month.
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,8 @@ for your GitLab instance). For example, <https://gitlab.com/public>.
|
||||||
You can control the visibility of individual features with
|
You can control the visibility of individual features with
|
||||||
[project feature settings](permissions.md#project-features).
|
[project feature settings](permissions.md#project-features).
|
||||||
|
|
||||||
The visibility setting of a project must be the same as or less restrictive
|
The visibility setting of a project must be at least as restrictive
|
||||||
than the visibility of its parent group.
|
as the visibility of its parent group.
|
||||||
For example, a private group can include only private projects,
|
For example, a private group can include only private projects,
|
||||||
while a public group can include private, internal, and public projects.
|
while a public group can include private, internal, and public projects.
|
||||||
|
|
||||||
|
|
|
@ -14,16 +14,28 @@ module API
|
||||||
end
|
end
|
||||||
|
|
||||||
namespace 'admin' do
|
namespace 'admin' do
|
||||||
desc "Get list of all instance clusters" do
|
desc 'List instance clusters' do
|
||||||
detail "This feature was introduced in GitLab 13.2."
|
detail 'This feature was introduced in GitLab 13.2. Returns a list of instance clusters.'
|
||||||
|
success Entities::Cluster
|
||||||
|
failure [
|
||||||
|
{ code: 403, message: 'Forbidden' }
|
||||||
|
]
|
||||||
|
is_array true
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
get '/clusters' do
|
get '/clusters' do
|
||||||
authorize! :read_cluster, clusterable_instance
|
authorize! :read_cluster, clusterable_instance
|
||||||
present paginate(clusters_for_current_user), with: Entities::Cluster
|
present paginate(clusters_for_current_user), with: Entities::Cluster
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Get a single instance cluster" do
|
desc 'Get a single instance cluster' do
|
||||||
detail "This feature was introduced in GitLab 13.2."
|
detail 'This feature was introduced in GitLab 13.2. Returns a single instance cluster.'
|
||||||
|
success Entities::Cluster
|
||||||
|
failure [
|
||||||
|
{ code: 403, message: 'Forbidden' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :cluster_id, type: Integer, desc: "The cluster ID"
|
requires :cluster_id, type: Integer, desc: "The cluster ID"
|
||||||
|
@ -34,8 +46,15 @@ module API
|
||||||
present cluster, with: Entities::Cluster
|
present cluster, with: Entities::Cluster
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Add an instance cluster" do
|
desc 'Add existing instance cluster' do
|
||||||
detail "This feature was introduced in GitLab 13.2."
|
detail 'This feature was introduced in GitLab 13.2. Adds an existing Kubernetes instance cluster.'
|
||||||
|
success Entities::Cluster
|
||||||
|
failure [
|
||||||
|
{ code: 400, message: 'Validation error' },
|
||||||
|
{ code: 403, message: 'Forbidden' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :name, type: String, desc: 'Cluster name'
|
requires :name, type: String, desc: 'Cluster name'
|
||||||
|
@ -67,8 +86,15 @@ module API
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Update an instance cluster" do
|
desc 'Edit instance cluster' do
|
||||||
detail "This feature was introduced in GitLab 13.2."
|
detail 'This feature was introduced in GitLab 13.2. Updates an existing instance cluster.'
|
||||||
|
success Entities::Cluster
|
||||||
|
failure [
|
||||||
|
{ code: 400, message: 'Validation error' },
|
||||||
|
{ code: 403, message: 'Forbidden' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :cluster_id, type: Integer, desc: 'The cluster ID'
|
requires :cluster_id, type: Integer, desc: 'The cluster ID'
|
||||||
|
@ -98,8 +124,14 @@ module API
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc "Remove a cluster" do
|
desc 'Delete instance cluster' do
|
||||||
detail "This feature was introduced in GitLab 13.2."
|
detail 'This feature was introduced in GitLab 13.2. Deletes an existing instance cluster. Does not remove existing resources within the connected Kubernetes cluster.'
|
||||||
|
success Entities::Cluster
|
||||||
|
failure [
|
||||||
|
{ code: 403, message: 'Forbidden' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :cluster_id, type: Integer, desc: "The cluster ID"
|
requires :cluster_id, type: Integer, desc: "The cluster ID"
|
||||||
|
|
|
@ -172,6 +172,7 @@ module API
|
||||||
# Keep in alphabetical order
|
# Keep in alphabetical order
|
||||||
mount ::API::AccessRequests
|
mount ::API::AccessRequests
|
||||||
mount ::API::Admin::Ci::Variables
|
mount ::API::Admin::Ci::Variables
|
||||||
|
mount ::API::Admin::InstanceClusters
|
||||||
mount ::API::Appearance
|
mount ::API::Appearance
|
||||||
mount ::API::Applications
|
mount ::API::Applications
|
||||||
mount ::API::BroadcastMessages
|
mount ::API::BroadcastMessages
|
||||||
|
@ -179,6 +180,7 @@ module API
|
||||||
mount ::API::Ci::ResourceGroups
|
mount ::API::Ci::ResourceGroups
|
||||||
mount ::API::Ci::Runner
|
mount ::API::Ci::Runner
|
||||||
mount ::API::Ci::Runners
|
mount ::API::Ci::Runners
|
||||||
|
mount ::API::Ci::Variables
|
||||||
mount ::API::Clusters::AgentTokens
|
mount ::API::Clusters::AgentTokens
|
||||||
mount ::API::Clusters::Agents
|
mount ::API::Clusters::Agents
|
||||||
mount ::API::Commits
|
mount ::API::Commits
|
||||||
|
@ -191,6 +193,7 @@ module API
|
||||||
mount ::API::FeatureFlagsUserLists
|
mount ::API::FeatureFlagsUserLists
|
||||||
mount ::API::Features
|
mount ::API::Features
|
||||||
mount ::API::FreezePeriods
|
mount ::API::FreezePeriods
|
||||||
|
mount ::API::GroupClusters
|
||||||
mount ::API::GroupExport
|
mount ::API::GroupExport
|
||||||
mount ::API::ImportBitbucketServer
|
mount ::API::ImportBitbucketServer
|
||||||
mount ::API::ImportGithub
|
mount ::API::ImportGithub
|
||||||
|
@ -200,15 +203,18 @@ module API
|
||||||
mount ::API::Metadata
|
mount ::API::Metadata
|
||||||
mount ::API::PersonalAccessTokens::SelfInformation
|
mount ::API::PersonalAccessTokens::SelfInformation
|
||||||
mount ::API::PersonalAccessTokens
|
mount ::API::PersonalAccessTokens
|
||||||
|
mount ::API::ProjectClusters
|
||||||
mount ::API::ProjectExport
|
mount ::API::ProjectExport
|
||||||
mount ::API::ProjectHooks
|
mount ::API::ProjectHooks
|
||||||
mount ::API::ProjectRepositoryStorageMoves
|
mount ::API::ProjectRepositoryStorageMoves
|
||||||
mount ::API::ProjectSnippets
|
mount ::API::ProjectSnippets
|
||||||
mount ::API::ProjectSnapshots
|
mount ::API::ProjectSnapshots
|
||||||
|
mount ::API::ProjectTemplates
|
||||||
mount ::API::ProtectedBranches
|
mount ::API::ProtectedBranches
|
||||||
mount ::API::ProtectedTags
|
mount ::API::ProtectedTags
|
||||||
mount ::API::Releases
|
mount ::API::Releases
|
||||||
mount ::API::Release::Links
|
mount ::API::Release::Links
|
||||||
|
mount ::API::RemoteMirrors
|
||||||
mount ::API::Repositories
|
mount ::API::Repositories
|
||||||
mount ::API::ResourceAccessTokens
|
mount ::API::ResourceAccessTokens
|
||||||
mount ::API::Snippets
|
mount ::API::Snippets
|
||||||
|
@ -226,7 +232,6 @@ module API
|
||||||
|
|
||||||
# Keep in alphabetical order
|
# Keep in alphabetical order
|
||||||
mount ::API::Admin::BatchedBackgroundMigrations
|
mount ::API::Admin::BatchedBackgroundMigrations
|
||||||
mount ::API::Admin::InstanceClusters
|
|
||||||
mount ::API::Admin::PlanLimits
|
mount ::API::Admin::PlanLimits
|
||||||
mount ::API::Admin::Sidekiq
|
mount ::API::Admin::Sidekiq
|
||||||
mount ::API::AlertManagementAlerts
|
mount ::API::AlertManagementAlerts
|
||||||
|
@ -241,7 +246,6 @@ module API
|
||||||
mount ::API::Ci::Pipelines
|
mount ::API::Ci::Pipelines
|
||||||
mount ::API::Ci::SecureFiles
|
mount ::API::Ci::SecureFiles
|
||||||
mount ::API::Ci::Triggers
|
mount ::API::Ci::Triggers
|
||||||
mount ::API::Ci::Variables
|
|
||||||
mount ::API::CommitStatuses
|
mount ::API::CommitStatuses
|
||||||
mount ::API::ComposerPackages
|
mount ::API::ComposerPackages
|
||||||
mount ::API::ConanInstancePackages
|
mount ::API::ConanInstancePackages
|
||||||
|
@ -262,7 +266,6 @@ module API
|
||||||
mount ::API::GoProxy
|
mount ::API::GoProxy
|
||||||
mount ::API::GroupAvatar
|
mount ::API::GroupAvatar
|
||||||
mount ::API::GroupBoards
|
mount ::API::GroupBoards
|
||||||
mount ::API::GroupClusters
|
|
||||||
mount ::API::GroupContainerRepositories
|
mount ::API::GroupContainerRepositories
|
||||||
mount ::API::GroupDebianDistributions
|
mount ::API::GroupDebianDistributions
|
||||||
mount ::API::GroupImport
|
mount ::API::GroupImport
|
||||||
|
@ -295,7 +298,6 @@ module API
|
||||||
mount ::API::PackageFiles
|
mount ::API::PackageFiles
|
||||||
mount ::API::Pages
|
mount ::API::Pages
|
||||||
mount ::API::PagesDomains
|
mount ::API::PagesDomains
|
||||||
mount ::API::ProjectClusters
|
|
||||||
mount ::API::ProjectContainerRepositories
|
mount ::API::ProjectContainerRepositories
|
||||||
mount ::API::ProjectDebianDistributions
|
mount ::API::ProjectDebianDistributions
|
||||||
mount ::API::ProjectEvents
|
mount ::API::ProjectEvents
|
||||||
|
@ -303,11 +305,9 @@ module API
|
||||||
mount ::API::ProjectMilestones
|
mount ::API::ProjectMilestones
|
||||||
mount ::API::ProjectPackages
|
mount ::API::ProjectPackages
|
||||||
mount ::API::ProjectStatistics
|
mount ::API::ProjectStatistics
|
||||||
mount ::API::ProjectTemplates
|
|
||||||
mount ::API::Projects
|
mount ::API::Projects
|
||||||
mount ::API::ProtectedTags
|
mount ::API::ProtectedTags
|
||||||
mount ::API::PypiPackages
|
mount ::API::PypiPackages
|
||||||
mount ::API::RemoteMirrors
|
|
||||||
mount ::API::ResourceLabelEvents
|
mount ::API::ResourceLabelEvents
|
||||||
mount ::API::ResourceMilestoneEvents
|
mount ::API::ResourceMilestoneEvents
|
||||||
mount ::API::ResourceStateEvents
|
mount ::API::ResourceStateEvents
|
||||||
|
|
|
@ -13,12 +13,13 @@ module API
|
||||||
helpers ::API::Helpers::VariablesHelpers
|
helpers ::API::Helpers::VariablesHelpers
|
||||||
|
|
||||||
params do
|
params do
|
||||||
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
|
requires :id, types: [String, Integer], desc: 'The ID of a project or URL-encoded NAMESPACE/PROJECT_NAME of the project owned by the authenticated user'
|
||||||
end
|
end
|
||||||
|
|
||||||
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
||||||
desc 'Get project variables' do
|
desc 'Get project variables' do
|
||||||
success Entities::Ci::Variable
|
success Entities::Ci::Variable
|
||||||
|
tags %w[ci_variables]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
use :pagination
|
use :pagination
|
||||||
|
@ -28,13 +29,15 @@ module API
|
||||||
present paginate(variables), with: Entities::Ci::Variable
|
present paginate(variables), with: Entities::Ci::Variable
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Get a specific variable from a project' do
|
desc 'Get the details of a single variable from a project' do
|
||||||
success Entities::Ci::Variable
|
success Entities::Ci::Variable
|
||||||
|
failure [{ code: 404, message: 'Variable Not Found' }]
|
||||||
|
tags %w[ci_variables]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :key, type: String, desc: 'The key of the variable'
|
requires :key, type: String, desc: 'The key of a variable'
|
||||||
optional :filter, type: Hash, desc: 'Available filters: [environment_scope]. Example: filter[environment_scope]=production' do
|
optional :filter, type: Hash, desc: 'Available filters: [environment_scope]. Example: filter[environment_scope]=production' do
|
||||||
optional :environment_scope, type: String, desc: 'The environment scope of the variable'
|
optional :environment_scope, type: String, desc: 'The environment scope of a variable'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# rubocop: disable CodeReuse/ActiveRecord
|
# rubocop: disable CodeReuse/ActiveRecord
|
||||||
|
@ -48,15 +51,17 @@ module API
|
||||||
|
|
||||||
desc 'Create a new variable in a project' do
|
desc 'Create a new variable in a project' do
|
||||||
success Entities::Ci::Variable
|
success Entities::Ci::Variable
|
||||||
|
failure [{ code: 400, message: '400 Bad Request' }]
|
||||||
|
tags %w[ci_variables]
|
||||||
end
|
end
|
||||||
route_setting :log_safety, { safe: %w[key], unsafe: %w[value] }
|
route_setting :log_safety, { safe: %w[key], unsafe: %w[value] }
|
||||||
params do
|
params do
|
||||||
requires :key, type: String, desc: 'The key of the variable'
|
requires :key, type: String, desc: 'The key of a variable'
|
||||||
requires :value, type: String, desc: 'The value of the variable'
|
requires :value, type: String, desc: 'The value of a variable'
|
||||||
optional :protected, type: Boolean, desc: 'Whether the variable is protected'
|
optional :protected, type: Boolean, desc: 'Whether the variable is protected'
|
||||||
optional :masked, type: Boolean, desc: 'Whether the variable is masked'
|
optional :masked, type: Boolean, desc: 'Whether the variable is masked'
|
||||||
optional :raw, type: Boolean, desc: 'Whether the variable will be expanded'
|
optional :raw, type: Boolean, desc: 'Whether the variable will be expanded'
|
||||||
optional :variable_type, type: String, values: ::Ci::Variable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file. Defaults to env_var'
|
optional :variable_type, type: String, values: ::Ci::Variable.variable_types.keys, desc: 'The type of the variable. Default: env_var'
|
||||||
optional :environment_scope, type: String, desc: 'The environment_scope of the variable'
|
optional :environment_scope, type: String, desc: 'The environment_scope of the variable'
|
||||||
end
|
end
|
||||||
post ':id/variables' do
|
post ':id/variables' do
|
||||||
|
@ -75,18 +80,20 @@ module API
|
||||||
|
|
||||||
desc 'Update an existing variable from a project' do
|
desc 'Update an existing variable from a project' do
|
||||||
success Entities::Ci::Variable
|
success Entities::Ci::Variable
|
||||||
|
failure [{ code: 404, message: 'Variable Not Found' }]
|
||||||
|
tags %w[ci_variables]
|
||||||
end
|
end
|
||||||
route_setting :log_safety, { safe: %w[key], unsafe: %w[value] }
|
route_setting :log_safety, { safe: %w[key], unsafe: %w[value] }
|
||||||
params do
|
params do
|
||||||
optional :key, type: String, desc: 'The key of the variable'
|
optional :key, type: String, desc: 'The key of a variable'
|
||||||
optional :value, type: String, desc: 'The value of the variable'
|
optional :value, type: String, desc: 'The value of a variable'
|
||||||
optional :protected, type: Boolean, desc: 'Whether the variable is protected'
|
optional :protected, type: Boolean, desc: 'Whether the variable is protected'
|
||||||
optional :masked, type: Boolean, desc: 'Whether the variable is masked'
|
optional :masked, type: Boolean, desc: 'Whether the variable is masked'
|
||||||
|
optional :environment_scope, type: String, desc: 'The environment_scope of a variable'
|
||||||
optional :raw, type: Boolean, desc: 'Whether the variable will be expanded'
|
optional :raw, type: Boolean, desc: 'Whether the variable will be expanded'
|
||||||
optional :variable_type, type: String, values: ::Ci::Variable.variable_types.keys, desc: 'The type of variable, must be one of env_var or file'
|
optional :variable_type, type: String, values: ::Ci::Variable.variable_types.keys, desc: 'The type of the variable. Default: env_var'
|
||||||
optional :environment_scope, type: String, desc: 'The environment_scope of the variable'
|
|
||||||
optional :filter, type: Hash, desc: 'Available filters: [environment_scope]. Example: filter[environment_scope]=production' do
|
optional :filter, type: Hash, desc: 'Available filters: [environment_scope]. Example: filter[environment_scope]=production' do
|
||||||
optional :environment_scope, type: String, desc: 'The environment scope of the variable'
|
optional :environment_scope, type: String, desc: 'The environment scope of a variable'
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
# rubocop: disable CodeReuse/ActiveRecord
|
# rubocop: disable CodeReuse/ActiveRecord
|
||||||
|
@ -110,9 +117,11 @@ module API
|
||||||
|
|
||||||
desc 'Delete an existing variable from a project' do
|
desc 'Delete an existing variable from a project' do
|
||||||
success Entities::Ci::Variable
|
success Entities::Ci::Variable
|
||||||
|
failure [{ code: 404, message: 'Variable Not Found' }]
|
||||||
|
tags %w[ci_variables]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :key, type: String, desc: 'The key of the variable'
|
requires :key, type: String, desc: 'The key of a variable'
|
||||||
optional :filter, type: Hash, desc: 'Available filters: [environment_scope]. Example: filter[environment_scope]=production' do
|
optional :filter, type: Hash, desc: 'Available filters: [environment_scope]. Example: filter[environment_scope]=production' do
|
||||||
optional :environment_scope, type: String, desc: 'The environment scope of the variable'
|
optional :environment_scope, type: String, desc: 'The environment scope of the variable'
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,12 +4,25 @@ module API
|
||||||
module Entities
|
module Entities
|
||||||
# Serializes a Licensee::License
|
# Serializes a Licensee::License
|
||||||
class License < Entities::LicenseBasic
|
class License < Entities::LicenseBasic
|
||||||
expose :popular?, as: :popular
|
expose :popular?, as: :popular, documentation: { type: 'boolean' }
|
||||||
expose(:description) { |license| license.meta['description'] }
|
|
||||||
expose(:conditions) { |license| license.meta['conditions'] }
|
expose :description, documentation: { type: 'string', example: 'A simple license' } do |license|
|
||||||
expose(:permissions) { |license| license.meta['permissions'] }
|
license.meta['description']
|
||||||
expose(:limitations) { |license| license.meta['limitations'] }
|
end
|
||||||
expose :content
|
|
||||||
|
expose :conditions, documentation: { type: 'string', is_array: true, example: 'include-copyright' } do |license|
|
||||||
|
license.meta['conditions']
|
||||||
|
end
|
||||||
|
|
||||||
|
expose :permissions, documentation: { type: 'string', is_array: true, example: 'commercial-use' } do |license|
|
||||||
|
license.meta['permissions']
|
||||||
|
end
|
||||||
|
|
||||||
|
expose :limitations, documentation: { type: 'string', is_array: true, example: 'liability' } do |license|
|
||||||
|
license.meta['limitations']
|
||||||
|
end
|
||||||
|
|
||||||
|
expose :content, documentation: { type: 'string', example: 'GNU GENERAL PUBLIC LICENSE' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -4,8 +4,10 @@ module API
|
||||||
module Entities
|
module Entities
|
||||||
# Serializes a Gitlab::Git::DeclaredLicense
|
# Serializes a Gitlab::Git::DeclaredLicense
|
||||||
class LicenseBasic < Grape::Entity
|
class LicenseBasic < Grape::Entity
|
||||||
expose :key, :name, :nickname
|
expose :key, documentation: { type: 'string', example: 'gpl-3.0' }
|
||||||
expose :url, as: :html_url
|
expose :name, documentation: { type: 'string', example: 'GNU General Public License v3.0' }
|
||||||
|
expose :nickname, documentation: { type: 'string', example: 'GNU GPLv3' }
|
||||||
|
expose :url, as: :html_url, documentation: { example: 'http://choosealicense.com/licenses/gpl-3.0' }
|
||||||
|
|
||||||
# This was dropped:
|
# This was dropped:
|
||||||
# https://github.com/github/choosealicense.com/commit/325806b42aa3d5b78e84120327ec877bc936dbdd#diff-66df8f1997786f7052d29010f2cbb4c66391d60d24ca624c356acc0ab986f139
|
# https://github.com/github/choosealicense.com/commit/325806b42aa3d5b78e84120327ec877bc936dbdd#diff-66df8f1997786f7052d29010f2cbb4c66391d60d24ca624c356acc0ab986f139
|
||||||
|
|
|
@ -3,16 +3,16 @@
|
||||||
module API
|
module API
|
||||||
module Entities
|
module Entities
|
||||||
class RemoteMirror < Grape::Entity
|
class RemoteMirror < Grape::Entity
|
||||||
expose :id
|
expose :id, documentation: { type: 'integer', example: 101486 }
|
||||||
expose :enabled
|
expose :enabled, documentation: { type: 'boolean', example: true }
|
||||||
expose :safe_url, as: :url
|
expose :safe_url, as: :url, documentation: { type: 'string', example: 'https://*****:*****@example.com/gitlab/example.git' }
|
||||||
expose :update_status
|
expose :update_status, documentation: { type: 'string', example: 'finished' }
|
||||||
expose :last_update_at
|
expose :last_update_at, documentation: { type: 'dateTime', example: '2020-01-06T17:32:02.823Z' }
|
||||||
expose :last_update_started_at
|
expose :last_update_started_at, documentation: { type: 'dateTime', example: '2020-01-06T17:32:02.823Z' }
|
||||||
expose :last_successful_update_at
|
expose :last_successful_update_at, documentation: { type: 'dateTime', example: '2020-01-06T17:31:55.864Z' }
|
||||||
expose :last_error
|
expose :last_error, documentation: { type: 'integer', example: 'The remote mirror URL is invalid.' }
|
||||||
expose :only_protected_branches
|
expose :only_protected_branches, documentation: { type: 'boolean' }
|
||||||
expose :keep_divergent_refs
|
expose :keep_divergent_refs, documentation: { type: 'boolean' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
module API
|
module API
|
||||||
module Entities
|
module Entities
|
||||||
class TemplatesList < Grape::Entity
|
class TemplatesList < Grape::Entity
|
||||||
expose :key
|
expose :key, documentation: { type: 'string', example: 'mit' }
|
||||||
expose :name
|
expose :name, documentation: { type: 'string', example: 'MIT License' }
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -16,8 +16,14 @@ module API
|
||||||
requires :id, type: String, desc: 'The ID of the group'
|
requires :id, type: String, desc: 'The ID of the group'
|
||||||
end
|
end
|
||||||
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
resource :groups, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
||||||
desc 'Get all clusters from the group' do
|
desc 'List group clusters' do
|
||||||
|
detail 'This feature was introduced in GitLab 12.1. Returns a list of group clusters.'
|
||||||
success Entities::Cluster
|
success Entities::Cluster
|
||||||
|
failure [
|
||||||
|
{ code: 403, message: 'Forbidden' }
|
||||||
|
]
|
||||||
|
is_array true
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
use :pagination
|
use :pagination
|
||||||
|
@ -28,8 +34,14 @@ module API
|
||||||
present paginate(clusters_for_current_user), with: Entities::Cluster
|
present paginate(clusters_for_current_user), with: Entities::Cluster
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Get specific cluster for the group' do
|
desc 'Get a single group cluster' do
|
||||||
|
detail 'This feature was introduced in GitLab 12.1. Gets a single group cluster.'
|
||||||
success Entities::ClusterGroup
|
success Entities::ClusterGroup
|
||||||
|
failure [
|
||||||
|
{ code: 403, message: 'Forbidden' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :cluster_id, type: Integer, desc: 'The cluster ID'
|
requires :cluster_id, type: Integer, desc: 'The cluster ID'
|
||||||
|
@ -40,8 +52,15 @@ module API
|
||||||
present cluster, with: Entities::ClusterGroup
|
present cluster, with: Entities::ClusterGroup
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Adds an existing cluster' do
|
desc 'Add existing cluster to group' do
|
||||||
|
detail 'This feature was introduced in GitLab 12.1. Adds an existing Kubernetes cluster to the group.'
|
||||||
success Entities::ClusterGroup
|
success Entities::ClusterGroup
|
||||||
|
failure [
|
||||||
|
{ code: 400, message: 'Validation error' },
|
||||||
|
{ code: 403, message: 'Forbidden' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :name, type: String, desc: 'Cluster name'
|
requires :name, type: String, desc: 'Cluster name'
|
||||||
|
@ -73,8 +92,15 @@ module API
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Update an existing cluster' do
|
desc 'Edit group cluster' do
|
||||||
|
detail 'This feature was introduced in GitLab 12.1. Updates an existing group cluster.'
|
||||||
success Entities::ClusterGroup
|
success Entities::ClusterGroup
|
||||||
|
failure [
|
||||||
|
{ code: 400, message: 'Validation error' },
|
||||||
|
{ code: 403, message: 'Forbidden' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :cluster_id, type: Integer, desc: 'The cluster ID'
|
requires :cluster_id, type: Integer, desc: 'The cluster ID'
|
||||||
|
@ -104,8 +130,14 @@ module API
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Remove a cluster' do
|
desc 'Delete group cluster' do
|
||||||
|
detail 'This feature was introduced in GitLab 12.1. Deletes an existing group cluster. Does not remove existing resources within the connected Kubernetes cluster.'
|
||||||
success Entities::ClusterGroup
|
success Entities::ClusterGroup
|
||||||
|
failure [
|
||||||
|
{ code: 403, message: 'Forbidden' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :cluster_id, type: Integer, desc: 'The Cluster ID'
|
requires :cluster_id, type: Integer, desc: 'The Cluster ID'
|
||||||
|
|
|
@ -17,8 +17,9 @@ module API
|
||||||
included do
|
included do
|
||||||
helpers do
|
helpers do
|
||||||
params :pagination do
|
params :pagination do
|
||||||
optional :page, type: Integer, default: 1, desc: 'Current page number'
|
optional :page, type: Integer, default: 1, desc: 'Current page number', documentation: { example: 1 }
|
||||||
optional :per_page, type: Integer, default: 20, desc: 'Number of items per page', except_values: [0]
|
optional :per_page, type: Integer, default: 20,
|
||||||
|
desc: 'Number of items per page', except_values: [0], documentation: { example: 20 }
|
||||||
end
|
end
|
||||||
|
|
||||||
def verify_pagination_params!
|
def verify_pagination_params!
|
||||||
|
|
|
@ -16,9 +16,14 @@ module API
|
||||||
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
|
requires :id, types: [String, Integer], desc: 'The ID or URL-encoded path of the project'
|
||||||
end
|
end
|
||||||
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
||||||
desc 'Get all clusters from the project' do
|
desc 'List project clusters' do
|
||||||
detail 'This feature was introduced in GitLab 11.7.'
|
detail 'This feature was introduced in GitLab 11.7. Returns a list of project clusters.'
|
||||||
success Entities::Cluster
|
success Entities::Cluster
|
||||||
|
failure [
|
||||||
|
{ code: 403, message: 'Forbidden' }
|
||||||
|
]
|
||||||
|
is_array true
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
use :pagination
|
use :pagination
|
||||||
|
@ -29,9 +34,14 @@ module API
|
||||||
present paginate(clusters_for_current_user), with: Entities::Cluster
|
present paginate(clusters_for_current_user), with: Entities::Cluster
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Get specific cluster for the project' do
|
desc 'Get a single project cluster' do
|
||||||
detail 'This feature was introduced in GitLab 11.7.'
|
detail 'This feature was introduced in GitLab 11.7. Gets a single project cluster.'
|
||||||
success Entities::ClusterProject
|
success Entities::ClusterProject
|
||||||
|
failure [
|
||||||
|
{ code: 403, message: 'Forbidden' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :cluster_id, type: Integer, desc: 'The cluster ID'
|
requires :cluster_id, type: Integer, desc: 'The cluster ID'
|
||||||
|
@ -42,9 +52,15 @@ module API
|
||||||
present cluster, with: Entities::ClusterProject
|
present cluster, with: Entities::ClusterProject
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Adds an existing cluster' do
|
desc 'Add existing cluster to project' do
|
||||||
detail 'This feature was introduced in GitLab 11.7.'
|
detail 'This feature was introduced in GitLab 11.7. Adds an existing Kubernetes cluster to the project.'
|
||||||
success Entities::ClusterProject
|
success Entities::ClusterProject
|
||||||
|
failure [
|
||||||
|
{ code: 400, message: 'Validation error' },
|
||||||
|
{ code: 403, message: 'Forbidden' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :name, type: String, desc: 'Cluster name'
|
requires :name, type: String, desc: 'Cluster name'
|
||||||
|
@ -76,9 +92,15 @@ module API
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Update an existing cluster' do
|
desc 'Edit project cluster' do
|
||||||
detail 'This feature was introduced in GitLab 11.7.'
|
detail 'This feature was introduced in GitLab 11.7. Updates an existing project cluster.'
|
||||||
success Entities::ClusterProject
|
success Entities::ClusterProject
|
||||||
|
failure [
|
||||||
|
{ code: 400, message: 'Validation error' },
|
||||||
|
{ code: 403, message: 'Forbidden' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :cluster_id, type: Integer, desc: 'The cluster ID'
|
requires :cluster_id, type: Integer, desc: 'The cluster ID'
|
||||||
|
@ -108,9 +130,14 @@ module API
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Remove a cluster' do
|
desc 'Delete project cluster' do
|
||||||
detail 'This feature was introduced in GitLab 11.7.'
|
detail 'This feature was introduced in GitLab 11.7. Deletes an existing project cluster. Does not remove existing resources within the connected Kubernetes cluster.'
|
||||||
success Entities::ClusterProject
|
success Entities::ClusterProject
|
||||||
|
failure [
|
||||||
|
{ code: 403, message: 'Forbidden' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[clusters]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :cluster_id, type: Integer, desc: 'The Cluster ID'
|
requires :cluster_id, type: Integer, desc: 'The Cluster ID'
|
||||||
|
|
|
@ -21,6 +21,12 @@ module API
|
||||||
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
||||||
desc 'Get a list of templates available to this project' do
|
desc 'Get a list of templates available to this project' do
|
||||||
detail 'This endpoint was introduced in GitLab 11.4'
|
detail 'This endpoint was introduced in GitLab 11.4'
|
||||||
|
is_array true
|
||||||
|
success Entities::TemplatesList
|
||||||
|
failure [
|
||||||
|
{ code: 401, message: 'Unauthorized' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
use :pagination
|
use :pagination
|
||||||
|
@ -33,13 +39,24 @@ module API
|
||||||
|
|
||||||
desc 'Download a template available to this project' do
|
desc 'Download a template available to this project' do
|
||||||
detail 'This endpoint was introduced in GitLab 11.4'
|
detail 'This endpoint was introduced in GitLab 11.4'
|
||||||
|
success Entities::License
|
||||||
|
failure [
|
||||||
|
{ code: 401, message: 'Unauthorized' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :name, type: String, desc: 'The name of the template'
|
requires :name, type: String,
|
||||||
|
desc: 'The key of the template, as obtained from the collection endpoint.', documentation: { example: 'MIT' }
|
||||||
optional :source_template_project_id, type: Integer,
|
optional :source_template_project_id, type: Integer,
|
||||||
desc: 'The project id where a given template is being stored. This is useful when multiple templates from different projects have the same name'
|
desc: 'The project id where a given template is being stored. This is useful when multiple templates from different projects have the same name',
|
||||||
optional :project, type: String, desc: 'The project name to use when expanding placeholders in the template. Only affects licenses'
|
documentation: { example: 1 }
|
||||||
optional :fullname, type: String, desc: 'The full name of the copyright holder to use when expanding placeholders in the template. Only affects licenses'
|
optional :project, type: String,
|
||||||
|
desc: 'The project name to use when expanding placeholders in the template. Only affects licenses',
|
||||||
|
documentation: { example: 'GitLab' }
|
||||||
|
optional :fullname, type: String,
|
||||||
|
desc: 'The full name of the copyright holder to use when expanding placeholders in the template. Only affects licenses',
|
||||||
|
documentation: { example: 'GitLab B.V.' }
|
||||||
end
|
end
|
||||||
|
|
||||||
get ':id/templates/:type/:name', requirements: TEMPLATE_NAMES_ENDPOINT_REQUIREMENTS do
|
get ':id/templates/:type/:name', requirements: TEMPLATE_NAMES_ENDPOINT_REQUIREMENTS do
|
||||||
|
|
|
@ -15,7 +15,13 @@ module API
|
||||||
end
|
end
|
||||||
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
|
||||||
desc "List the project's remote mirrors" do
|
desc "List the project's remote mirrors" do
|
||||||
success Entities::RemoteMirror
|
success code: 200, model: Entities::RemoteMirror
|
||||||
|
is_array true
|
||||||
|
failure [
|
||||||
|
{ code: 401, message: 'Unauthorized' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[remote_mirrors]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
use :pagination
|
use :pagination
|
||||||
|
@ -26,7 +32,12 @@ module API
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Get a single remote mirror' do
|
desc 'Get a single remote mirror' do
|
||||||
success Entities::RemoteMirror
|
success code: 200, model: Entities::RemoteMirror
|
||||||
|
failure [
|
||||||
|
{ code: 401, message: 'Unauthorized' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[remote_mirrors]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :mirror_id, type: String, desc: 'The ID of a remote mirror'
|
requires :mirror_id, type: String, desc: 'The ID of a remote mirror'
|
||||||
|
@ -38,13 +49,21 @@ module API
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Create remote mirror for a project' do
|
desc 'Create remote mirror for a project' do
|
||||||
success Entities::RemoteMirror
|
success code: 201, model: Entities::RemoteMirror
|
||||||
|
failure [
|
||||||
|
{ code: 400, message: 'Bad request' },
|
||||||
|
{ code: 401, message: 'Unauthorized' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[remote_mirrors]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :url, type: String, desc: 'The URL for a remote mirror'
|
requires :url, type: String, desc: 'The URL for a remote mirror', documentation: { example: 'https://*****:*****@example.com/gitlab/example.git' }
|
||||||
optional :enabled, type: Boolean, desc: 'Determines if the mirror is enabled'
|
optional :enabled, type: Boolean, desc: 'Determines if the mirror is enabled', documentation: { example: false }
|
||||||
optional :only_protected_branches, type: Boolean, desc: 'Determines if only protected branches are mirrored'
|
optional :only_protected_branches, type: Boolean, desc: 'Determines if only protected branches are mirrored',
|
||||||
optional :keep_divergent_refs, type: Boolean, desc: 'Determines if divergent refs are kept on the target'
|
documentation: { example: false }
|
||||||
|
optional :keep_divergent_refs, type: Boolean, desc: 'Determines if divergent refs are kept on the target',
|
||||||
|
documentation: { example: false }
|
||||||
end
|
end
|
||||||
post ':id/remote_mirrors' do
|
post ':id/remote_mirrors' do
|
||||||
create_params = declared_params(include_missing: false)
|
create_params = declared_params(include_missing: false)
|
||||||
|
@ -59,13 +78,21 @@ module API
|
||||||
end
|
end
|
||||||
|
|
||||||
desc 'Update the attributes of a single remote mirror' do
|
desc 'Update the attributes of a single remote mirror' do
|
||||||
success Entities::RemoteMirror
|
success code: 200, model: Entities::RemoteMirror
|
||||||
|
failure [
|
||||||
|
{ code: 400, message: 'Bad request' },
|
||||||
|
{ code: 401, message: 'Unauthorized' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[remote_mirrors]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :mirror_id, type: String, desc: 'The ID of a remote mirror'
|
requires :mirror_id, type: String, desc: 'The ID of a remote mirror'
|
||||||
optional :enabled, type: Boolean, desc: 'Determines if the mirror is enabled'
|
optional :enabled, type: Boolean, desc: 'Determines if the mirror is enabled', documentation: { example: true }
|
||||||
optional :only_protected_branches, type: Boolean, desc: 'Determines if only protected branches are mirrored'
|
optional :only_protected_branches, type: Boolean, desc: 'Determines if only protected branches are mirrored',
|
||||||
optional :keep_divergent_refs, type: Boolean, desc: 'Determines if divergent refs are kept on the target'
|
documentation: { example: false }
|
||||||
|
optional :keep_divergent_refs, type: Boolean, desc: 'Determines if divergent refs are kept on the target',
|
||||||
|
documentation: { example: false }
|
||||||
end
|
end
|
||||||
put ':id/remote_mirrors/:mirror_id' do
|
put ':id/remote_mirrors/:mirror_id' do
|
||||||
mirror = user_project.remote_mirrors.find(params[:mirror_id])
|
mirror = user_project.remote_mirrors.find(params[:mirror_id])
|
||||||
|
@ -88,6 +115,13 @@ module API
|
||||||
|
|
||||||
desc 'Delete a single remote mirror' do
|
desc 'Delete a single remote mirror' do
|
||||||
detail 'This feature was introduced in GitLab 14.10'
|
detail 'This feature was introduced in GitLab 14.10'
|
||||||
|
success code: 204
|
||||||
|
failure [
|
||||||
|
{ code: 400, message: 'Bad request' },
|
||||||
|
{ code: 401, message: 'Unauthorized' },
|
||||||
|
{ code: 404, message: 'Not found' }
|
||||||
|
]
|
||||||
|
tags %w[remote_mirrors]
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :mirror_id, type: String, desc: 'The ID of a remote mirror'
|
requires :mirror_id, type: String, desc: 'The ID of a remote mirror'
|
||||||
|
|
|
@ -433,16 +433,16 @@ module API
|
||||||
success Entities::SSHKey
|
success Entities::SSHKey
|
||||||
end
|
end
|
||||||
params do
|
params do
|
||||||
requires :id, type: Integer, desc: 'The ID of the user'
|
requires :user_id, type: Integer, desc: 'The ID of the user'
|
||||||
requires :key, type: String, desc: 'The new SSH key'
|
requires :key, type: String, desc: 'The new SSH key'
|
||||||
requires :title, type: String, desc: 'The title of the new SSH key'
|
requires :title, type: String, desc: 'The title of the new SSH key'
|
||||||
optional :expires_at, type: DateTime, desc: 'The expiration date of the SSH key in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)'
|
optional :expires_at, type: DateTime, desc: 'The expiration date of the SSH key in ISO 8601 format (YYYY-MM-DDTHH:MM:SSZ)'
|
||||||
end
|
end
|
||||||
# rubocop: disable CodeReuse/ActiveRecord
|
# rubocop: disable CodeReuse/ActiveRecord
|
||||||
post ":id/keys", feature_category: :authentication_and_authorization do
|
post ":user_id/keys", feature_category: :authentication_and_authorization do
|
||||||
authenticated_as_admin!
|
authenticated_as_admin!
|
||||||
|
|
||||||
user = User.find_by(id: params.delete(:id))
|
user = User.find_by(id: params.delete(:user_id))
|
||||||
not_found!('User') unless user
|
not_found!('User') unless user
|
||||||
|
|
||||||
key = ::Keys::CreateService.new(current_user, declared_params(include_missing: false).merge(user: user)).execute
|
key = ::Keys::CreateService.new(current_user, declared_params(include_missing: false).merge(user: user)).execute
|
||||||
|
|
|
@ -209,6 +209,12 @@ module Gitlab
|
||||||
'in the body of your migration class'
|
'in the body of your migration class'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if partition?(table_name)
|
||||||
|
raise ArgumentError, 'remove_concurrent_index can not be used on a partitioned ' \
|
||||||
|
'table. Please use remove_concurrent_partitioned_index_by_name on the partitioned table ' \
|
||||||
|
'as we need to remove the index on the parent table'
|
||||||
|
end
|
||||||
|
|
||||||
options = options.merge({ algorithm: :concurrently })
|
options = options.merge({ algorithm: :concurrently })
|
||||||
|
|
||||||
unless index_exists?(table_name, column_name, **options)
|
unless index_exists?(table_name, column_name, **options)
|
||||||
|
@ -238,6 +244,12 @@ module Gitlab
|
||||||
'in the body of your migration class'
|
'in the body of your migration class'
|
||||||
end
|
end
|
||||||
|
|
||||||
|
if partition?(table_name)
|
||||||
|
raise ArgumentError, 'remove_concurrent_index_by_name can not be used on a partitioned ' \
|
||||||
|
'table. Please use remove_concurrent_partitioned_index_by_name on the partitioned table ' \
|
||||||
|
'as we need to remove the index on the parent table'
|
||||||
|
end
|
||||||
|
|
||||||
index_name = index_name[:name] if index_name.is_a?(Hash)
|
index_name = index_name[:name] if index_name.is_a?(Hash)
|
||||||
|
|
||||||
raise 'remove_concurrent_index_by_name must get an index name as the second argument' if index_name.blank?
|
raise 'remove_concurrent_index_by_name must get an index name as the second argument' if index_name.blank?
|
||||||
|
|
|
@ -10,13 +10,17 @@ module Gitlab::UsageDataCounters
|
||||||
expanded_template_name = expand_template_name(template)
|
expanded_template_name = expand_template_name(template)
|
||||||
return unless expanded_template_name
|
return unless expanded_template_name
|
||||||
|
|
||||||
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(
|
event_name = ci_template_event_name(expanded_template_name, config_source)
|
||||||
ci_template_event_name(expanded_template_name, config_source), values: project.id
|
Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values: project.id)
|
||||||
)
|
|
||||||
|
|
||||||
namespace = project.namespace
|
namespace = project.namespace
|
||||||
if Feature.enabled?(:route_hll_to_snowplow, namespace)
|
if Feature.enabled?(:route_hll_to_snowplow, namespace)
|
||||||
Gitlab::Tracking.event(name, 'ci_templates_unique', namespace: namespace, user: user, project: project)
|
context = Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll,
|
||||||
|
event: event_name).to_context
|
||||||
|
label = 'redis_hll_counters.ci_templates.ci_templates_total_unique_counts_monthly'
|
||||||
|
Gitlab::Tracking.event(name, 'ci_templates_unique', namespace: namespace,
|
||||||
|
project: project, context: [context], user: user,
|
||||||
|
label: label)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ source 'https://rubygems.org'
|
||||||
|
|
||||||
gem 'gitlab-qa', '~> 8', '>= 8.10.1', require: 'gitlab/qa'
|
gem 'gitlab-qa', '~> 8', '>= 8.10.1', require: 'gitlab/qa'
|
||||||
gem 'activesupport', '~> 6.1.4.7' # This should stay in sync with the root's Gemfile
|
gem 'activesupport', '~> 6.1.4.7' # This should stay in sync with the root's Gemfile
|
||||||
gem 'allure-rspec', '~> 2.18.0'
|
gem 'allure-rspec', '~> 2.19.0'
|
||||||
gem 'capybara', '~> 3.38.0'
|
gem 'capybara', '~> 3.38.0'
|
||||||
gem 'capybara-screenshot', '~> 1.0.26'
|
gem 'capybara-screenshot', '~> 1.0.26'
|
||||||
gem 'rake', '~> 13', '>= 13.0.6'
|
gem 'rake', '~> 13', '>= 13.0.6'
|
||||||
|
|
|
@ -15,10 +15,10 @@ GEM
|
||||||
rack-test (>= 1.1.0, < 2.0)
|
rack-test (>= 1.1.0, < 2.0)
|
||||||
rest-client (>= 2.0.2, < 3.0)
|
rest-client (>= 2.0.2, < 3.0)
|
||||||
rspec (~> 3.8)
|
rspec (~> 3.8)
|
||||||
allure-rspec (2.18.0)
|
allure-rspec (2.19.0)
|
||||||
allure-ruby-commons (= 2.18.0)
|
allure-ruby-commons (= 2.19.0)
|
||||||
rspec-core (>= 3.8, < 4)
|
rspec-core (>= 3.8, < 4)
|
||||||
allure-ruby-commons (2.18.0)
|
allure-ruby-commons (2.19.0)
|
||||||
mime-types (>= 3.3, < 4)
|
mime-types (>= 3.3, < 4)
|
||||||
oj (>= 3.10, < 4)
|
oj (>= 3.10, < 4)
|
||||||
require_all (>= 2, < 4)
|
require_all (>= 2, < 4)
|
||||||
|
@ -184,7 +184,7 @@ GEM
|
||||||
octokit (6.0.0)
|
octokit (6.0.0)
|
||||||
faraday (>= 1, < 3)
|
faraday (>= 1, < 3)
|
||||||
sawyer (~> 0.9)
|
sawyer (~> 0.9)
|
||||||
oj (3.13.21)
|
oj (3.13.23)
|
||||||
os (1.1.4)
|
os (1.1.4)
|
||||||
parallel (1.22.1)
|
parallel (1.22.1)
|
||||||
parallel_tests (4.0.0)
|
parallel_tests (4.0.0)
|
||||||
|
@ -301,7 +301,7 @@ PLATFORMS
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
activesupport (~> 6.1.4.7)
|
activesupport (~> 6.1.4.7)
|
||||||
airborne (~> 0.3.7)
|
airborne (~> 0.3.7)
|
||||||
allure-rspec (~> 2.18.0)
|
allure-rspec (~> 2.19.0)
|
||||||
capybara (~> 3.38.0)
|
capybara (~> 3.38.0)
|
||||||
capybara-screenshot (~> 1.0.26)
|
capybara-screenshot (~> 1.0.26)
|
||||||
chemlab (~> 0.10)
|
chemlab (~> 0.10)
|
||||||
|
@ -338,4 +338,4 @@ DEPENDENCIES
|
||||||
zeitwerk (~> 2.4)
|
zeitwerk (~> 2.4)
|
||||||
|
|
||||||
BUNDLED WITH
|
BUNDLED WITH
|
||||||
2.3.24
|
2.3.25
|
||||||
|
|
|
@ -37,7 +37,9 @@ module QA
|
||||||
Page::Main::Menu.perform(&:not_signed_in?)
|
Page::Main::Menu.perform(&:not_signed_in?)
|
||||||
end
|
end
|
||||||
|
|
||||||
raise "Failed user registration attempt. Registration was expected to #{user.expect_fabrication_success ? 'succeed' : 'fail'} but #{success ? 'succeeded' : 'failed'}." unless success
|
return if success
|
||||||
|
|
||||||
|
raise "Failed user registration attempt. Registration was expected to #{user.expect_fabrication_success ? 'succeed' : 'fail'} but #{success ? 'succeeded' : 'failed'}."
|
||||||
end
|
end
|
||||||
|
|
||||||
def disable_sign_ups
|
def disable_sign_ups
|
||||||
|
|
|
@ -28,6 +28,10 @@ module QA
|
||||||
click_link(username)
|
click_link(username)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def has_username?(username)
|
||||||
|
has_element?(:user_row_content, text: username, wait: 1)
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -0,0 +1,35 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module QA
|
||||||
|
module Page
|
||||||
|
module Component
|
||||||
|
module DeleteModal
|
||||||
|
extend QA::Page::PageConcern
|
||||||
|
|
||||||
|
def self.included(base)
|
||||||
|
super
|
||||||
|
|
||||||
|
base.view 'app/assets/javascripts/projects/components/shared/delete_button.vue' do
|
||||||
|
element :confirm_name_field
|
||||||
|
element :confirm_delete_button
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def fill_confirmation_path(text)
|
||||||
|
fill_element(:confirm_name_field, text)
|
||||||
|
end
|
||||||
|
|
||||||
|
def wait_for_delete_button_enabled
|
||||||
|
wait_until(reload: false) do
|
||||||
|
!find_element(:confirm_delete_button).disabled?
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def confirm_delete
|
||||||
|
wait_for_delete_button_enabled
|
||||||
|
click_element(:confirm_delete_button)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -16,6 +16,10 @@ module QA
|
||||||
base.view 'app/assets/javascripts/groups/components/groups.vue' do
|
base.view 'app/assets/javascripts/groups/components/groups.vue' do
|
||||||
element :groups_list_tree_container
|
element :groups_list_tree_container
|
||||||
end
|
end
|
||||||
|
|
||||||
|
base.view 'app/views/dashboard/_groups_head.html.haml' do
|
||||||
|
element :public_groups_tab
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
@ -28,9 +32,24 @@ module QA
|
||||||
# groups_list_tree_container means we have the complete filtered list
|
# groups_list_tree_container means we have the complete filtered list
|
||||||
# of groups
|
# of groups
|
||||||
has_element?(:groups_list_tree_container, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
|
has_element?(:groups_list_tree_container, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
|
||||||
|
|
||||||
# If there are no groups we'll know immediately because we filtered the list
|
# If there are no groups we'll know immediately because we filtered the list
|
||||||
return false if page.has_text?('No groups or projects matched your search', wait: 0)
|
if page.has_text?('No groups or projects matched your search',
|
||||||
|
wait: 0) || page.has_text?('No groups matched your search', wait: 0)
|
||||||
|
return false unless has_element?(:public_groups_tab)
|
||||||
|
|
||||||
|
# Try for public groups
|
||||||
|
click_element(:public_groups_tab)
|
||||||
|
# Filter and submit to reload the page and only retrieve the filtered results
|
||||||
|
find_element(:groups_filter_field).set(name).send_keys(:return)
|
||||||
|
|
||||||
|
# Since we submitted after filtering, the presence of
|
||||||
|
# groups_list_tree_container means we have the complete filtered list
|
||||||
|
# of groups
|
||||||
|
has_element?(:groups_list_tree_container, wait: QA::Support::Repeater::DEFAULT_MAX_WAIT_TIME)
|
||||||
|
|
||||||
|
return false if page.has_text?('No groups or projects matched your search',
|
||||||
|
wait: 0) || page.has_text?('No groups matched your search', wait: 0)
|
||||||
|
end
|
||||||
|
|
||||||
# The name will be present as filter input so we check for a link, not text
|
# The name will be present as filter input so we check for a link, not text
|
||||||
page.has_link?(name, wait: 0)
|
page.has_link?(name, wait: 0)
|
||||||
|
|
|
@ -31,7 +31,7 @@ module QA
|
||||||
end
|
end
|
||||||
|
|
||||||
def create
|
def create
|
||||||
click_button 'Create group'
|
click_element(:create_group_button)
|
||||||
end
|
end
|
||||||
|
|
||||||
def create_subgroup
|
def create_subgroup
|
||||||
|
|
|
@ -64,6 +64,8 @@ module QA
|
||||||
end
|
end
|
||||||
|
|
||||||
def add_description(description)
|
def add_description(description)
|
||||||
|
return unless has_element?(:project_description, wait: 1)
|
||||||
|
|
||||||
fill_in 'project_description', with: description
|
fill_in 'project_description', with: description
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -6,8 +6,13 @@ module QA
|
||||||
module Settings
|
module Settings
|
||||||
class Advanced < Page::Base
|
class Advanced < Page::Base
|
||||||
include QA::Page::Component::ConfirmModal
|
include QA::Page::Component::ConfirmModal
|
||||||
|
include QA::Page::Component::DeleteModal
|
||||||
include Component::NamespaceSelect
|
include Component::NamespaceSelect
|
||||||
|
|
||||||
|
view 'app/assets/javascripts/projects/components/shared/delete_button.vue' do
|
||||||
|
element :delete_button
|
||||||
|
end
|
||||||
|
|
||||||
view 'app/views/projects/edit.html.haml' do
|
view 'app/views/projects/edit.html.haml' do
|
||||||
element :project_path_field
|
element :project_path_field
|
||||||
element :change_path_button
|
element :change_path_button
|
||||||
|
@ -88,6 +93,13 @@ module QA
|
||||||
click_confirmation_ok_button
|
click_confirmation_ok_button
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def delete_project!(project_name)
|
||||||
|
click_element :delete_button
|
||||||
|
fill_confirmation_path(project_name)
|
||||||
|
wait_for_delete_button_enabled
|
||||||
|
confirm_delete
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def wait_for_transfer_project_content
|
def wait_for_transfer_project_content
|
||||||
|
|
|
@ -22,8 +22,20 @@ module QA
|
||||||
new.tap(&prepare_block)
|
new.tap(&prepare_block)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def fabricate_via_api_unless_fips!
|
||||||
|
if QA::Support::FIPS.enabled?
|
||||||
|
fabricate!
|
||||||
|
else
|
||||||
|
fabricate_via_api!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def fabricate!(*args, &prepare_block)
|
def fabricate!(*args, &prepare_block)
|
||||||
fabricate_via_api!(*args, &prepare_block)
|
if QA::Support::FIPS.enabled?
|
||||||
|
fabricate_via_browser_ui!(*args, &prepare_block)
|
||||||
|
else
|
||||||
|
fabricate_via_api!(*args, &prepare_block)
|
||||||
|
end
|
||||||
rescue NotImplementedError
|
rescue NotImplementedError
|
||||||
fabricate_via_browser_ui!(*args, &prepare_block)
|
fabricate_via_browser_ui!(*args, &prepare_block)
|
||||||
end
|
end
|
||||||
|
@ -95,7 +107,7 @@ module QA
|
||||||
|
|
||||||
Support::FabricationTracker.save_fabrication(:"#{fabrication_method}_fabrication", fabrication_time)
|
Support::FabricationTracker.save_fabrication(:"#{fabrication_method}_fabrication", fabrication_time)
|
||||||
|
|
||||||
unless resource.retrieved_from_cache
|
unless resource.retrieved_from_cache || QA::Support::FIPS.enabled?
|
||||||
Tools::TestResourceDataProcessor.collect(
|
Tools::TestResourceDataProcessor.collect(
|
||||||
resource: resource,
|
resource: resource,
|
||||||
info: resource.identifier,
|
info: resource.identifier,
|
||||||
|
|
|
@ -18,8 +18,14 @@ module QA
|
||||||
end
|
end
|
||||||
|
|
||||||
attribute :sandbox do
|
attribute :sandbox do
|
||||||
Sandbox.fabricate_via_api! do |sandbox|
|
if QA::Support::FIPS.enabled?
|
||||||
sandbox.api_client = api_client
|
Resource::Sandbox.fabricate! do |sandbox|
|
||||||
|
sandbox.path = Runtime::Namespace.sandbox_name
|
||||||
|
end
|
||||||
|
else
|
||||||
|
Sandbox.fabricate_via_api! do |sandbox|
|
||||||
|
sandbox.api_client = api_client
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -10,8 +10,8 @@ module QA
|
||||||
def add_member(user, access_level = AccessLevel::DEVELOPER)
|
def add_member(user, access_level = AccessLevel::DEVELOPER)
|
||||||
Support::Retrier.retry_until do
|
Support::Retrier.retry_until do
|
||||||
QA::Runtime::Logger.info(%(Adding user #{user.username} to #{full_path} #{self.class.name}))
|
QA::Runtime::Logger.info(%(Adding user #{user.username} to #{full_path} #{self.class.name}))
|
||||||
|
response = post Runtime::API::Request.new(api_client, api_members_path).url,
|
||||||
response = post Runtime::API::Request.new(api_client, api_members_path).url, { user_id: user.id, access_level: access_level }
|
{ user_id: user.id, access_level: access_level }
|
||||||
break true if response.code == QA::Support::API::HTTP_STATUS_CREATED
|
break true if response.code == QA::Support::API::HTTP_STATUS_CREATED
|
||||||
break true if response.body.include?('Member already exists')
|
break true if response.body.include?('Member already exists')
|
||||||
end
|
end
|
||||||
|
@ -31,7 +31,8 @@ module QA
|
||||||
Support::Retrier.retry_until do
|
Support::Retrier.retry_until do
|
||||||
QA::Runtime::Logger.info(%(Sharing #{self.class.name} with #{group.name}))
|
QA::Runtime::Logger.info(%(Sharing #{self.class.name} with #{group.name}))
|
||||||
|
|
||||||
response = post Runtime::API::Request.new(api_client, api_share_path).url, { group_id: group.id, group_access: access_level }
|
response = post Runtime::API::Request.new(api_client, api_share_path).url,
|
||||||
|
{ group_id: group.id, group_access: access_level }
|
||||||
response.code == QA::Support::API::HTTP_STATUS_CREATED
|
response.code == QA::Support::API::HTTP_STATUS_CREATED
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -479,6 +479,16 @@ module QA
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def remove_via_browser_ui!
|
||||||
|
Page::Project::Menu.perform(&:go_to_general_settings)
|
||||||
|
|
||||||
|
Page::Project::Settings::Main.perform(&:expand_advanced_settings)
|
||||||
|
|
||||||
|
Page::Project::Settings::Advanced.perform do |advanced|
|
||||||
|
advanced.delete_project!(full_path)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
# Calls the API endpoint that triggers the backend service that performs repository housekeeping (garbage
|
# Calls the API endpoint that triggers the backend service that performs repository housekeeping (garbage
|
||||||
# collection and similar tasks).
|
# collection and similar tasks).
|
||||||
def perform_housekeeping
|
def perform_housekeeping
|
||||||
|
|
|
@ -10,7 +10,9 @@ module QA
|
||||||
class << self
|
class << self
|
||||||
# Force top level group creation via UI if test is executed on dot_com environment
|
# Force top level group creation via UI if test is executed on dot_com environment
|
||||||
def fabricate!(*args, &prepare_block)
|
def fabricate!(*args, &prepare_block)
|
||||||
return fabricate_via_browser_ui!(*args, &prepare_block) if Specs::Helpers::ContextSelector.dot_com?
|
if Specs::Helpers::ContextSelector.dot_com? || QA::Support::FIPS.enabled?
|
||||||
|
return fabricate_via_browser_ui!(*args, &prepare_block)
|
||||||
|
end
|
||||||
|
|
||||||
fabricate_via_api!(*args, &prepare_block)
|
fabricate_via_api!(*args, &prepare_block)
|
||||||
rescue NotImplementedError
|
rescue NotImplementedError
|
||||||
|
|
|
@ -79,11 +79,22 @@ module QA
|
||||||
defined?(@username) && defined?(@password)
|
defined?(@username) && defined?(@password)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def has_user?(user)
|
||||||
|
Flow::Login.while_signed_in_as_admin do
|
||||||
|
Page::Main::Menu.perform(&:go_to_admin_area)
|
||||||
|
Page::Admin::Menu.perform(&:go_to_users_overview)
|
||||||
|
Page::Admin::Overview::Users::Index.perform do |index|
|
||||||
|
index.search_user(user.username)
|
||||||
|
index.has_username?(user.username)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def fabricate!
|
def fabricate!
|
||||||
# Don't try to log-out if we're not logged-in
|
# Don't try to log-out if we're not logged-in
|
||||||
Page::Main::Menu.perform(&:sign_out) if Page::Main::Menu.perform { |p| p.has_personal_area?(wait: 0) }
|
Page::Main::Menu.perform(&:sign_out) if Page::Main::Menu.perform { |p| p.has_personal_area?(wait: 0) }
|
||||||
|
|
||||||
if credentials_given?
|
if credentials_given? || has_user?(self)
|
||||||
Page::Main::Login.perform do |login|
|
Page::Main::Login.perform do |login|
|
||||||
login.sign_in_using_credentials(user: self)
|
login.sign_in_using_credentials(user: self)
|
||||||
end
|
end
|
||||||
|
@ -144,7 +155,7 @@ module QA
|
||||||
end
|
end
|
||||||
|
|
||||||
def self.fabricate_or_use(username = nil, password = nil)
|
def self.fabricate_or_use(username = nil, password = nil)
|
||||||
if Runtime::Env.signup_disabled?
|
if Runtime::Env.signup_disabled? || !QA::Support::FIPS.enabled?
|
||||||
fabricate_via_api! do |user|
|
fabricate_via_api! do |user|
|
||||||
user.username = username
|
user.username = username
|
||||||
user.password = password
|
user.password = password
|
||||||
|
|
|
@ -4,8 +4,8 @@ module QA
|
||||||
module Runtime
|
module Runtime
|
||||||
module Key
|
module Key
|
||||||
class ED25519 < Base
|
class ED25519 < Base
|
||||||
def initialize
|
def initialize(bits = 256)
|
||||||
super('ed25519', 256)
|
super('ed25519', bits)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,8 +3,17 @@
|
||||||
module QA
|
module QA
|
||||||
RSpec.describe 'Plan', :smoke, product_group: :project_management do
|
RSpec.describe 'Plan', :smoke, product_group: :project_management do
|
||||||
describe 'Issue creation' do
|
describe 'Issue creation' do
|
||||||
let(:project) { Resource::Project.fabricate_via_api! }
|
let(:project) do
|
||||||
let(:closed_issue) { Resource::Issue.fabricate_via_api! { |issue| issue.project = project } }
|
Resource::Project.fabricate_via_api_unless_fips! do |project|
|
||||||
|
project.name = "project-create-issue-#{SecureRandom.hex(8)}"
|
||||||
|
project.personal_namespace = Runtime::User.username
|
||||||
|
project.description = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
let(:closed_issue) do
|
||||||
|
Resource::Issue.fabricate_via_api_unless_fips! { |issue| issue.project = project }
|
||||||
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
Flow::Login.sign_in
|
Flow::Login.sign_in
|
||||||
|
@ -55,7 +64,7 @@ module QA
|
||||||
end
|
end
|
||||||
|
|
||||||
before do
|
before do
|
||||||
Resource::Issue.fabricate_via_api! { |issue| issue.project = project }.visit!
|
Resource::Issue.fabricate_via_api_unless_fips! { |issue| issue.project = project }.visit!
|
||||||
end
|
end
|
||||||
|
|
||||||
# The following example is excluded from running in `review-qa-smoke` job
|
# The following example is excluded from running in `review-qa-smoke` job
|
||||||
|
|
|
@ -3,9 +3,12 @@
|
||||||
module QA
|
module QA
|
||||||
RSpec.describe 'Plan', :smoke, product_group: :project_management do
|
RSpec.describe 'Plan', :smoke, product_group: :project_management do
|
||||||
describe 'mention' do
|
describe 'mention' do
|
||||||
let(:user) { Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1) }
|
let(:user) do
|
||||||
|
Resource::User.fabricate_or_use(Runtime::Env.gitlab_qa_username_1, Runtime::Env.gitlab_qa_password_1)
|
||||||
|
end
|
||||||
|
|
||||||
let(:project) do
|
let(:project) do
|
||||||
Resource::Project.fabricate_via_api! do |project|
|
Resource::Project.fabricate_via_api_unless_fips! do |project|
|
||||||
project.name = 'project-to-test-mention'
|
project.name = 'project-to-test-mention'
|
||||||
project.visibility = 'private'
|
project.visibility = 'private'
|
||||||
end
|
end
|
||||||
|
@ -14,14 +17,33 @@ module QA
|
||||||
before do
|
before do
|
||||||
Flow::Login.sign_in
|
Flow::Login.sign_in
|
||||||
|
|
||||||
project.add_member(user)
|
if QA::Support::FIPS.enabled?
|
||||||
|
# Ensure user exists
|
||||||
|
user
|
||||||
|
Flow::Login.sign_in_as_admin
|
||||||
|
project.visit!
|
||||||
|
Page::Project::Menu.perform(&:click_members)
|
||||||
|
Page::Project::Members.perform do |members|
|
||||||
|
members.add_member(user.username)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
project.visit!
|
||||||
|
project.add_member(user)
|
||||||
|
end
|
||||||
|
|
||||||
Resource::Issue.fabricate_via_api! do |issue|
|
if QA::Support::FIPS.enabled?
|
||||||
issue.project = project
|
Resource::Issue.fabricate_via_browser_ui! do |issue|
|
||||||
end.visit!
|
issue.project = project
|
||||||
|
end.visit!
|
||||||
|
else
|
||||||
|
Resource::Issue.fabricate_via_api! do |issue|
|
||||||
|
issue.project = project
|
||||||
|
end.visit!
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'mentions another user in an issue', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347988' do
|
it 'mentions another user in an issue',
|
||||||
|
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347988' do
|
||||||
Page::Project::Issue::Show.perform do |show|
|
Page::Project::Issue::Show.perform do |show|
|
||||||
at_username = "@#{user.username}"
|
at_username = "@#{user.username}"
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,7 @@ module QA
|
||||||
|
|
||||||
it(
|
it(
|
||||||
'creates a basic merge request',
|
'creates a basic merge request',
|
||||||
:smoke,
|
:smoke, :skip_fips_env,
|
||||||
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347738'
|
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347738'
|
||||||
) do
|
) do
|
||||||
Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
|
Resource::MergeRequest.fabricate_via_browser_ui! do |merge_request|
|
||||||
|
|
|
@ -2,8 +2,9 @@
|
||||||
|
|
||||||
module QA
|
module QA
|
||||||
RSpec.describe 'Create' do
|
RSpec.describe 'Create' do
|
||||||
describe 'Git push over HTTP', :smoke, product_group: :source_code do
|
describe 'Git push over HTTP', :smoke, :skip_fips_env, product_group: :source_code do
|
||||||
it 'user using a personal access token pushes code to the repository', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347749' do
|
it 'user using a personal access token pushes code to the repository',
|
||||||
|
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347749' do
|
||||||
Flow::Login.sign_in
|
Flow::Login.sign_in
|
||||||
|
|
||||||
access_token = Resource::PersonalAccessToken.fabricate!.token
|
access_token = Resource::PersonalAccessToken.fabricate!.token
|
||||||
|
|
|
@ -3,7 +3,8 @@
|
||||||
module QA
|
module QA
|
||||||
RSpec.describe 'Create' do
|
RSpec.describe 'Create' do
|
||||||
describe 'Git push over HTTP', product_group: :source_code do
|
describe 'Git push over HTTP', product_group: :source_code do
|
||||||
it 'user pushes code to the repository', :smoke, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347747' do
|
it 'user pushes code to the repository', :smoke, :skip_fips_env,
|
||||||
|
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347747' do
|
||||||
Flow::Login.sign_in
|
Flow::Login.sign_in
|
||||||
|
|
||||||
Resource::Repository::ProjectPush.fabricate! do |push|
|
Resource::Repository::ProjectPush.fabricate! do |push|
|
||||||
|
@ -18,7 +19,8 @@ module QA
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'pushes to a project using a specific Praefect repository storage', :smoke, :requires_admin, :requires_praefect, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347789' do
|
it 'pushes to a project using a specific Praefect repository storage', :smoke, :skip_fips_env, :requires_admin,
|
||||||
|
:requires_praefect, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347789' do
|
||||||
Flow::Login.sign_in_as_admin
|
Flow::Login.sign_in_as_admin
|
||||||
|
|
||||||
project = Resource::Project.fabricate_via_api! do |storage_project|
|
project = Resource::Project.fabricate_via_api! do |storage_project|
|
||||||
|
|
|
@ -26,7 +26,8 @@ module QA
|
||||||
Flow::Login.sign_in
|
Flow::Login.sign_in
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'pushes code to the repository via SSH', :smoke, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347825' do
|
it 'pushes code to the repository via SSH', :smoke, :skip_fips_env,
|
||||||
|
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347825' do
|
||||||
Resource::Repository::ProjectPush.fabricate! do |push|
|
Resource::Repository::ProjectPush.fabricate! do |push|
|
||||||
push.project = project
|
push.project = project
|
||||||
push.ssh_key = @key
|
push.ssh_key = @key
|
||||||
|
@ -41,7 +42,8 @@ module QA
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'pushes multiple branches and tags together', :smoke, testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347826' do
|
it 'pushes multiple branches and tags together', :smoke, :skip_fips_env,
|
||||||
|
testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347826' do
|
||||||
branches = []
|
branches = []
|
||||||
tags = []
|
tags = []
|
||||||
Git::Repository.perform do |repository|
|
Git::Repository.perform do |repository|
|
||||||
|
|
|
@ -17,6 +17,15 @@ module QA
|
||||||
Flow::Login.sign_in
|
Flow::Login.sign_in
|
||||||
end
|
end
|
||||||
|
|
||||||
|
after do
|
||||||
|
if QA::Support::FIPS.enabled?
|
||||||
|
snippet.visit!
|
||||||
|
Page::Dashboard::Snippet::Show.perform(&:click_delete_button)
|
||||||
|
else
|
||||||
|
snippet.remove_via_api!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
it 'user creates a personal snippet', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347799' do
|
it 'user creates a personal snippet', testcase: 'https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/347799' do
|
||||||
snippet
|
snippet
|
||||||
|
|
||||||
|
|
|
@ -4,7 +4,7 @@ module QA
|
||||||
RSpec.describe 'Verify' do
|
RSpec.describe 'Verify' do
|
||||||
describe 'Add or Remove CI variable via UI', :smoke, product_group: :pipeline_authoring do
|
describe 'Add or Remove CI variable via UI', :smoke, product_group: :pipeline_authoring do
|
||||||
let(:project) do
|
let(:project) do
|
||||||
Resource::Project.fabricate_via_api! do |project|
|
Resource::Project.fabricate_via_api_unless_fips! do |project|
|
||||||
project.name = 'project-with-ci-variables'
|
project.name = 'project-with-ci-variables'
|
||||||
project.description = 'project with CI variables'
|
project.description = 'project with CI variables'
|
||||||
end
|
end
|
||||||
|
|
|
@ -35,7 +35,7 @@ module QA
|
||||||
keys = [
|
keys = [
|
||||||
['https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348022', Runtime::Key::RSA, 8192, true],
|
['https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348022', Runtime::Key::RSA, 8192, true],
|
||||||
['https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348021', Runtime::Key::ECDSA, 521, true],
|
['https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348021', Runtime::Key::ECDSA, 521, true],
|
||||||
['https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348020', Runtime::Key::ED25519, false]
|
['https://gitlab.com/gitlab-org/gitlab/-/quality/test_cases/348020', Runtime::Key::ED25519, 256, false]
|
||||||
]
|
]
|
||||||
|
|
||||||
supported_keys =
|
supported_keys =
|
||||||
|
|
|
@ -5,7 +5,7 @@ module QA
|
||||||
module Support
|
module Support
|
||||||
class FIPS
|
class FIPS
|
||||||
def self.enabled?
|
def self.enabled?
|
||||||
%(1 true yes).include?(ENV['FIPS'].to_s)
|
%w[1 true yes].include?(ENV['FIPS'].to_s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -87,12 +87,46 @@ RSpec.describe QA::Resource::Base do
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'when resource supports fabrication via the API' do
|
context 'when resource supports fabrication via the API' do
|
||||||
it 'calls .fabricate_via_browser_ui!' do
|
it 'calls .fabricate_via_api!!' do
|
||||||
expect(described_class).to receive(:fabricate_via_api!)
|
expect(described_class).to receive(:fabricate_via_api!)
|
||||||
|
|
||||||
described_class.fabricate!
|
described_class.fabricate!
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when FIPS mode is enabled' do
|
||||||
|
before do
|
||||||
|
stub_env('FIPS', '1')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'calls .fabricate_via_browser_ui!' do
|
||||||
|
expect(described_class).to receive(:fabricate_via_browser_ui!)
|
||||||
|
|
||||||
|
described_class.fabricate!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
describe '.fabricate_via_api_unless_fips!' do
|
||||||
|
context 'when FIPS mode is not enabled' do
|
||||||
|
it 'calls .fabricate_via_api!!' do
|
||||||
|
expect(described_class).to receive(:fabricate_via_api!)
|
||||||
|
|
||||||
|
described_class.fabricate_via_api_unless_fips!
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when FIPS mode is enabled' do
|
||||||
|
before do
|
||||||
|
stub_env('FIPS', '1')
|
||||||
|
end
|
||||||
|
|
||||||
|
it 'calls .fabricate_via_browser_ui!' do
|
||||||
|
expect(described_class).to receive(:fabricate_via_browser_ui!)
|
||||||
|
|
||||||
|
described_class.fabricate_via_api_unless_fips!
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
describe '.fabricate_via_api!' do
|
describe '.fabricate_via_api!' do
|
||||||
|
|
|
@ -116,4 +116,31 @@ RSpec.describe QA::Resource::User do
|
||||||
expect(subject).to be_credentials_given
|
expect(subject).to be_credentials_given
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe '#has_user?' do
|
||||||
|
let(:index_mock) do
|
||||||
|
instance_double(QA::Page::Admin::Overview::Users::Index)
|
||||||
|
end
|
||||||
|
|
||||||
|
users = [
|
||||||
|
['foo', true],
|
||||||
|
['bar', false]
|
||||||
|
]
|
||||||
|
|
||||||
|
users.each do |(username, found)|
|
||||||
|
it "returns #{found} when has_username returns #{found}" do
|
||||||
|
subject.username = username
|
||||||
|
|
||||||
|
allow(QA::Flow::Login).to receive(:while_signed_in_as_admin).and_yield
|
||||||
|
allow(QA::Page::Main::Menu).to receive(:perform)
|
||||||
|
allow(QA::Page::Admin::Menu).to receive(:perform)
|
||||||
|
allow(QA::Page::Admin::Overview::Users::Index).to receive(:perform).and_yield(index_mock)
|
||||||
|
|
||||||
|
expect(index_mock).to receive(:search_user).with(username)
|
||||||
|
expect(index_mock).to receive(:has_username?).with(username).and_return(found)
|
||||||
|
|
||||||
|
expect(subject.has_user?(subject)).to eq(found)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -8,8 +8,13 @@ fi
|
||||||
|
|
||||||
# Tag with commit SHA by default
|
# Tag with commit SHA by default
|
||||||
QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/${QA_IMAGE_NAME}:${CI_COMMIT_SHA}"
|
QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/${QA_IMAGE_NAME}:${CI_COMMIT_SHA}"
|
||||||
|
|
||||||
# For branches, tag with slugified branch name. For tags, use the tag directly
|
# For branches, tag with slugified branch name. For tags, use the tag directly
|
||||||
QA_IMAGE_BRANCH="${CI_REGISTRY}/${CI_PROJECT_PATH}/${QA_IMAGE_NAME}:${CI_COMMIT_TAG:-$CI_COMMIT_REF_SLUG}"
|
# with v prefix removed
|
||||||
|
IMAGE_TAG=${CI_COMMIT_TAG#v}
|
||||||
|
IMAGE_TAG=${IMAGE_TAG:-$CI_COMMIT_REF_SLUG}
|
||||||
|
|
||||||
|
QA_IMAGE_BRANCH="${CI_REGISTRY}/${CI_PROJECT_PATH}/${QA_IMAGE_NAME}:${IMAGE_TAG}"
|
||||||
|
|
||||||
DESTINATIONS="--destination=${QA_IMAGE} --destination=${QA_IMAGE_BRANCH}"
|
DESTINATIONS="--destination=${QA_IMAGE} --destination=${QA_IMAGE_BRANCH}"
|
||||||
|
|
||||||
|
|
|
@ -14,6 +14,8 @@ main_report = JSON.parse(File.read(main_report_file))
|
||||||
new_report = main_report.dup
|
new_report = main_report.dup
|
||||||
|
|
||||||
ARGV.each do |report_file|
|
ARGV.each do |report_file|
|
||||||
|
next unless File.exist?(report_file)
|
||||||
|
|
||||||
report = JSON.parse(File.read(report_file))
|
report = JSON.parse(File.read(report_file))
|
||||||
|
|
||||||
# Remove existing values
|
# Remove existing values
|
||||||
|
|
|
@ -60,6 +60,9 @@ function update_tests_metadata() {
|
||||||
scripts/flaky_examples/prune-old-flaky-examples "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
|
scripts/flaky_examples/prune-old-flaky-examples "${FLAKY_RSPEC_SUITE_REPORT_PATH}"
|
||||||
|
|
||||||
if [[ "$CI_PIPELINE_SOURCE" == "schedule" ]]; then
|
if [[ "$CI_PIPELINE_SOURCE" == "schedule" ]]; then
|
||||||
|
if [[ -n "$RSPEC_PROFILING_PGSSLKEY" ]]; then
|
||||||
|
chmod 0600 $RSPEC_PROFILING_PGSSLKEY
|
||||||
|
fi
|
||||||
PGSSLMODE=$RSPEC_PROFILING_PGSSLMODE PGSSLROOTCERT=$RSPEC_PROFILING_PGSSLROOTCERT PGSSLCERT=$RSPEC_PROFILING_PGSSLCERT PGSSLKEY=$RSPEC_PROFILING_PGSSLKEY scripts/insert-rspec-profiling-data
|
PGSSLMODE=$RSPEC_PROFILING_PGSSLMODE PGSSLROOTCERT=$RSPEC_PROFILING_PGSSLROOTCERT PGSSLCERT=$RSPEC_PROFILING_PGSSLCERT PGSSLKEY=$RSPEC_PROFILING_PGSSLKEY scripts/insert-rspec-profiling-data
|
||||||
else
|
else
|
||||||
echo "Not inserting profiling data as the pipeline is not a scheduled one."
|
echo "Not inserting profiling data as the pipeline is not a scheduled one."
|
||||||
|
|
|
@ -19,6 +19,7 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
|
||||||
<gl-button-stub
|
<gl-button-stub
|
||||||
buttontextclasses=""
|
buttontextclasses=""
|
||||||
category="primary"
|
category="primary"
|
||||||
|
data-qa-selector="delete_button"
|
||||||
icon=""
|
icon=""
|
||||||
role="button"
|
role="button"
|
||||||
size="medium"
|
size="medium"
|
||||||
|
@ -102,6 +103,7 @@ exports[`Project remove modal initialized matches the snapshot 1`] = `
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<gl-form-input-stub
|
<gl-form-input-stub
|
||||||
|
data-qa-selector="confirm_name_field"
|
||||||
id="confirm_name_input"
|
id="confirm_name_input"
|
||||||
name="confirm_name_input"
|
name="confirm_name_input"
|
||||||
type="text"
|
type="text"
|
||||||
|
|
|
@ -20,6 +20,7 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
|
||||||
<gl-button-stub
|
<gl-button-stub
|
||||||
buttontextclasses=""
|
buttontextclasses=""
|
||||||
category="primary"
|
category="primary"
|
||||||
|
data-qa-selector="delete_button"
|
||||||
icon=""
|
icon=""
|
||||||
role="button"
|
role="button"
|
||||||
size="medium"
|
size="medium"
|
||||||
|
@ -103,6 +104,7 @@ exports[`Project remove modal intialized matches the snapshot 1`] = `
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
<gl-form-input-stub
|
<gl-form-input-stub
|
||||||
|
data-qa-selector="confirm_name_field"
|
||||||
id="confirm_name_input"
|
id="confirm_name_input"
|
||||||
name="confirm_name_input"
|
name="confirm_name_input"
|
||||||
type="text"
|
type="text"
|
||||||
|
|
|
@ -44,7 +44,7 @@ exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have
|
||||||
class="gl-display-flex gl-w-full"
|
class="gl-display-flex gl-w-full"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="media-body gl-display-flex"
|
class="media-body gl-display-flex gl-align-items-center"
|
||||||
>
|
>
|
||||||
|
|
||||||
<h4
|
<h4
|
||||||
|
@ -70,7 +70,7 @@ exports[`MRWidgetAutoMergeEnabled when graphql is disabled template should have
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="gl-display-flex gl-md-display-block gl-font-size-0 gl-ml-auto"
|
class="gl-display-flex gl-font-size-0 gl-ml-auto gl-gap-3"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="gl-display-flex gl-align-items-flex-start"
|
class="gl-display-flex gl-align-items-flex-start"
|
||||||
|
@ -221,7 +221,7 @@ exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have c
|
||||||
class="gl-display-flex gl-w-full"
|
class="gl-display-flex gl-w-full"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="media-body gl-display-flex"
|
class="media-body gl-display-flex gl-align-items-center"
|
||||||
>
|
>
|
||||||
|
|
||||||
<h4
|
<h4
|
||||||
|
@ -247,7 +247,7 @@ exports[`MRWidgetAutoMergeEnabled when graphql is enabled template should have c
|
||||||
</h4>
|
</h4>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="gl-display-flex gl-md-display-block gl-font-size-0 gl-ml-auto"
|
class="gl-display-flex gl-font-size-0 gl-ml-auto gl-gap-3"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="gl-display-flex gl-align-items-flex-start"
|
class="gl-display-flex gl-align-items-flex-start"
|
||||||
|
|
|
@ -469,6 +469,37 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
|
||||||
model.remove_concurrent_index(:users, :foo)
|
model.remove_concurrent_index(:users, :foo)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when targeting a partition table' do
|
||||||
|
let(:schema) { 'public' }
|
||||||
|
let(:partition_table_name) { '_test_partition_01' }
|
||||||
|
let(:identifier) { "#{schema}.#{partition_table_name}" }
|
||||||
|
let(:index_name) { '_test_partitioned_index' }
|
||||||
|
let(:partition_index_name) { '_test_partition_01_partition_id_idx' }
|
||||||
|
let(:column_name) { 'partition_id' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
model.execute(<<~SQL)
|
||||||
|
CREATE TABLE public._test_partitioned_table (
|
||||||
|
id serial NOT NULL,
|
||||||
|
partition_id serial NOT NULL,
|
||||||
|
PRIMARY KEY (id, partition_id)
|
||||||
|
) PARTITION BY LIST(partition_id);
|
||||||
|
|
||||||
|
CREATE INDEX #{index_name} ON public._test_partitioned_table(#{column_name});
|
||||||
|
|
||||||
|
CREATE TABLE #{identifier} PARTITION OF public._test_partitioned_table
|
||||||
|
FOR VALUES IN (1);
|
||||||
|
SQL
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when dropping an index on the partition table' do
|
||||||
|
it 'raises ArgumentError' do
|
||||||
|
expect { model.remove_concurrent_index(partition_table_name, column_name) }
|
||||||
|
.to raise_error(ArgumentError, /use remove_concurrent_partitioned_index_by_name/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe 'by index name' do
|
describe 'by index name' do
|
||||||
before do
|
before do
|
||||||
allow(model).to receive(:index_exists_by_name?).with(:users, "index_x_by_y").and_return(true)
|
allow(model).to receive(:index_exists_by_name?).with(:users, "index_x_by_y").and_return(true)
|
||||||
|
@ -510,6 +541,36 @@ RSpec.describe Gitlab::Database::MigrationHelpers do
|
||||||
|
|
||||||
model.remove_concurrent_index_by_name(:users, "index_x_by_y")
|
model.remove_concurrent_index_by_name(:users, "index_x_by_y")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
context 'when targeting a partition table' do
|
||||||
|
let(:schema) { 'public' }
|
||||||
|
let(:partition_table_name) { '_test_partition_01' }
|
||||||
|
let(:identifier) { "#{schema}.#{partition_table_name}" }
|
||||||
|
let(:index_name) { '_test_partitioned_index' }
|
||||||
|
let(:partition_index_name) { '_test_partition_01_partition_id_idx' }
|
||||||
|
|
||||||
|
before do
|
||||||
|
model.execute(<<~SQL)
|
||||||
|
CREATE TABLE public._test_partitioned_table (
|
||||||
|
id serial NOT NULL,
|
||||||
|
partition_id serial NOT NULL,
|
||||||
|
PRIMARY KEY (id, partition_id)
|
||||||
|
) PARTITION BY LIST(partition_id);
|
||||||
|
|
||||||
|
CREATE INDEX #{index_name} ON public._test_partitioned_table(partition_id);
|
||||||
|
|
||||||
|
CREATE TABLE #{identifier} PARTITION OF public._test_partitioned_table
|
||||||
|
FOR VALUES IN (1);
|
||||||
|
SQL
|
||||||
|
end
|
||||||
|
|
||||||
|
context 'when dropping an index on the partition table' do
|
||||||
|
it 'raises ArgumentError' do
|
||||||
|
expect { model.remove_concurrent_index_by_name(partition_table_name, partition_index_name) }
|
||||||
|
.to raise_error(ArgumentError, /use remove_concurrent_partitioned_index_by_name/)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
|
@ -3,8 +3,10 @@
|
||||||
require 'spec_helper'
|
require 'spec_helper'
|
||||||
|
|
||||||
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
|
let(:database_metric_class) { Class.new(described_class) }
|
||||||
|
|
||||||
subject do
|
subject do
|
||||||
described_class.tap do |metric_class|
|
database_metric_class.tap do |metric_class|
|
||||||
metric_class.relation { Issue }
|
metric_class.relation { Issue }
|
||||||
metric_class.operation :count
|
metric_class.operation :count
|
||||||
metric_class.start { Issue.minimum(:id) }
|
metric_class.start { Issue.minimum(:id) }
|
||||||
|
@ -38,7 +40,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
|
|
||||||
context 'with metric options specified with custom batch_size' do
|
context 'with metric options specified with custom batch_size' do
|
||||||
subject do
|
subject do
|
||||||
described_class.tap do |metric_class|
|
database_metric_class.tap do |metric_class|
|
||||||
metric_class.relation { Issue }
|
metric_class.relation { Issue }
|
||||||
metric_class.operation :count
|
metric_class.operation :count
|
||||||
metric_class.start { Issue.minimum(:id) }
|
metric_class.start { Issue.minimum(:id) }
|
||||||
|
@ -60,7 +62,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
|
|
||||||
context 'with start and finish not called' do
|
context 'with start and finish not called' do
|
||||||
subject do
|
subject do
|
||||||
described_class.tap do |metric_class|
|
database_metric_class.tap do |metric_class|
|
||||||
metric_class.relation { Issue }
|
metric_class.relation { Issue }
|
||||||
metric_class.operation :count
|
metric_class.operation :count
|
||||||
end.new(time_frame: 'all')
|
end.new(time_frame: 'all')
|
||||||
|
@ -73,7 +75,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
|
|
||||||
context 'with availability defined' do
|
context 'with availability defined' do
|
||||||
subject do
|
subject do
|
||||||
described_class.tap do |metric_class|
|
database_metric_class.tap do |metric_class|
|
||||||
metric_class.relation { Issue }
|
metric_class.relation { Issue }
|
||||||
metric_class.operation :count
|
metric_class.operation :count
|
||||||
metric_class.available? { false }
|
metric_class.available? { false }
|
||||||
|
@ -87,7 +89,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
|
|
||||||
context 'with availability not defined' do
|
context 'with availability not defined' do
|
||||||
subject do
|
subject do
|
||||||
Class.new(described_class) do
|
database_metric_class do
|
||||||
relation { Issue }
|
relation { Issue }
|
||||||
operation :count
|
operation :count
|
||||||
end.new(time_frame: 'all')
|
end.new(time_frame: 'all')
|
||||||
|
@ -100,7 +102,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
|
|
||||||
context 'with cache_start_and_finish_as called' do
|
context 'with cache_start_and_finish_as called' do
|
||||||
subject do
|
subject do
|
||||||
described_class.tap do |metric_class|
|
database_metric_class.tap do |metric_class|
|
||||||
metric_class.relation { Issue }
|
metric_class.relation { Issue }
|
||||||
metric_class.operation :count
|
metric_class.operation :count
|
||||||
metric_class.start { Issue.minimum(:id) }
|
metric_class.start { Issue.minimum(:id) }
|
||||||
|
@ -123,7 +125,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
|
|
||||||
context 'with estimate_batch_distinct_count' do
|
context 'with estimate_batch_distinct_count' do
|
||||||
subject do
|
subject do
|
||||||
described_class.tap do |metric_class|
|
database_metric_class.tap do |metric_class|
|
||||||
metric_class.relation { Issue }
|
metric_class.relation { Issue }
|
||||||
metric_class.operation(:estimate_batch_distinct_count)
|
metric_class.operation(:estimate_batch_distinct_count)
|
||||||
metric_class.start { Issue.minimum(:id) }
|
metric_class.start { Issue.minimum(:id) }
|
||||||
|
@ -139,7 +141,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
let(:buckets) { double('Buckets').as_null_object }
|
let(:buckets) { double('Buckets').as_null_object }
|
||||||
|
|
||||||
subject do
|
subject do
|
||||||
described_class.tap do |metric_class|
|
database_metric_class.tap do |metric_class|
|
||||||
metric_class.relation { Issue }
|
metric_class.relation { Issue }
|
||||||
metric_class.operation(:estimate_batch_distinct_count) do |result|
|
metric_class.operation(:estimate_batch_distinct_count) do |result|
|
||||||
result.foo
|
result.foo
|
||||||
|
@ -163,7 +165,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
|
|
||||||
context 'with custom timestamp column' do
|
context 'with custom timestamp column' do
|
||||||
subject do
|
subject do
|
||||||
described_class.tap do |metric_class|
|
database_metric_class.tap do |metric_class|
|
||||||
metric_class.relation { Issue }
|
metric_class.relation { Issue }
|
||||||
metric_class.operation :count
|
metric_class.operation :count
|
||||||
metric_class.timestamp_column :last_edited_at
|
metric_class.timestamp_column :last_edited_at
|
||||||
|
@ -171,6 +173,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'calculates a correct result' do
|
it 'calculates a correct result' do
|
||||||
|
create(:issue, last_edited_at: 40.days.ago)
|
||||||
create(:issue, last_edited_at: 5.days.ago)
|
create(:issue, last_edited_at: 5.days.ago)
|
||||||
|
|
||||||
expect(subject.value).to eq(1)
|
expect(subject.value).to eq(1)
|
||||||
|
@ -179,14 +182,14 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
|
|
||||||
context 'with default timestamp column' do
|
context 'with default timestamp column' do
|
||||||
subject do
|
subject do
|
||||||
described_class.tap do |metric_class|
|
database_metric_class.tap do |metric_class|
|
||||||
metric_class.relation { Issue }
|
metric_class.relation { Issue }
|
||||||
metric_class.operation :count
|
metric_class.operation :count
|
||||||
end.new(time_frame: '28d')
|
end.new(time_frame: '28d')
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'calculates a correct result' do
|
it 'calculates a correct result' do
|
||||||
create(:issue, last_edited_at: 5.days.ago)
|
create(:issue, created_at: 40.days.ago)
|
||||||
create(:issue, created_at: 5.days.ago)
|
create(:issue, created_at: 5.days.ago)
|
||||||
|
|
||||||
expect(subject.value).to eq(1)
|
expect(subject.value).to eq(1)
|
||||||
|
@ -195,15 +198,15 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
|
|
||||||
context 'with additional parameters passed via options' do
|
context 'with additional parameters passed via options' do
|
||||||
subject do
|
subject do
|
||||||
described_class.tap do |metric_class|
|
database_metric_class.tap do |metric_class|
|
||||||
metric_class.relation ->(options) { Issue.where(confidential: options[:confidential]) }
|
metric_class.relation ->(options) { Issue.where(confidential: options[:confidential]) }
|
||||||
metric_class.operation :count
|
metric_class.operation :count
|
||||||
end.new(time_frame: '28d', options: { confidential: true })
|
end.new(time_frame: '28d', options: { confidential: true })
|
||||||
end
|
end
|
||||||
|
|
||||||
it 'calculates a correct result' do
|
it 'calculates a correct result' do
|
||||||
create(:issue, last_edited_at: 5.days.ago, confidential: true)
|
create(:issue, created_at: 5.days.ago, confidential: true)
|
||||||
create(:issue, last_edited_at: 5.days.ago, confidential: false)
|
create(:issue, created_at: 5.days.ago, confidential: false)
|
||||||
|
|
||||||
expect(subject.value).to eq(1)
|
expect(subject.value).to eq(1)
|
||||||
end
|
end
|
||||||
|
@ -212,7 +215,7 @@ RSpec.describe Gitlab::Usage::Metrics::Instrumentations::DatabaseMetric do
|
||||||
|
|
||||||
context 'with unimplemented operation method used' do
|
context 'with unimplemented operation method used' do
|
||||||
subject do
|
subject do
|
||||||
described_class.tap do |metric_class|
|
database_metric_class.tap do |metric_class|
|
||||||
metric_class.relation { Issue }
|
metric_class.relation { Issue }
|
||||||
metric_class.operation :invalid_operation
|
metric_class.operation :invalid_operation
|
||||||
end.new(time_frame: 'all')
|
end.new(time_frame: 'all')
|
||||||
|
|
|
@ -12,6 +12,10 @@ RSpec.describe Gitlab::UsageDataCounters::CiTemplateUniqueCounter do
|
||||||
|
|
||||||
shared_examples 'tracks template' do
|
shared_examples 'tracks template' do
|
||||||
let(:subject) { described_class.track_unique_project_event(project: project, template: template_path, config_source: config_source, user: user) }
|
let(:subject) { described_class.track_unique_project_event(project: project, template: template_path, config_source: config_source, user: user) }
|
||||||
|
let(:template_name) do
|
||||||
|
expanded_template_name = described_class.expand_template_name(template_path)
|
||||||
|
described_class.ci_template_event_name(expanded_template_name, config_source)
|
||||||
|
end
|
||||||
|
|
||||||
it "has an event defined for template" do
|
it "has an event defined for template" do
|
||||||
expect do
|
expect do
|
||||||
|
@ -20,33 +24,18 @@ RSpec.describe Gitlab::UsageDataCounters::CiTemplateUniqueCounter do
|
||||||
end
|
end
|
||||||
|
|
||||||
it "tracks template" do
|
it "tracks template" do
|
||||||
expanded_template_name = described_class.expand_template_name(template_path)
|
expect(Gitlab::UsageDataCounters::HLLRedisCounter).to(receive(:track_event)).with(template_name, values: project.id)
|
||||||
expected_template_event_name = described_class.ci_template_event_name(expanded_template_name, config_source)
|
|
||||||
expect(Gitlab::UsageDataCounters::HLLRedisCounter).to(receive(:track_event)).with(expected_template_event_name, values: project.id)
|
|
||||||
|
|
||||||
subject
|
subject
|
||||||
end
|
end
|
||||||
|
|
||||||
context 'Snowplow' do
|
it_behaves_like 'Snowplow event tracking with RedisHLL context' do
|
||||||
it 'event is not tracked if FF is disabled' do
|
let(:feature_flag_name) { :route_hll_to_snowplow }
|
||||||
stub_feature_flags(route_hll_to_snowplow: false)
|
let(:category) { described_class.to_s }
|
||||||
|
let(:action) { 'ci_templates_unique' }
|
||||||
subject
|
let(:namespace) { project.namespace }
|
||||||
|
let(:label) { 'redis_hll_counters.ci_templates.ci_templates_total_unique_counts_monthly' }
|
||||||
expect_no_snowplow_event
|
let(:context) { [Gitlab::Tracking::ServicePingContext.new(data_source: :redis_hll, event: template_name).to_context] }
|
||||||
end
|
|
||||||
|
|
||||||
it 'tracks event' do
|
|
||||||
subject
|
|
||||||
|
|
||||||
expect_snowplow_event(
|
|
||||||
category: described_class.to_s,
|
|
||||||
action: 'ci_templates_unique',
|
|
||||||
namespace: project.namespace,
|
|
||||||
user: user,
|
|
||||||
project: project
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ require (
|
||||||
github.com/BurntSushi/toml v1.2.1
|
github.com/BurntSushi/toml v1.2.1
|
||||||
github.com/FZambia/sentinel v1.1.1
|
github.com/FZambia/sentinel v1.1.1
|
||||||
github.com/alecthomas/chroma/v2 v2.3.0
|
github.com/alecthomas/chroma/v2 v2.3.0
|
||||||
github.com/aws/aws-sdk-go v1.44.131
|
github.com/aws/aws-sdk-go v1.44.133
|
||||||
github.com/disintegration/imaging v1.6.2
|
github.com/disintegration/imaging v1.6.2
|
||||||
github.com/getsentry/raven-go v0.2.0
|
github.com/getsentry/raven-go v0.2.0
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.2
|
github.com/golang-jwt/jwt/v4 v4.4.2
|
||||||
|
|
|
@ -227,8 +227,8 @@ github.com/aws/aws-sdk-go v1.43.11/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4
|
||||||
github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
github.com/aws/aws-sdk-go v1.43.31/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||||
github.com/aws/aws-sdk-go v1.44.45/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
github.com/aws/aws-sdk-go v1.44.45/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||||
github.com/aws/aws-sdk-go v1.44.68/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
github.com/aws/aws-sdk-go v1.44.68/go.mod h1:y4AeaBuwd2Lk+GepC1E9v0qOiTws0MIWAX4oIKwKHZo=
|
||||||
github.com/aws/aws-sdk-go v1.44.131 h1:kd61x79ax0vyiC/SZ9X1hKh8E0pt1BUOOcVBJEFhxkg=
|
github.com/aws/aws-sdk-go v1.44.133 h1:+pWxt9nyKc0jf33rORBaQ93KPjYpmIIy3ozVXdJ82Oo=
|
||||||
github.com/aws/aws-sdk-go v1.44.131/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
github.com/aws/aws-sdk-go v1.44.133/go.mod h1:aVsgQcEevwlmQ7qHE9I3h+dtQgpqhFB+i8Phjh7fkwI=
|
||||||
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
github.com/aws/aws-sdk-go-v2 v0.18.0/go.mod h1:JWVYvqSMppoMJC0x5wdwiImzgXTI9FuZwxzkQq9wy+g=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.16.8 h1:gOe9UPR98XSf7oEJCcojYg+N2/jCRm4DdeIsP85pIyQ=
|
github.com/aws/aws-sdk-go-v2 v1.16.8 h1:gOe9UPR98XSf7oEJCcojYg+N2/jCRm4DdeIsP85pIyQ=
|
||||||
github.com/aws/aws-sdk-go-v2 v1.16.8/go.mod h1:6CpKuLXg2w7If3ABZCl/qZ6rEgwtjZTn4eAf4RcEyuw=
|
github.com/aws/aws-sdk-go-v2 v1.16.8/go.mod h1:6CpKuLXg2w7If3ABZCl/qZ6rEgwtjZTn4eAf4RcEyuw=
|
||||||
|
|
Loading…
Reference in New Issue