Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
f1ce233e6a
commit
bb0d99269b
|
|
@ -1103,3 +1103,10 @@ RSpec/UselessDynamicDefinition:
|
||||||
Exclude:
|
Exclude:
|
||||||
- 'spec/factories/**/*'
|
- 'spec/factories/**/*'
|
||||||
- 'ee/spec/factories/**/*'
|
- 'ee/spec/factories/**/*'
|
||||||
|
|
||||||
|
Database/AvoidUsingPluckWithoutLimit:
|
||||||
|
Enabled: true
|
||||||
|
Exclude:
|
||||||
|
- 'spec/**/*.rb'
|
||||||
|
- 'ee/spec/**/*.rb'
|
||||||
|
- 'qa/qa/specs/**/*.rb'
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,167 @@
|
||||||
|
---
|
||||||
|
Database/AvoidUsingPluckWithoutLimit:
|
||||||
|
Details: grace period
|
||||||
|
Exclude:
|
||||||
|
- app/finders/groups/projects_requiring_authorizations_refresh/base.rb
|
||||||
|
- app/finders/issuables/label_filter.rb
|
||||||
|
- app/finders/projects/members/effective_access_level_finder.rb
|
||||||
|
- app/models/application_record.rb
|
||||||
|
- app/models/ci/build.rb
|
||||||
|
- app/models/ci/build_trace_chunks/fog.rb
|
||||||
|
- app/models/ci/build_trace_chunks/redis_base.rb
|
||||||
|
- app/models/ci/group_variable.rb
|
||||||
|
- app/models/ci/job_artifact.rb
|
||||||
|
- app/models/ci/job_token/allowlist.rb
|
||||||
|
- app/models/ci/pipeline.rb
|
||||||
|
- app/models/ci/runner.rb
|
||||||
|
- app/models/ci/runner_manager_build.rb
|
||||||
|
- app/models/commit_collection.rb
|
||||||
|
- app/models/commit_signatures/gpg_signature.rb
|
||||||
|
- app/models/commit_status.rb
|
||||||
|
- app/models/concerns/cascading_namespace_setting_attribute.rb
|
||||||
|
- app/models/concerns/commit_signature.rb
|
||||||
|
- app/models/concerns/integrations/reset_secret_fields.rb
|
||||||
|
- app/models/concerns/issuable.rb
|
||||||
|
- app/models/concerns/packages/debian/distribution.rb
|
||||||
|
- app/models/concerns/subquery.rb
|
||||||
|
- app/models/concerns/taggable_queries.rb
|
||||||
|
- app/models/customer_relations/contact.rb
|
||||||
|
- app/models/customer_relations/issue_contact.rb
|
||||||
|
- app/models/environment.rb
|
||||||
|
- app/models/event_collection.rb
|
||||||
|
- app/models/group.rb
|
||||||
|
- app/models/incident_management/timeline_event_tag.rb
|
||||||
|
- app/models/integration.rb
|
||||||
|
- app/models/integrations/base_chat_notification.rb
|
||||||
|
- app/models/integrations/slack_workspace/api_scope.rb
|
||||||
|
- app/models/integrations/slack_workspace/integration_api_scope.rb
|
||||||
|
- app/models/issue.rb
|
||||||
|
- app/models/label.rb
|
||||||
|
- app/models/loose_foreign_keys/deleted_record.rb
|
||||||
|
- app/models/member.rb
|
||||||
|
- app/models/members/last_group_owner_assigner.rb
|
||||||
|
- app/models/merge_request.rb
|
||||||
|
- app/models/merge_request_diff.rb
|
||||||
|
- app/models/merge_requests_closing_issues.rb
|
||||||
|
- app/models/namespace.rb
|
||||||
|
- app/models/namespaces/traversal/linear.rb
|
||||||
|
- app/models/namespaces/traversal/recursive.rb
|
||||||
|
- app/models/note.rb
|
||||||
|
- app/models/packages/build_info.rb
|
||||||
|
- app/models/packages/dependency.rb
|
||||||
|
- app/models/packages/maven/metadatum.rb
|
||||||
|
- app/models/packages/package.rb
|
||||||
|
- app/models/pages_deployment.rb
|
||||||
|
- app/models/postgresql/replication_slot.rb
|
||||||
|
- app/models/project.rb
|
||||||
|
- app/models/project_authorizations/changes.rb
|
||||||
|
- app/models/project_team.rb
|
||||||
|
- app/models/prometheus_alert.rb
|
||||||
|
- app/models/protected_branch.rb
|
||||||
|
- app/models/remote_mirror.rb
|
||||||
|
- app/models/shard.rb
|
||||||
|
- app/models/slack_integration.rb
|
||||||
|
- app/models/todo.rb
|
||||||
|
- app/models/uploads/fog.rb
|
||||||
|
- app/models/user.rb
|
||||||
|
- app/models/users/group_visit.rb
|
||||||
|
- app/models/users/project_visit.rb
|
||||||
|
- app/models/x509_certificate.rb
|
||||||
|
- app/services/authorized_project_update/project_recalculate_service.rb
|
||||||
|
- app/services/boards/base_items_list_service.rb
|
||||||
|
- app/services/branches/delete_merged_service.rb
|
||||||
|
- app/services/bulk_imports/batched_relation_export_service.rb
|
||||||
|
- app/services/ci/job_artifacts/bulk_delete_by_project_service.rb
|
||||||
|
- app/services/ci/pipeline_creation/cancel_redundant_pipelines_service.rb
|
||||||
|
- app/services/ci/pipeline_processing/atomic_processing_service/status_collection.rb
|
||||||
|
- app/services/ci/queue/pending_builds_strategy.rb
|
||||||
|
- app/services/ci/refs/enqueue_pipelines_to_unlock_service.rb
|
||||||
|
- app/services/ci/runners/reconcile_existing_runner_versions_service.rb
|
||||||
|
- app/services/ci/unlock_pipeline_service.rb
|
||||||
|
- app/services/groups/autocomplete_service.rb
|
||||||
|
- app/services/groups/destroy_service.rb
|
||||||
|
- app/services/groups/transfer_service.rb
|
||||||
|
- app/services/issues/referenced_merge_requests_service.rb
|
||||||
|
- app/services/labels/available_labels_service.rb
|
||||||
|
- app/services/labels/promote_service.rb
|
||||||
|
- app/services/labels/transfer_service.rb
|
||||||
|
- app/services/merge_requests/push_options_handler_service.rb
|
||||||
|
- app/services/merge_requests/pushed_branches_service.rb
|
||||||
|
- app/services/packages/cleanup/execute_policy_service.rb
|
||||||
|
- app/services/projects/slack_application_install_service.rb
|
||||||
|
- app/services/projects/unlink_fork_service.rb
|
||||||
|
- ee/app/finders/ee/issuables/label_filter.rb
|
||||||
|
- ee/app/finders/ee/merge_requests_finder.rb
|
||||||
|
- ee/app/finders/groups_with_templates_finder.rb
|
||||||
|
- ee/app/finders/namespaces/billed_users_finder.rb
|
||||||
|
- ee/app/finders/namespaces/free_user_cap/users_finder.rb
|
||||||
|
- ee/app/finders/namespaces/free_user_cap/users_without_added_members_finder.rb
|
||||||
|
- ee/app/models/ai/ai_resource/concerns/noteable.rb
|
||||||
|
- ee/app/models/allowed_email_domain.rb
|
||||||
|
- ee/app/models/analytics/issues_analytics.rb
|
||||||
|
- ee/app/models/approval_wrapped_rule.rb
|
||||||
|
- ee/app/models/concerns/audit_events/streaming/streamable_event_type_filter.rb
|
||||||
|
- ee/app/models/concerns/ee/ci/artifactable.rb
|
||||||
|
- ee/app/models/concerns/ee/issuable_link.rb
|
||||||
|
- ee/app/models/concerns/elasticsearch_indexed_container.rb
|
||||||
|
- ee/app/models/concerns/geo/verifiable_model.rb
|
||||||
|
- ee/app/models/dast_scanner_profile.rb
|
||||||
|
- ee/app/models/dast_site_profile.rb
|
||||||
|
- ee/app/models/ee/ci/daily_build_group_report_result.rb
|
||||||
|
- ee/app/models/ee/ci/pipeline.rb
|
||||||
|
- ee/app/models/ee/design_management/repository.rb
|
||||||
|
- ee/app/models/ee/epic.rb
|
||||||
|
- ee/app/models/ee/group.rb
|
||||||
|
- ee/app/models/ee/group_group_link.rb
|
||||||
|
- ee/app/models/ee/group_member.rb
|
||||||
|
- ee/app/models/ee/label.rb
|
||||||
|
- ee/app/models/ee/merge_request.rb
|
||||||
|
- ee/app/models/ee/personal_access_token.rb
|
||||||
|
- ee/app/models/ee/project.rb
|
||||||
|
- ee/app/models/ee/project_authorization.rb
|
||||||
|
- ee/app/models/ee/project_group_link.rb
|
||||||
|
- ee/app/models/ee/projects/wiki_repository.rb
|
||||||
|
- ee/app/models/ee/uploads/local.rb
|
||||||
|
- ee/app/models/ee/user.rb
|
||||||
|
- ee/app/models/embedding/application_record.rb
|
||||||
|
- ee/app/models/geo/base_registry.rb
|
||||||
|
- ee/app/models/geo/container_repository_registry.rb
|
||||||
|
- ee/app/models/geo/lfs_object_registry.rb
|
||||||
|
- ee/app/models/geo/tracking_base.rb
|
||||||
|
- ee/app/models/geo/upload_registry.rb
|
||||||
|
- ee/app/models/gitlab_subscriptions/user_add_on_assignment.rb
|
||||||
|
- ee/app/models/incident_management/oncall_rotation.rb
|
||||||
|
- ee/app/models/instance_security_dashboard.rb
|
||||||
|
- ee/app/models/issuables_analytics.rb
|
||||||
|
- ee/app/models/iteration.rb
|
||||||
|
- ee/app/models/merge_requests/external_status_check.rb
|
||||||
|
- ee/app/models/protected_environment.rb
|
||||||
|
- ee/app/models/security/finding.rb
|
||||||
|
- ee/app/models/security/scan.rb
|
||||||
|
- ee/app/models/security/scan_result_policy_violation.rb
|
||||||
|
- ee/app/models/software_license.rb
|
||||||
|
- ee/app/models/vulnerabilities/finding.rb
|
||||||
|
- ee/app/models/vulnerabilities/read.rb
|
||||||
|
- ee/app/services/analytics/cycle_analytics/consistency_check_service.rb
|
||||||
|
- ee/app/services/analytics/cycle_analytics/data_loader_service.rb
|
||||||
|
- ee/app/services/approval_rules/params_filtering_service.rb
|
||||||
|
- ee/app/services/click_house/data_ingestion/ci_finished_builds_sync_service.rb
|
||||||
|
- ee/app/services/ee/groups/destroy_service.rb
|
||||||
|
- ee/app/services/ee/search/global_service.rb
|
||||||
|
- ee/app/services/epics/update_dates_service.rb
|
||||||
|
- ee/app/services/gitlab_subscriptions/preview_billable_user_change_service.rb
|
||||||
|
- ee/app/services/security/merge_request_security_report_generation_service.rb
|
||||||
|
- ee/app/services/security/scan_result_policies/sync_any_merge_request_rules_service.rb
|
||||||
|
- ee/app/services/security/scan_result_policies/update_approvals_service.rb
|
||||||
|
- ee/app/services/security/security_orchestration_policies/default_branch_updation_check_service.rb
|
||||||
|
- ee/app/services/security/security_orchestration_policies/fetch_policy_approvers_service.rb
|
||||||
|
- ee/app/services/security/security_orchestration_policies/policy_branches_service.rb
|
||||||
|
- ee/app/services/security/security_orchestration_policies/process_scan_result_policy_service.rb
|
||||||
|
- ee/app/services/security/security_orchestration_policies/protected_branches_deletion_check_service.rb
|
||||||
|
- ee/app/services/security/security_orchestration_policies/protected_branches_push_service.rb
|
||||||
|
- ee/app/services/security/security_orchestration_policies/rule_schedule_service.rb
|
||||||
|
- ee/app/services/security/security_orchestration_policies/validate_policy_service.rb
|
||||||
|
- ee/app/services/security/sync_license_scanning_rules_service.rb
|
||||||
|
- ee/app/services/vulnerabilities/bulk_dismiss_service.rb
|
||||||
|
- ee/app/services/vulnerability_exports/export_service.rb
|
||||||
|
- ee/lib/ee/gitlab/background_migration/migrate_approver_to_approval_rules.rb
|
||||||
|
|
@ -2281,7 +2281,6 @@ Layout/LineLength:
|
||||||
- 'ee/spec/views/admin/dashboard/index.html.haml_spec.rb'
|
- 'ee/spec/views/admin/dashboard/index.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/compliance_management/compliance_framework/_project_settings.html.haml_spec.rb'
|
- 'ee/spec/views/compliance_management/compliance_framework/_project_settings.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/groups/security/discover/show.html.haml_spec.rb'
|
- 'ee/spec/views/groups/security/discover/show.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/layouts/header/_current_user_dropdown.html.haml_spec.rb'
|
|
||||||
- 'ee/spec/views/operations/environments.html.haml_spec.rb'
|
- 'ee/spec/views/operations/environments.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/projects/security/discover/show.html.haml_spec.rb'
|
- 'ee/spec/views/projects/security/discover/show.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/shared/_mirror_status.html.haml_spec.rb'
|
- 'ee/spec/views/shared/_mirror_status.html.haml_spec.rb'
|
||||||
|
|
|
||||||
|
|
@ -205,7 +205,6 @@ RSpec/FactoryBot/AvoidCreate:
|
||||||
- 'ee/spec/views/groups/settings/reporting/show.html.haml_spec.rb'
|
- 'ee/spec/views/groups/settings/reporting/show.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/layouts/application.html.haml_spec.rb'
|
- 'ee/spec/views/layouts/application.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/layouts/group.html.haml_spec.rb'
|
- 'ee/spec/views/layouts/group.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/layouts/header/_current_user_dropdown.html.haml_spec.rb'
|
|
||||||
- 'ee/spec/views/layouts/header/_read_only_banner.html.haml_spec.rb'
|
- 'ee/spec/views/layouts/header/_read_only_banner.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/layouts/project.html.haml_spec.rb'
|
- 'ee/spec/views/layouts/project.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/projects/edit.html.haml_spec.rb'
|
- 'ee/spec/views/projects/edit.html.haml_spec.rb'
|
||||||
|
|
|
||||||
|
|
@ -1445,7 +1445,6 @@ RSpec/FeatureCategory:
|
||||||
- 'ee/spec/views/groups/settings/reporting/show.html.haml_spec.rb'
|
- 'ee/spec/views/groups/settings/reporting/show.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/layouts/application.html.haml_spec.rb'
|
- 'ee/spec/views/layouts/application.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/layouts/checkout.html.haml_spec.rb'
|
- 'ee/spec/views/layouts/checkout.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/layouts/header/_current_user_dropdown.html.haml_spec.rb'
|
|
||||||
- 'ee/spec/views/layouts/header/_ee_subscribable_banner.html.haml_spec.rb'
|
- 'ee/spec/views/layouts/header/_ee_subscribable_banner.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/layouts/header/_read_only_banner.html.haml_spec.rb'
|
- 'ee/spec/views/layouts/header/_read_only_banner.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/operations/environments.html.haml_spec.rb'
|
- 'ee/spec/views/operations/environments.html.haml_spec.rb'
|
||||||
|
|
@ -4061,8 +4060,6 @@ RSpec/FeatureCategory:
|
||||||
- 'spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric_spec.rb'
|
- 'spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_direct_installations_count_metric_spec.rb'
|
||||||
- 'spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric_spec.rb'
|
- 'spec/lib/gitlab/usage/metrics/instrumentations/gitlab_for_jira_app_proxy_installations_count_metric_spec.rb'
|
||||||
- 'spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb'
|
- 'spec/lib/gitlab/usage/metrics/instrumentations/hostname_metric_spec.rb'
|
||||||
- 'spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_cta_clicked_metric_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/usage/metrics/instrumentations/in_product_marketing_email_sent_metric_spec.rb'
|
|
||||||
- 'spec/lib/gitlab/usage/metrics/instrumentations/jira_imports_total_imported_issues_count_metric_spec.rb'
|
- 'spec/lib/gitlab/usage/metrics/instrumentations/jira_imports_total_imported_issues_count_metric_spec.rb'
|
||||||
- 'spec/lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric_spec.rb'
|
- 'spec/lib/gitlab/usage/metrics/instrumentations/merge_request_widget_extension_metric_spec.rb'
|
||||||
- 'spec/lib/gitlab/usage/metrics/instrumentations/numbers_metric_spec.rb'
|
- 'spec/lib/gitlab/usage/metrics/instrumentations/numbers_metric_spec.rb'
|
||||||
|
|
|
||||||
|
|
@ -1188,7 +1188,6 @@ RSpec/NamedSubject:
|
||||||
- 'ee/spec/validators/user_existence_validator_spec.rb'
|
- 'ee/spec/validators/user_existence_validator_spec.rb'
|
||||||
- 'ee/spec/validators/user_id_existence_validator_spec.rb'
|
- 'ee/spec/validators/user_id_existence_validator_spec.rb'
|
||||||
- 'ee/spec/views/devise/registrations/new.html.haml_spec.rb'
|
- 'ee/spec/views/devise/registrations/new.html.haml_spec.rb'
|
||||||
- 'ee/spec/views/layouts/header/_current_user_dropdown.html.haml_spec.rb'
|
|
||||||
- 'ee/spec/workers/active_user_count_threshold_worker_spec.rb'
|
- 'ee/spec/workers/active_user_count_threshold_worker_spec.rb'
|
||||||
- 'ee/spec/workers/admin_emails_worker_spec.rb'
|
- 'ee/spec/workers/admin_emails_worker_spec.rb'
|
||||||
- 'ee/spec/workers/app_sec/dast/profile_schedule_worker_spec.rb'
|
- 'ee/spec/workers/app_sec/dast/profile_schedule_worker_spec.rb'
|
||||||
|
|
@ -3528,7 +3527,6 @@ RSpec/NamedSubject:
|
||||||
- 'spec/services/users/activity_service_spec.rb'
|
- 'spec/services/users/activity_service_spec.rb'
|
||||||
- 'spec/services/users/approve_service_spec.rb'
|
- 'spec/services/users/approve_service_spec.rb'
|
||||||
- 'spec/services/users/assigned_issues_count_service_spec.rb'
|
- 'spec/services/users/assigned_issues_count_service_spec.rb'
|
||||||
- 'spec/services/users/in_product_marketing_email_records_spec.rb'
|
|
||||||
- 'spec/services/users/keys_count_service_spec.rb'
|
- 'spec/services/users/keys_count_service_spec.rb'
|
||||||
- 'spec/services/users/reject_service_spec.rb'
|
- 'spec/services/users/reject_service_spec.rb'
|
||||||
- 'spec/services/users/saved_replies/create_service_spec.rb'
|
- 'spec/services/users/saved_replies/create_service_spec.rb'
|
||||||
|
|
|
||||||
|
|
@ -30,8 +30,8 @@ export const initHomeOrganizationSetting = () => {
|
||||||
block: true,
|
block: true,
|
||||||
label: s__('Organization|Home organization'),
|
label: s__('Organization|Home organization'),
|
||||||
description: s__('Organization|Choose what organization you want to see by default.'),
|
description: s__('Organization|Choose what organization you want to see by default.'),
|
||||||
inputName: 'home_organization',
|
inputName: 'user[home_organization_id]',
|
||||||
inputId: 'home_organization',
|
inputId: 'user_home_organization_id',
|
||||||
initialSelection,
|
initialSelection,
|
||||||
toggleClass: 'gl-form-input-xl',
|
toggleClass: 'gl-form-input-xl',
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -22,12 +22,17 @@ export default class PersistentUserCallout {
|
||||||
|
|
||||||
init() {
|
init() {
|
||||||
const followLink = this.container.querySelector('.js-follow-link');
|
const followLink = this.container.querySelector('.js-follow-link');
|
||||||
|
const closeAndFollowLink = this.container.querySelector('.js-close-and-follow-link');
|
||||||
|
|
||||||
if (this.closeButtons.length) {
|
if (this.closeButtons.length) {
|
||||||
this.handleCloseButtonCallout();
|
this.handleCloseButtonCallout();
|
||||||
} else if (followLink) {
|
} else if (followLink) {
|
||||||
this.handleFollowLinkCallout(followLink);
|
this.handleFollowLinkCallout(followLink);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (closeAndFollowLink) {
|
||||||
|
this.handleFollowLinkCallout(closeAndFollowLink);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
handleCloseButtonCallout() {
|
handleCloseButtonCallout() {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@ const PERSISTENT_USER_CALLOUTS = [
|
||||||
'.js-recovery-settings-callout',
|
'.js-recovery-settings-callout',
|
||||||
'.js-users-over-license-callout',
|
'.js-users-over-license-callout',
|
||||||
'.js-admin-licensed-user-count-threshold',
|
'.js-admin-licensed-user-count-threshold',
|
||||||
'.js-buy-pipeline-minutes-notification-callout',
|
|
||||||
'.js-token-expiry-callout',
|
'.js-token-expiry-callout',
|
||||||
'.js-registration-enabled-callout',
|
'.js-registration-enabled-callout',
|
||||||
'.js-new-user-signups-cap-reached',
|
'.js-new-user-signups-cap-reached',
|
||||||
|
|
|
||||||
|
|
@ -53,6 +53,9 @@ export default {
|
||||||
projectKey: {
|
projectKey: {
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
reopenIssueOnExternalParticipantNote: {
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
addExternalParticipantsFromCc: {
|
addExternalParticipantsFromCc: {
|
||||||
default: false,
|
default: false,
|
||||||
},
|
},
|
||||||
|
|
@ -115,6 +118,7 @@ export default {
|
||||||
fileTemplateProjectId,
|
fileTemplateProjectId,
|
||||||
outgoingName,
|
outgoingName,
|
||||||
projectKey,
|
projectKey,
|
||||||
|
reopenIssueOnExternalParticipantNote,
|
||||||
addExternalParticipantsFromCc,
|
addExternalParticipantsFromCc,
|
||||||
}) {
|
}) {
|
||||||
this.isTemplateSaving = true;
|
this.isTemplateSaving = true;
|
||||||
|
|
@ -123,6 +127,7 @@ export default {
|
||||||
issue_template_key: selectedTemplate,
|
issue_template_key: selectedTemplate,
|
||||||
outgoing_name: outgoingName,
|
outgoing_name: outgoingName,
|
||||||
project_key: projectKey,
|
project_key: projectKey,
|
||||||
|
reopen_issue_on_external_participant_note: reopenIssueOnExternalParticipantNote,
|
||||||
add_external_participants_from_cc: addExternalParticipantsFromCc,
|
add_external_participants_from_cc: addExternalParticipantsFromCc,
|
||||||
service_desk_enabled: this.isEnabled,
|
service_desk_enabled: this.isEnabled,
|
||||||
file_template_project_id: fileTemplateProjectId,
|
file_template_project_id: fileTemplateProjectId,
|
||||||
|
|
@ -195,6 +200,7 @@ export default {
|
||||||
:initial-selected-file-template-project-id="selectedFileTemplateProjectId"
|
:initial-selected-file-template-project-id="selectedFileTemplateProjectId"
|
||||||
:initial-outgoing-name="outgoingName"
|
:initial-outgoing-name="outgoingName"
|
||||||
:initial-project-key="projectKey"
|
:initial-project-key="projectKey"
|
||||||
|
:initial-reopen-issue-on-external-participant-note="reopenIssueOnExternalParticipantNote"
|
||||||
:initial-add-external-participants-from-cc="addExternalParticipantsFromCc"
|
:initial-add-external-participants-from-cc="addExternalParticipantsFromCc"
|
||||||
:templates="templates"
|
:templates="templates"
|
||||||
:is-template-saving="isTemplateSaving"
|
:is-template-saving="isTemplateSaving"
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,12 @@ export default {
|
||||||
issueTrackerEnableMessage: __(
|
issueTrackerEnableMessage: __(
|
||||||
'To use Service Desk in this project, you must %{linkStart}activate the issue tracker%{linkEnd}.',
|
'To use Service Desk in this project, you must %{linkStart}activate the issue tracker%{linkEnd}.',
|
||||||
),
|
),
|
||||||
|
reopenIssueOnExternalParticipantNote: {
|
||||||
|
label: s__('ServiceDesk|Reopen issues when an external participant comments'),
|
||||||
|
help: s__(
|
||||||
|
'ServiceDesk|This also adds an internal comment that mentions the assignees of the issue.',
|
||||||
|
),
|
||||||
|
},
|
||||||
addExternalParticipantsFromCc: {
|
addExternalParticipantsFromCc: {
|
||||||
label: s__('ServiceDesk|Add external participants from the %{codeStart}Cc%{codeEnd} header'),
|
label: s__('ServiceDesk|Add external participants from the %{codeStart}Cc%{codeEnd} header'),
|
||||||
help: s__(
|
help: s__(
|
||||||
|
|
@ -91,6 +97,11 @@ export default {
|
||||||
required: false,
|
required: false,
|
||||||
default: '',
|
default: '',
|
||||||
},
|
},
|
||||||
|
initialReopenIssueOnExternalParticipantNote: {
|
||||||
|
type: Boolean,
|
||||||
|
required: false,
|
||||||
|
default: false,
|
||||||
|
},
|
||||||
initialAddExternalParticipantsFromCc: {
|
initialAddExternalParticipantsFromCc: {
|
||||||
type: Boolean,
|
type: Boolean,
|
||||||
required: false,
|
required: false,
|
||||||
|
|
@ -113,6 +124,7 @@ export default {
|
||||||
selectedFileTemplateProjectId: this.initialSelectedFileTemplateProjectId,
|
selectedFileTemplateProjectId: this.initialSelectedFileTemplateProjectId,
|
||||||
outgoingName: this.initialOutgoingName || __('GitLab Support Bot'),
|
outgoingName: this.initialOutgoingName || __('GitLab Support Bot'),
|
||||||
projectKey: this.initialProjectKey,
|
projectKey: this.initialProjectKey,
|
||||||
|
reopenIssueOnExternalParticipantNote: this.initialReopenIssueOnExternalParticipantNote,
|
||||||
addExternalParticipantsFromCc: this.initialAddExternalParticipantsFromCc,
|
addExternalParticipantsFromCc: this.initialAddExternalParticipantsFromCc,
|
||||||
searchTerm: '',
|
searchTerm: '',
|
||||||
projectKeyError: null,
|
projectKeyError: null,
|
||||||
|
|
@ -156,6 +168,7 @@ export default {
|
||||||
selectedTemplate: this.selectedTemplate,
|
selectedTemplate: this.selectedTemplate,
|
||||||
outgoingName: this.outgoingName,
|
outgoingName: this.outgoingName,
|
||||||
projectKey: this.projectKey,
|
projectKey: this.projectKey,
|
||||||
|
reopenIssueOnExternalParticipantNote: this.reopenIssueOnExternalParticipantNote,
|
||||||
addExternalParticipantsFromCc: this.addExternalParticipantsFromCc,
|
addExternalParticipantsFromCc: this.addExternalParticipantsFromCc,
|
||||||
fileTemplateProjectId: this.selectedFileTemplateProjectId,
|
fileTemplateProjectId: this.selectedFileTemplateProjectId,
|
||||||
});
|
});
|
||||||
|
|
@ -322,10 +335,23 @@ export default {
|
||||||
</template>
|
</template>
|
||||||
</gl-form-group>
|
</gl-form-group>
|
||||||
|
|
||||||
|
<gl-form-checkbox
|
||||||
|
v-model="reopenIssueOnExternalParticipantNote"
|
||||||
|
:disabled="!isIssueTrackerEnabled"
|
||||||
|
data-testid="reopen-issue-on-external-participant-note"
|
||||||
|
>
|
||||||
|
{{ $options.i18n.reopenIssueOnExternalParticipantNote.label }}
|
||||||
|
|
||||||
|
<template #help>
|
||||||
|
{{ $options.i18n.reopenIssueOnExternalParticipantNote.help }}
|
||||||
|
</template>
|
||||||
|
</gl-form-checkbox>
|
||||||
|
|
||||||
<gl-form-checkbox
|
<gl-form-checkbox
|
||||||
v-if="showAddExternalParticipantsFromCC"
|
v-if="showAddExternalParticipantsFromCC"
|
||||||
v-model="addExternalParticipantsFromCc"
|
v-model="addExternalParticipantsFromCc"
|
||||||
:disabled="!isIssueTrackerEnabled"
|
:disabled="!isIssueTrackerEnabled"
|
||||||
|
data-testid="add-external-participants-from-cc"
|
||||||
>
|
>
|
||||||
<gl-sprintf :message="$options.i18n.addExternalParticipantsFromCc.label">
|
<gl-sprintf :message="$options.i18n.addExternalParticipantsFromCc.label">
|
||||||
<template #code="{ content }">
|
<template #code="{ content }">
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ export default () => {
|
||||||
incomingEmail,
|
incomingEmail,
|
||||||
outgoingName,
|
outgoingName,
|
||||||
projectKey,
|
projectKey,
|
||||||
|
reopenIssueOnExternalParticipantNote,
|
||||||
addExternalParticipantsFromCc,
|
addExternalParticipantsFromCc,
|
||||||
selectedTemplate,
|
selectedTemplate,
|
||||||
selectedFileTemplateProjectId,
|
selectedFileTemplateProjectId,
|
||||||
|
|
@ -40,6 +41,7 @@ export default () => {
|
||||||
isIssueTrackerEnabled: parseBoolean(issueTrackerEnabled),
|
isIssueTrackerEnabled: parseBoolean(issueTrackerEnabled),
|
||||||
outgoingName,
|
outgoingName,
|
||||||
projectKey,
|
projectKey,
|
||||||
|
reopenIssueOnExternalParticipantNote: parseBoolean(reopenIssueOnExternalParticipantNote),
|
||||||
addExternalParticipantsFromCc: parseBoolean(addExternalParticipantsFromCc),
|
addExternalParticipantsFromCc: parseBoolean(addExternalParticipantsFromCc),
|
||||||
selectedTemplate,
|
selectedTemplate,
|
||||||
selectedFileTemplateProjectId: parseInt(selectedFileTemplateProjectId, 10) || null,
|
selectedFileTemplateProjectId: parseInt(selectedFileTemplateProjectId, 10) || null,
|
||||||
|
|
|
||||||
|
|
@ -31,13 +31,14 @@ const fetchData = (projectPath, path, ref, offset, refType) => {
|
||||||
|
|
||||||
fetchedBatches.push(offset);
|
fetchedBatches.push(offset);
|
||||||
|
|
||||||
|
const encodePathFunc = gon.features.encodingLogsTree ? encodeURI : encodeURIComponent;
|
||||||
const url = joinPaths(
|
const url = joinPaths(
|
||||||
gon.relative_url_root || '/',
|
gon.relative_url_root || '/',
|
||||||
projectPath,
|
projectPath,
|
||||||
'/-/refs/',
|
'/-/refs/',
|
||||||
encodeURIComponent(ref),
|
encodePathFunc(ref),
|
||||||
'/logs_tree/',
|
'/logs_tree/',
|
||||||
encodeURIComponent(removeLeadingSlash(path)),
|
encodePathFunc(removeLeadingSlash(path)),
|
||||||
);
|
);
|
||||||
|
|
||||||
return axios
|
return axios
|
||||||
|
|
|
||||||
|
|
@ -1,30 +1,41 @@
|
||||||
import setHighlightClass from 'ee_else_ce/search/highlight_blob_search_result';
|
import setHighlightClass from 'ee_else_ce/search/highlight_blob_search_result';
|
||||||
import { queryToObject } from '~/lib/utils/url_utility';
|
import { queryToObject } from '~/lib/utils/url_utility';
|
||||||
import syntaxHighlight from '~/syntax_highlight';
|
import syntaxHighlight from '~/syntax_highlight';
|
||||||
import { initSidebar, sidebarInitState } from './sidebar';
|
import { initSidebar } from './sidebar';
|
||||||
import { initSearchSort } from './sort';
|
import { initSearchSort } from './sort';
|
||||||
import createStore from './store';
|
import createStore from './store';
|
||||||
import { initTopbar } from './topbar';
|
import { initTopbar } from './topbar';
|
||||||
import { initBlobRefSwitcher } from './under_topbar';
|
import { initBlobRefSwitcher } from './under_topbar';
|
||||||
|
|
||||||
const topbarInitState = () => {
|
const sidebarInitState = () => {
|
||||||
const el = document.getElementById('js-search-topbar');
|
const el = document.getElementById('js-search-sidebar');
|
||||||
if (!el) return {};
|
if (!el) return {};
|
||||||
const { defaultBranchName } = el.dataset;
|
|
||||||
return { defaultBranchName };
|
const { navigationJson, searchType, groupInitialJson, projectInitialJson } = el.dataset;
|
||||||
|
|
||||||
|
const navigationJsonParsed = JSON.parse(navigationJson);
|
||||||
|
const groupInitialJsonParsed = JSON.parse(groupInitialJson);
|
||||||
|
const projectInitialJsonParsed = JSON.parse(projectInitialJson);
|
||||||
|
|
||||||
|
return { navigationJsonParsed, searchType, groupInitialJsonParsed, projectInitialJsonParsed };
|
||||||
};
|
};
|
||||||
|
|
||||||
export const initSearchApp = () => {
|
export const initSearchApp = () => {
|
||||||
syntaxHighlight(document.querySelectorAll('.js-search-results'));
|
syntaxHighlight(document.querySelectorAll('.js-search-results'));
|
||||||
const query = queryToObject(window.location.search, { gatherArrays: true });
|
const query = queryToObject(window.location.search, { gatherArrays: true });
|
||||||
const { navigationJsonParsed: navigation, searchType } = sidebarInitState() || {};
|
const {
|
||||||
const { defaultBranchName } = topbarInitState() || {};
|
navigationJsonParsed: navigation,
|
||||||
|
searchType,
|
||||||
|
groupInitialJsonParsed: groupInitialJson,
|
||||||
|
projectInitialJsonParsed: projectInitialJson,
|
||||||
|
} = sidebarInitState() || {};
|
||||||
|
|
||||||
const store = createStore({
|
const store = createStore({
|
||||||
query,
|
query,
|
||||||
navigation,
|
navigation,
|
||||||
searchType,
|
searchType,
|
||||||
defaultBranchName,
|
groupInitialJson,
|
||||||
|
projectInitialJson,
|
||||||
});
|
});
|
||||||
|
|
||||||
initTopbar(store);
|
initTopbar(store);
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,19 @@
|
||||||
|
<script>
|
||||||
|
import GroupFilter from './group_filter.vue';
|
||||||
|
import ProjectFilter from './project_filter.vue';
|
||||||
|
|
||||||
|
export default {
|
||||||
|
name: 'AllScopesStartFilters',
|
||||||
|
components: {
|
||||||
|
GroupFilter,
|
||||||
|
ProjectFilter,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<template>
|
||||||
|
<div class="gl-px-5 gl-pt-6">
|
||||||
|
<group-filter class="gl-mb-5" />
|
||||||
|
<project-filter class="gl-mb-5" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
@ -25,6 +25,7 @@ import NotesFilters from './notes_filters.vue';
|
||||||
import CommitsFilters from './commits_filters.vue';
|
import CommitsFilters from './commits_filters.vue';
|
||||||
import MilestonesFilters from './milestones_filters.vue';
|
import MilestonesFilters from './milestones_filters.vue';
|
||||||
import WikiBlobsFilters from './wiki_blobs_filters.vue';
|
import WikiBlobsFilters from './wiki_blobs_filters.vue';
|
||||||
|
import AllScopesStartFilters from './all_scopes_start_filters.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'GlobalSearchSidebar',
|
name: 'GlobalSearchSidebar',
|
||||||
|
|
@ -40,8 +41,16 @@ export default {
|
||||||
DomElementListener,
|
DomElementListener,
|
||||||
CommitsFilters,
|
CommitsFilters,
|
||||||
MilestonesFilters,
|
MilestonesFilters,
|
||||||
|
AllScopesStartFilters,
|
||||||
},
|
},
|
||||||
mixins: [glFeatureFlagsMixin()],
|
mixins: [glFeatureFlagsMixin()],
|
||||||
|
props: {
|
||||||
|
headerText: {
|
||||||
|
required: false,
|
||||||
|
type: String,
|
||||||
|
default: '',
|
||||||
|
},
|
||||||
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['searchType']),
|
...mapState(['searchType']),
|
||||||
...mapGetters(['currentScope']),
|
...mapGetters(['currentScope']),
|
||||||
|
|
@ -82,6 +91,13 @@ export default {
|
||||||
<section>
|
<section>
|
||||||
<dom-element-listener selector="#js-open-mobile-filters" @click="toggleFiltersFromSidebar" />
|
<dom-element-listener selector="#js-open-mobile-filters" @click="toggleFiltersFromSidebar" />
|
||||||
<sidebar-portal>
|
<sidebar-portal>
|
||||||
|
<all-scopes-start-filters />
|
||||||
|
<div
|
||||||
|
v-if="headerText"
|
||||||
|
class="gl-px-5 gl-pt-3 gl-pb-2 gl-m-0 gl-reset-line-height gl-font-weight-bold gl-font-sm super-sidebar-context-header"
|
||||||
|
>
|
||||||
|
{{ headerText }}
|
||||||
|
</div>
|
||||||
<scope-sidebar-navigation />
|
<scope-sidebar-navigation />
|
||||||
<issues-filters v-if="showIssuesFilters" />
|
<issues-filters v-if="showIssuesFilters" />
|
||||||
<merge-requests-filters v-if="showMergeRequestFilters" />
|
<merge-requests-filters v-if="showMergeRequestFilters" />
|
||||||
|
|
|
||||||
|
|
@ -2,34 +2,27 @@
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
// eslint-disable-next-line no-restricted-imports
|
// eslint-disable-next-line no-restricted-imports
|
||||||
import { mapState, mapActions, mapGetters } from 'vuex';
|
import { mapState, mapActions, mapGetters } from 'vuex';
|
||||||
|
import { s__ } from '~/locale';
|
||||||
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
|
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
|
||||||
import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '../constants';
|
import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '../constants';
|
||||||
import SearchableDropdown from './searchable_dropdown.vue';
|
import SearchableDropdown from './searchable_dropdown.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'GroupFilter',
|
name: 'GroupFilter',
|
||||||
|
i18n: {
|
||||||
|
groupFieldLabel: s__('GlobalSearch|Group'),
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
SearchableDropdown,
|
SearchableDropdown,
|
||||||
},
|
},
|
||||||
props: {
|
|
||||||
groupInitialJson: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
labelId: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
default: 'labelId',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
search: '',
|
search: '',
|
||||||
|
labelId: 'group-filter-dropdown-id',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['query', 'groups', 'fetchingGroups']),
|
...mapState(['query', 'groups', 'fetchingGroups', 'groupInitialJson', 'useSidebarNavigation']),
|
||||||
...mapGetters(['frequentGroups', 'currentScope']),
|
...mapGetters(['frequentGroups', 'currentScope']),
|
||||||
selectedGroup() {
|
selectedGroup() {
|
||||||
return isEmpty(this.groupInitialJson) ? ANY_OPTION : this.groupInitialJson;
|
return isEmpty(this.groupInitialJson) ? ANY_OPTION : this.groupInitialJson;
|
||||||
|
|
@ -73,6 +66,10 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<div>
|
||||||
|
<h5 :id="labelId" class="gl-mt-0 gl-mb-5 gl-font-sm">
|
||||||
|
{{ $options.i18n.groupFieldLabel }}
|
||||||
|
</h5>
|
||||||
<searchable-dropdown
|
<searchable-dropdown
|
||||||
data-testid="group-filter"
|
data-testid="group-filter"
|
||||||
:header-text="$options.GROUP_DATA.headerText"
|
:header-text="$options.GROUP_DATA.headerText"
|
||||||
|
|
@ -86,4 +83,5 @@ export default {
|
||||||
@first-open="firstLoad"
|
@first-open="firstLoad"
|
||||||
@change="handleGroupChange"
|
@change="handleGroupChange"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -2,34 +2,33 @@
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
// eslint-disable-next-line no-restricted-imports
|
// eslint-disable-next-line no-restricted-imports
|
||||||
import { mapState, mapActions, mapGetters } from 'vuex';
|
import { mapState, mapActions, mapGetters } from 'vuex';
|
||||||
|
import { s__ } from '~/locale';
|
||||||
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
|
import { visitUrl, setUrlParams } from '~/lib/utils/url_utility';
|
||||||
import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '../constants';
|
import { ANY_OPTION, GROUP_DATA, PROJECT_DATA } from '~/search/sidebar/constants';
|
||||||
import SearchableDropdown from './searchable_dropdown.vue';
|
import SearchableDropdown from './searchable_dropdown.vue';
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'ProjectFilter',
|
name: 'ProjectFilter',
|
||||||
|
i18n: {
|
||||||
|
projectFieldLabel: s__('GlobalSearch|Project'),
|
||||||
|
},
|
||||||
components: {
|
components: {
|
||||||
SearchableDropdown,
|
SearchableDropdown,
|
||||||
},
|
},
|
||||||
props: {
|
|
||||||
projectInitialJson: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
default: () => null,
|
|
||||||
},
|
|
||||||
labelId: {
|
|
||||||
type: String,
|
|
||||||
required: false,
|
|
||||||
default: '',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
data() {
|
data() {
|
||||||
return {
|
return {
|
||||||
search: '',
|
search: '',
|
||||||
|
labelId: 'projects-filter-dropdown-id',
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
...mapState(['query', 'projects', 'fetchingProjects']),
|
...mapState([
|
||||||
|
'query',
|
||||||
|
'projects',
|
||||||
|
'fetchingProjects',
|
||||||
|
'projectInitialJson',
|
||||||
|
'useSidebarNavigation',
|
||||||
|
]),
|
||||||
...mapGetters(['frequentProjects', 'currentScope']),
|
...mapGetters(['frequentProjects', 'currentScope']),
|
||||||
selectedProject() {
|
selectedProject() {
|
||||||
return isEmpty(this.projectInitialJson) ? ANY_OPTION : this.projectInitialJson;
|
return isEmpty(this.projectInitialJson) ? ANY_OPTION : this.projectInitialJson;
|
||||||
|
|
@ -74,6 +73,10 @@ export default {
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
|
<div>
|
||||||
|
<h5 :id="labelId" class="gl-mt-0 gl-mb-5 gl-font-sm">
|
||||||
|
{{ $options.i18n.projectFieldLabel }}
|
||||||
|
</h5>
|
||||||
<searchable-dropdown
|
<searchable-dropdown
|
||||||
data-testid="project-filter"
|
data-testid="project-filter"
|
||||||
:header-text="$options.PROJECT_DATA.headerText"
|
:header-text="$options.PROJECT_DATA.headerText"
|
||||||
|
|
@ -87,4 +90,5 @@ export default {
|
||||||
@first-open="firstLoad"
|
@first-open="firstLoad"
|
||||||
@change="handleProjectChange"
|
@change="handleProjectChange"
|
||||||
/>
|
/>
|
||||||
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
// eslint-disable-next-line no-restricted-imports
|
// eslint-disable-next-line no-restricted-imports
|
||||||
import { mapActions, mapState, mapGetters } from 'vuex';
|
import { mapActions, mapState, mapGetters } from 'vuex';
|
||||||
import { s__ } from '~/locale';
|
import { s__ } from '~/locale';
|
||||||
|
import eventHub from '~/super_sidebar/event_hub';
|
||||||
import NavItem from '~/super_sidebar/components/nav_item.vue';
|
import NavItem from '~/super_sidebar/components/nav_item.vue';
|
||||||
import { NAV_LINK_DEFAULT_CLASSES, NAV_LINK_COUNT_DEFAULT_CLASSES } from '../constants';
|
import { NAV_LINK_DEFAULT_CLASSES, NAV_LINK_COUNT_DEFAULT_CLASSES } from '../constants';
|
||||||
|
|
||||||
|
|
@ -18,6 +19,8 @@ export default {
|
||||||
...mapGetters(['navigationItems']),
|
...mapGetters(['navigationItems']),
|
||||||
},
|
},
|
||||||
created() {
|
created() {
|
||||||
|
eventHub.$emit('toggle-menu-header', false);
|
||||||
|
|
||||||
if (this.urlQuery?.search) {
|
if (this.urlQuery?.search) {
|
||||||
this.fetchSidebarCount();
|
this.fetchSidebarCount();
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,3 +1,5 @@
|
||||||
|
import { __ } from '~/locale';
|
||||||
|
|
||||||
export const SCOPE_ISSUES = 'issues';
|
export const SCOPE_ISSUES = 'issues';
|
||||||
export const SCOPE_MERGE_REQUESTS = 'merge_requests';
|
export const SCOPE_MERGE_REQUESTS = 'merge_requests';
|
||||||
export const SCOPE_BLOB = 'blobs';
|
export const SCOPE_BLOB = 'blobs';
|
||||||
|
|
@ -26,3 +28,23 @@ export const TRACKING_LABEL_RESET = 'Reset Filters';
|
||||||
export const SEARCH_TYPE_BASIC = 'basic';
|
export const SEARCH_TYPE_BASIC = 'basic';
|
||||||
export const SEARCH_TYPE_ADVANCED = 'advanced';
|
export const SEARCH_TYPE_ADVANCED = 'advanced';
|
||||||
export const SEARCH_TYPE_ZOEKT = 'zoekt';
|
export const SEARCH_TYPE_ZOEKT = 'zoekt';
|
||||||
|
|
||||||
|
export const ANY_OPTION = {
|
||||||
|
id: null,
|
||||||
|
name: __('Any'),
|
||||||
|
name_with_namespace: __('Any'),
|
||||||
|
};
|
||||||
|
|
||||||
|
export const GROUP_DATA = {
|
||||||
|
headerText: __('Filter results by group'),
|
||||||
|
queryParam: 'group_id',
|
||||||
|
name: 'name',
|
||||||
|
fullName: 'full_name',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const PROJECT_DATA = {
|
||||||
|
headerText: __('Filter results by project'),
|
||||||
|
queryParam: 'project_id',
|
||||||
|
name: 'name',
|
||||||
|
fullName: 'name_with_namespace',
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -4,27 +4,23 @@ import GlobalSearchSidebar from './components/app.vue';
|
||||||
|
|
||||||
Vue.use(Translate);
|
Vue.use(Translate);
|
||||||
|
|
||||||
export const sidebarInitState = () => {
|
|
||||||
const el = document.getElementById('js-search-sidebar');
|
|
||||||
if (!el) return {};
|
|
||||||
|
|
||||||
const { navigationJson, searchType } = el.dataset;
|
|
||||||
|
|
||||||
const navigationJsonParsed = JSON.parse(navigationJson);
|
|
||||||
|
|
||||||
return { navigationJsonParsed, searchType };
|
|
||||||
};
|
|
||||||
|
|
||||||
export const initSidebar = (store) => {
|
export const initSidebar = (store) => {
|
||||||
const el = document.getElementById('js-search-sidebar');
|
const el = document.getElementById('js-search-sidebar');
|
||||||
|
const hederEl = document.getElementById('super-sidebar-context-header');
|
||||||
|
const headerText = hederEl.innerText;
|
||||||
|
|
||||||
if (!el) return false;
|
if (!el) return false;
|
||||||
|
|
||||||
return new Vue({
|
return new Vue({
|
||||||
el,
|
el,
|
||||||
|
name: 'GlobalSearchSidebar',
|
||||||
store,
|
store,
|
||||||
render(createElement) {
|
render(createElement) {
|
||||||
return createElement(GlobalSearchSidebar);
|
return createElement(GlobalSearchSidebar, {
|
||||||
|
props: {
|
||||||
|
headerText,
|
||||||
|
},
|
||||||
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,7 @@
|
||||||
import { cloneDeep } from 'lodash';
|
import { cloneDeep } from 'lodash';
|
||||||
import { GROUPS_LOCAL_STORAGE_KEY, PROJECTS_LOCAL_STORAGE_KEY } from './constants';
|
import { GROUPS_LOCAL_STORAGE_KEY, PROJECTS_LOCAL_STORAGE_KEY } from './constants';
|
||||||
|
|
||||||
const createState = ({ query, navigation, defaultBranchName, searchType }) => ({
|
const createState = ({ query, navigation, searchType, groupInitialJson, projectInitialJson }) => ({
|
||||||
urlQuery: cloneDeep(query),
|
urlQuery: cloneDeep(query),
|
||||||
query,
|
query,
|
||||||
groups: [],
|
groups: [],
|
||||||
|
|
@ -21,7 +21,8 @@ const createState = ({ query, navigation, defaultBranchName, searchType }) => ({
|
||||||
},
|
},
|
||||||
searchLabelString: '',
|
searchLabelString: '',
|
||||||
searchType,
|
searchType,
|
||||||
defaultBranchName,
|
groupInitialJson,
|
||||||
|
projectInitialJson,
|
||||||
});
|
});
|
||||||
|
|
||||||
export default createState;
|
export default createState;
|
||||||
|
|
|
||||||
|
|
@ -3,13 +3,10 @@ import { GlSearchBoxByType, GlButton } from '@gitlab/ui';
|
||||||
// eslint-disable-next-line no-restricted-imports
|
// eslint-disable-next-line no-restricted-imports
|
||||||
import { mapState, mapActions } from 'vuex';
|
import { mapState, mapActions } from 'vuex';
|
||||||
import { s__ } from '~/locale';
|
import { s__ } from '~/locale';
|
||||||
import { parseBoolean } from '~/lib/utils/common_utils';
|
|
||||||
import MarkdownDrawer from '~/vue_shared/components/markdown_drawer/markdown_drawer.vue';
|
import MarkdownDrawer from '~/vue_shared/components/markdown_drawer/markdown_drawer.vue';
|
||||||
import { ZOEKT_SEARCH_TYPE, ADVANCED_SEARCH_TYPE } from '~/search/store/constants';
|
import { ZOEKT_SEARCH_TYPE, ADVANCED_SEARCH_TYPE } from '~/search/store/constants';
|
||||||
import { SYNTAX_OPTIONS_ADVANCED_DOCUMENT, SYNTAX_OPTIONS_ZOEKT_DOCUMENT } from '../constants';
|
import { SYNTAX_OPTIONS_ADVANCED_DOCUMENT, SYNTAX_OPTIONS_ZOEKT_DOCUMENT } from '../constants';
|
||||||
import SearchTypeIndicator from './search_type_indicator.vue';
|
import SearchTypeIndicator from './search_type_indicator.vue';
|
||||||
import GroupFilter from './group_filter.vue';
|
|
||||||
import ProjectFilter from './project_filter.vue';
|
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'GlobalSearchTopbar',
|
name: 'GlobalSearchTopbar',
|
||||||
|
|
@ -23,22 +20,10 @@ export default {
|
||||||
components: {
|
components: {
|
||||||
GlButton,
|
GlButton,
|
||||||
GlSearchBoxByType,
|
GlSearchBoxByType,
|
||||||
GroupFilter,
|
|
||||||
ProjectFilter,
|
|
||||||
MarkdownDrawer,
|
MarkdownDrawer,
|
||||||
SearchTypeIndicator,
|
SearchTypeIndicator,
|
||||||
},
|
},
|
||||||
props: {
|
props: {
|
||||||
groupInitialJson: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
projectInitialJson: {
|
|
||||||
type: Object,
|
|
||||||
required: false,
|
|
||||||
default: () => ({}),
|
|
||||||
},
|
|
||||||
defaultBranchName: {
|
defaultBranchName: {
|
||||||
type: String,
|
type: String,
|
||||||
required: false,
|
required: false,
|
||||||
|
|
@ -55,9 +40,6 @@ export default {
|
||||||
this.setQuery({ key: 'search', value });
|
this.setQuery({ key: 'search', value });
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
showFilters() {
|
|
||||||
return !parseBoolean(this.query.snippets);
|
|
||||||
},
|
|
||||||
showSyntaxOptions() {
|
showSyntaxOptions() {
|
||||||
return (
|
return (
|
||||||
(this.searchType === ZOEKT_SEARCH_TYPE || this.searchType === ADVANCED_SEARCH_TYPE) &&
|
(this.searchType === ZOEKT_SEARCH_TYPE || this.searchType === ADVANCED_SEARCH_TYPE) &&
|
||||||
|
|
@ -103,31 +85,17 @@ export default {
|
||||||
</template>
|
</template>
|
||||||
<search-type-indicator />
|
<search-type-indicator />
|
||||||
</div>
|
</div>
|
||||||
<div class="search-page-form gl-lg-display-flex gl-flex-direction-row gl-align-items-flex-end">
|
<div class="search-page-form gl-lg-display-flex gl-flex-direction-column">
|
||||||
<div class="gl-flex-grow-1 gl-lg-mb-0 gl-lg-mr-2">
|
<div class="gl-lg-display-flex gl-flex-direction-row gl-align-items-flex-start">
|
||||||
|
<div class="gl-flex-grow-1 gl-pb-8 gl-lg-mb-0 gl-lg-mr-2">
|
||||||
<gl-search-box-by-type
|
<gl-search-box-by-type
|
||||||
id="dashboard_search"
|
id="dashboard_search"
|
||||||
v-model="search"
|
v-model="search"
|
||||||
name="search"
|
name="search"
|
||||||
:placeholder="$options.i18n.searchPlaceholder"
|
:placeholder="$options.i18n.searchPlaceholder"
|
||||||
@submit="applyQuery"
|
|
||||||
@keydown.enter.stop.prevent="applyQuery"
|
@keydown.enter.stop.prevent="applyQuery"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div v-if="showFilters" class="gl-mb-4 gl-lg-mb-0 gl-lg-mx-3 gl-min-w-20">
|
|
||||||
<label id="groupfilterDropdown" class="gl-display-block gl-mb-1 gl-md-pb-2">{{
|
|
||||||
$options.i18n.groupFieldLabel
|
|
||||||
}}</label>
|
|
||||||
<group-filter label-id="groupfilterDropdown" :group-initial-json="groupInitialJson" />
|
|
||||||
</div>
|
|
||||||
<div v-if="showFilters" class="gl-mb-4 gl-lg-mb-0 gl-lg-ml-3 gl-min-w-20">
|
|
||||||
<label id="projectfilterDropdown" class="gl-display-block gl-mb-1 gl-md-pb-2">{{
|
|
||||||
$options.i18n.projectFieldLabel
|
|
||||||
}}</label>
|
|
||||||
<project-filter
|
|
||||||
label-id="projectfilterDropdown"
|
|
||||||
:project-initial-json="projectInitialJson"
|
|
||||||
/>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
|
|
|
||||||
|
|
@ -1,25 +1,3 @@
|
||||||
import { __ } from '~/locale';
|
|
||||||
|
|
||||||
export const ANY_OPTION = Object.freeze({
|
|
||||||
id: null,
|
|
||||||
name: __('Any'),
|
|
||||||
name_with_namespace: __('Any'),
|
|
||||||
});
|
|
||||||
|
|
||||||
export const GROUP_DATA = {
|
|
||||||
headerText: __('Filter results by group'),
|
|
||||||
queryParam: 'group_id',
|
|
||||||
name: 'name',
|
|
||||||
fullName: 'full_name',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const PROJECT_DATA = {
|
|
||||||
headerText: __('Filter results by project'),
|
|
||||||
queryParam: 'project_id',
|
|
||||||
name: 'name',
|
|
||||||
fullName: 'name_with_namespace',
|
|
||||||
};
|
|
||||||
|
|
||||||
export const SYNTAX_OPTIONS_ADVANCED_DOCUMENT = 'drawers/drawers/advanced_search_syntax.md';
|
export const SYNTAX_OPTIONS_ADVANCED_DOCUMENT = 'drawers/drawers/advanced_search_syntax.md';
|
||||||
export const SYNTAX_OPTIONS_ZOEKT_DOCUMENT = 'drawers/drawers/exact_code_search_syntax.md';
|
export const SYNTAX_OPTIONS_ZOEKT_DOCUMENT = 'drawers/drawers/exact_code_search_syntax.md';
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,19 +11,16 @@ export const initTopbar = (store) => {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { groupInitialJson, projectInitialJson } = el.dataset;
|
const { defaultBranchName } = el.dataset;
|
||||||
|
|
||||||
const groupInitialJsonParsed = JSON.parse(groupInitialJson);
|
|
||||||
const projectInitialJsonParsed = JSON.parse(projectInitialJson);
|
|
||||||
|
|
||||||
return new Vue({
|
return new Vue({
|
||||||
el,
|
el,
|
||||||
|
name: 'GlobalSearchTopbar',
|
||||||
store,
|
store,
|
||||||
render(createElement) {
|
render(createElement) {
|
||||||
return createElement(GlobalSearchTopbar, {
|
return createElement(GlobalSearchTopbar, {
|
||||||
props: {
|
props: {
|
||||||
groupInitialJson: groupInitialJsonParsed,
|
defaultBranchName,
|
||||||
projectInitialJson: projectInitialJsonParsed,
|
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ export const initBlobRefSwitcher = () => {
|
||||||
|
|
||||||
return new Vue({
|
return new Vue({
|
||||||
el,
|
el,
|
||||||
|
name: 'GlobalSearchUnderTopbar',
|
||||||
render(createElement) {
|
render(createElement) {
|
||||||
return createElement(RefSelector, {
|
return createElement(RefSelector, {
|
||||||
props: {
|
props: {
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@ import { TAB_KEY_CODE } from '~/lib/utils/keycodes';
|
||||||
import { keysFor, TOGGLE_SUPER_SIDEBAR } from '~/behaviors/shortcuts/keybindings';
|
import { keysFor, TOGGLE_SUPER_SIDEBAR } from '~/behaviors/shortcuts/keybindings';
|
||||||
import { __, s__ } from '~/locale';
|
import { __, s__ } from '~/locale';
|
||||||
import Tracking from '~/tracking';
|
import Tracking from '~/tracking';
|
||||||
|
import eventHub from '../event_hub';
|
||||||
import {
|
import {
|
||||||
sidebarState,
|
sidebarState,
|
||||||
SUPER_SIDEBAR_PEEK_STATE_CLOSED as STATE_CLOSED,
|
SUPER_SIDEBAR_PEEK_STATE_CLOSED as STATE_CLOSED,
|
||||||
|
|
@ -58,6 +59,7 @@ export default {
|
||||||
showPeekHint: false,
|
showPeekHint: false,
|
||||||
isMouseover: false,
|
isMouseover: false,
|
||||||
breakpoint: null,
|
breakpoint: null,
|
||||||
|
showSuperSidebarContextHeader: true,
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
computed: {
|
computed: {
|
||||||
|
|
@ -96,6 +98,7 @@ export default {
|
||||||
mounted() {
|
mounted() {
|
||||||
this.setupFocusTrapListener();
|
this.setupFocusTrapListener();
|
||||||
Mousetrap.bind(keysFor(TOGGLE_SUPER_SIDEBAR), this.toggleSidebar);
|
Mousetrap.bind(keysFor(TOGGLE_SUPER_SIDEBAR), this.toggleSidebar);
|
||||||
|
eventHub.$on('toggle-menu-header', this.onToggleMenuHeader);
|
||||||
},
|
},
|
||||||
beforeDestroy() {
|
beforeDestroy() {
|
||||||
document.removeEventListener('keydown', this.focusTrap);
|
document.removeEventListener('keydown', this.focusTrap);
|
||||||
|
|
@ -166,6 +169,9 @@ export default {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
onToggleMenuHeader(forceState) {
|
||||||
|
this.showSuperSidebarContextHeader = forceState;
|
||||||
|
},
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
@ -207,6 +213,7 @@ export default {
|
||||||
>
|
>
|
||||||
<scroll-scrim class="gl-flex-grow-1" data-testid="nav-container">
|
<scroll-scrim class="gl-flex-grow-1" data-testid="nav-container">
|
||||||
<div
|
<div
|
||||||
|
v-if="showSuperSidebarContextHeader"
|
||||||
id="super-sidebar-context-header"
|
id="super-sidebar-context-header"
|
||||||
class="gl-px-5 gl-pt-3 gl-pb-2 gl-m-0 gl-reset-line-height gl-font-weight-bold gl-font-sm super-sidebar-context-header"
|
class="gl-px-5 gl-pt-3 gl-pb-2 gl-m-0 gl-reset-line-height gl-font-weight-bold gl-font-sm super-sidebar-context-header"
|
||||||
>
|
>
|
||||||
|
|
|
||||||
|
|
@ -92,8 +92,7 @@
|
||||||
@include transition(background-color, border-color, color, box-shadow);
|
@include transition(background-color, border-color, color, box-shadow);
|
||||||
}
|
}
|
||||||
|
|
||||||
.dropdown-menu-toggle,
|
.dropdown-menu-toggle {
|
||||||
.header-user-avatar {
|
|
||||||
@include transition(border-color);
|
@include transition(border-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -810,14 +810,6 @@
|
||||||
.navbar-gitlab {
|
.navbar-gitlab {
|
||||||
li.dropdown {
|
li.dropdown {
|
||||||
position: static;
|
position: static;
|
||||||
|
|
||||||
&.user-counter {
|
|
||||||
margin-left: 8px !important;
|
|
||||||
|
|
||||||
> a {
|
|
||||||
padding: 0 4px !important;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -98,12 +98,6 @@
|
||||||
.container-fluid {
|
.container-fluid {
|
||||||
padding: 0;
|
padding: 0;
|
||||||
|
|
||||||
.user-counter {
|
|
||||||
svg {
|
|
||||||
margin-right: 3px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.navbar-nav {
|
.navbar-nav {
|
||||||
@include media-breakpoint-down(xs) {
|
@include media-breakpoint-down(xs) {
|
||||||
display: flex;
|
display: flex;
|
||||||
|
|
@ -120,12 +114,6 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
.nav > li {
|
.nav > li {
|
||||||
&.header-user {
|
|
||||||
@include media-breakpoint-down(xs) {
|
|
||||||
padding-left: 10px;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
> a {
|
> a {
|
||||||
will-change: color;
|
will-change: color;
|
||||||
margin: 4px 0;
|
margin: 4px 0;
|
||||||
|
|
@ -137,38 +125,11 @@
|
||||||
padding: 0;
|
padding: 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.header-user-dropdown-toggle {
|
|
||||||
margin-left: 2px;
|
|
||||||
|
|
||||||
.header-user-avatar {
|
|
||||||
margin-right: 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-new-dropdown-toggle {
|
.header-new-dropdown-toggle {
|
||||||
margin-right: 0;
|
margin-right: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.impersonated-user,
|
|
||||||
.impersonated-user:hover {
|
|
||||||
margin-right: 1px;
|
|
||||||
background-color: $white;
|
|
||||||
border-top-right-radius: 0;
|
|
||||||
border-bottom-right-radius: 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
.impersonation-btn,
|
|
||||||
.impersonation-btn:hover {
|
|
||||||
background-color: $white;
|
|
||||||
border-top-left-radius: 0;
|
|
||||||
border-bottom-left-radius: 0;
|
|
||||||
|
|
||||||
svg {
|
|
||||||
color: $orange-500;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -223,10 +184,6 @@
|
||||||
top: -1px;
|
top: -1px;
|
||||||
font-size: 10px;
|
font-size: 10px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.impersonation i {
|
|
||||||
color: $red-500;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.caret-down,
|
.caret-down,
|
||||||
|
|
@ -238,7 +195,6 @@
|
||||||
fill: currentColor;
|
fill: currentColor;
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-user .dropdown-menu,
|
|
||||||
.header-new .dropdown-menu {
|
.header-new .dropdown-menu {
|
||||||
margin-top: $dropdown-vertical-offset;
|
margin-top: $dropdown-vertical-offset;
|
||||||
}
|
}
|
||||||
|
|
@ -304,44 +260,6 @@
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-user-dropdown-toggle {
|
|
||||||
text-align: center;
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-user-avatar {
|
|
||||||
float: none;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-user {
|
|
||||||
&.show .dropdown-menu {
|
|
||||||
margin-top: 4px;
|
|
||||||
color: var(--gl-text-color, $gl-text-color);
|
|
||||||
left: auto;
|
|
||||||
max-height: $dropdown-max-height-lg;
|
|
||||||
|
|
||||||
.user-status {
|
|
||||||
max-width: 240px;
|
|
||||||
}
|
|
||||||
|
|
||||||
svg {
|
|
||||||
vertical-align: text-top;
|
|
||||||
}
|
|
||||||
|
|
||||||
a.ci-minutes-emoji gl-emoji,
|
|
||||||
a.trial-link gl-emoji {
|
|
||||||
font-size: $gl-font-size;
|
|
||||||
vertical-align: baseline;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
.header-user-avatar {
|
|
||||||
float: left;
|
|
||||||
margin-right: 5px;
|
|
||||||
border-radius: 50%;
|
|
||||||
border: 1px solid $gray-normal;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.notification-dot {
|
.notification-dot {
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,6 @@
|
||||||
module Explore
|
module Explore
|
||||||
class CatalogController < Explore::ApplicationController
|
class CatalogController < Explore::ApplicationController
|
||||||
feature_category :pipeline_composition
|
feature_category :pipeline_composition
|
||||||
before_action :check_feature_flag
|
|
||||||
before_action :check_resource_access, only: :show
|
before_action :check_resource_access, only: :show
|
||||||
|
|
||||||
def show; end
|
def show; end
|
||||||
|
|
@ -14,10 +13,6 @@ module Explore
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def check_feature_flag
|
|
||||||
render_404 unless Feature.enabled?(:global_ci_catalog, current_user)
|
|
||||||
end
|
|
||||||
|
|
||||||
def check_resource_access
|
def check_resource_access
|
||||||
render_404 unless catalog_resource.present?
|
render_404 unless catalog_resource.present?
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ class Profiles::PreferencesController < Profiles::ApplicationController
|
||||||
:color_scheme_id,
|
:color_scheme_id,
|
||||||
:diffs_deletion_color,
|
:diffs_deletion_color,
|
||||||
:diffs_addition_color,
|
:diffs_addition_color,
|
||||||
|
:home_organization_id,
|
||||||
:layout,
|
:layout,
|
||||||
:dashboard,
|
:dashboard,
|
||||||
:project_view,
|
:project_view,
|
||||||
|
|
|
||||||
|
|
@ -52,6 +52,7 @@ class Projects::BlobController < Projects::ApplicationController
|
||||||
push_frontend_feature_flag(:blob_blame_info, @project)
|
push_frontend_feature_flag(:blob_blame_info, @project)
|
||||||
push_frontend_feature_flag(:highlight_js_worker, @project)
|
push_frontend_feature_flag(:highlight_js_worker, @project)
|
||||||
push_frontend_feature_flag(:explain_code_chat, current_user)
|
push_frontend_feature_flag(:explain_code_chat, current_user)
|
||||||
|
push_frontend_feature_flag(:encoding_logs_tree)
|
||||||
push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)
|
push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,13 @@ class Projects::ServiceDeskController < Projects::ApplicationController
|
||||||
end
|
end
|
||||||
|
|
||||||
def allowed_update_attributes
|
def allowed_update_attributes
|
||||||
%i[issue_template_key outgoing_name project_key add_external_participants_from_cc]
|
%i[
|
||||||
|
issue_template_key
|
||||||
|
outgoing_name
|
||||||
|
project_key
|
||||||
|
reopen_issue_on_external_participant_note
|
||||||
|
add_external_participants_from_cc
|
||||||
|
]
|
||||||
end
|
end
|
||||||
|
|
||||||
def service_desk_attributes
|
def service_desk_attributes
|
||||||
|
|
@ -42,6 +48,7 @@ class Projects::ServiceDeskController < Projects::ApplicationController
|
||||||
template_file_missing: service_desk_settings&.issue_template_missing?,
|
template_file_missing: service_desk_settings&.issue_template_missing?,
|
||||||
outgoing_name: service_desk_settings&.outgoing_name,
|
outgoing_name: service_desk_settings&.outgoing_name,
|
||||||
project_key: service_desk_settings&.project_key,
|
project_key: service_desk_settings&.project_key,
|
||||||
|
reopen_issue_on_external_participant_note: service_desk_settings&.reopen_issue_on_external_participant_note,
|
||||||
add_external_participants_from_cc: service_desk_settings&.add_external_participants_from_cc
|
add_external_participants_from_cc: service_desk_settings&.add_external_participants_from_cc
|
||||||
}
|
}
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@ class Projects::TreeController < Projects::ApplicationController
|
||||||
push_frontend_feature_flag(:blob_blame_info, @project)
|
push_frontend_feature_flag(:blob_blame_info, @project)
|
||||||
push_frontend_feature_flag(:highlight_js_worker, @project)
|
push_frontend_feature_flag(:highlight_js_worker, @project)
|
||||||
push_frontend_feature_flag(:explain_code_chat, current_user)
|
push_frontend_feature_flag(:explain_code_chat, current_user)
|
||||||
|
push_frontend_feature_flag(:encoding_logs_tree)
|
||||||
push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)
|
push_licensed_feature(:file_locks) if @project.licensed_feature_available?(:file_locks)
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -43,6 +43,7 @@ class ProjectsController < Projects::ApplicationController
|
||||||
push_frontend_feature_flag(:remove_monitor_metrics, @project)
|
push_frontend_feature_flag(:remove_monitor_metrics, @project)
|
||||||
push_frontend_feature_flag(:explain_code_chat, current_user)
|
push_frontend_feature_flag(:explain_code_chat, current_user)
|
||||||
push_frontend_feature_flag(:issue_email_participants, @project)
|
push_frontend_feature_flag(:issue_email_participants, @project)
|
||||||
|
push_frontend_feature_flag(:encoding_logs_tree)
|
||||||
# TODO: We need to remove the FF eventually when we rollout page_specific_styles
|
# TODO: We need to remove the FF eventually when we rollout page_specific_styles
|
||||||
push_frontend_feature_flag(:page_specific_styles, current_user)
|
push_frontend_feature_flag(:page_specific_styles, current_user)
|
||||||
push_licensed_feature(:file_locks) if @project.present? && @project.licensed_feature_available?(:file_locks)
|
push_licensed_feature(:file_locks) if @project.present? && @project.licensed_feature_available?(:file_locks)
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,30 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Resolvers
|
||||||
|
module Namespaces
|
||||||
|
class WorkItemStateCountsResolver < WorkItemsResolver
|
||||||
|
type Types::WorkItemStateCountsType, null: true
|
||||||
|
|
||||||
|
def ready?(**args)
|
||||||
|
# The search filter is not supported for work times at the namespace level.
|
||||||
|
# See https://gitlab.com/gitlab-org/gitlab/-/work_items/393126
|
||||||
|
if args[:search]
|
||||||
|
raise Gitlab::Graphql::Errors::ArgumentError,
|
||||||
|
'Searching is not available for work items at the namespace level yet'
|
||||||
|
end
|
||||||
|
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
def resolve(**args)
|
||||||
|
return if resource_parent.nil?
|
||||||
|
|
||||||
|
Gitlab::IssuablesCountForState.new(
|
||||||
|
finder(args),
|
||||||
|
resource_parent,
|
||||||
|
store_in_redis_cache: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Resolvers
|
||||||
|
class WorkItemStateCountsResolver < WorkItemsResolver
|
||||||
|
type Types::WorkItemStateCountsType, null: true
|
||||||
|
|
||||||
|
def resolve(**args)
|
||||||
|
return if resource_parent.nil?
|
||||||
|
|
||||||
|
work_item_finder = finder(prepare_finder_params(args))
|
||||||
|
work_item_finder.parent_param = resource_parent
|
||||||
|
|
||||||
|
Gitlab::IssuablesCountForState.new(work_item_finder, resource_parent)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -275,6 +275,14 @@ module Types
|
||||||
description: 'Find a work item by IID directly associated with the group. Returns `null` if the ' \
|
description: 'Find a work item by IID directly associated with the group. Returns `null` if the ' \
|
||||||
'`namespace_level_work_items` feature flag is disabled.'
|
'`namespace_level_work_items` feature flag is disabled.'
|
||||||
|
|
||||||
|
field :work_item_state_counts,
|
||||||
|
Types::WorkItemStateCountsType,
|
||||||
|
null: true,
|
||||||
|
alpha: { milestone: '16.7' },
|
||||||
|
description: 'Counts of work items by state for the namespace. Returns `null` if the ' \
|
||||||
|
'`namespace_level_work_items` feature flag is disabled.',
|
||||||
|
resolver: Resolvers::Namespaces::WorkItemStateCountsResolver
|
||||||
|
|
||||||
field :autocomplete_users,
|
field :autocomplete_users,
|
||||||
null: true,
|
null: true,
|
||||||
resolver: Resolvers::AutocompleteUsersResolver,
|
resolver: Resolvers::AutocompleteUsersResolver,
|
||||||
|
|
|
||||||
|
|
@ -254,6 +254,13 @@ module Types
|
||||||
extras: [:lookahead],
|
extras: [:lookahead],
|
||||||
resolver: Resolvers::WorkItemsResolver
|
resolver: Resolvers::WorkItemsResolver
|
||||||
|
|
||||||
|
field :work_item_state_counts,
|
||||||
|
Types::WorkItemStateCountsType,
|
||||||
|
null: true,
|
||||||
|
alpha: { milestone: '16.7' },
|
||||||
|
description: 'Counts of work items by state for the project.',
|
||||||
|
resolver: Resolvers::WorkItemStateCountsResolver
|
||||||
|
|
||||||
field :issue_status_counts,
|
field :issue_status_counts,
|
||||||
Types::IssueStatusCountsType,
|
Types::IssueStatusCountsType,
|
||||||
null: true,
|
null: true,
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,25 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
module Types
|
||||||
|
# rubocop: disable Graphql/AuthorizeTypes -- Parent node applies authorization
|
||||||
|
class WorkItemStateCountsType < BaseObject
|
||||||
|
graphql_name 'WorkItemStateCountsType'
|
||||||
|
description 'Represents total number of work items for the represented states'
|
||||||
|
|
||||||
|
field :all,
|
||||||
|
GraphQL::Types::Int,
|
||||||
|
null: true,
|
||||||
|
description: 'Number of work items for the project or group.'
|
||||||
|
|
||||||
|
field :closed,
|
||||||
|
GraphQL::Types::Int,
|
||||||
|
null: true,
|
||||||
|
description: 'Number of work items with state CLOSED for the project or group.'
|
||||||
|
|
||||||
|
field :opened,
|
||||||
|
GraphQL::Types::Int,
|
||||||
|
null: true,
|
||||||
|
description: 'Number of work items with state OPENED for the project or group.'
|
||||||
|
end
|
||||||
|
# rubocop: enable Graphql/AuthorizeTypes
|
||||||
|
end
|
||||||
|
|
@ -315,8 +315,8 @@ module ApplicationHelper
|
||||||
class_names << 'issue-boards-page gl-overflow-auto' if current_controller?(:boards)
|
class_names << 'issue-boards-page gl-overflow-auto' if current_controller?(:boards)
|
||||||
class_names << 'epic-boards-page gl-overflow-auto' if current_controller?(:epic_boards)
|
class_names << 'epic-boards-page gl-overflow-auto' if current_controller?(:epic_boards)
|
||||||
class_names << 'with-performance-bar' if performance_bar_enabled?
|
class_names << 'with-performance-bar' if performance_bar_enabled?
|
||||||
class_names << 'with-header' if !show_super_sidebar? || !current_user
|
class_names << 'with-header' unless current_user
|
||||||
class_names << 'with-top-bar' if show_super_sidebar? && !@hide_top_bar_padding
|
class_names << 'with-top-bar' unless @hide_top_bar_padding
|
||||||
class_names << system_message_class
|
class_names << system_message_class
|
||||||
|
|
||||||
class_names
|
class_names
|
||||||
|
|
|
||||||
|
|
@ -3,18 +3,6 @@
|
||||||
module DashboardHelper
|
module DashboardHelper
|
||||||
include IconsHelper
|
include IconsHelper
|
||||||
|
|
||||||
def assigned_issues_dashboard_path
|
|
||||||
issues_dashboard_path(assignee_username: current_user.username)
|
|
||||||
end
|
|
||||||
|
|
||||||
def assigned_mrs_dashboard_path
|
|
||||||
merge_requests_dashboard_path(assignee_username: current_user.username)
|
|
||||||
end
|
|
||||||
|
|
||||||
def reviewer_mrs_dashboard_path
|
|
||||||
merge_requests_dashboard_path(reviewer_username: current_user.username)
|
|
||||||
end
|
|
||||||
|
|
||||||
def has_start_trial?
|
def has_start_trial?
|
||||||
false
|
false
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -149,16 +149,6 @@ module IssuablesHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def assigned_open_issues_count_text
|
|
||||||
count = assigned_issuables_count(:issues)
|
|
||||||
|
|
||||||
if count > User::MAX_LIMIT_FOR_ASSIGNEED_ISSUES_COUNT - 1
|
|
||||||
"#{count - 1}+"
|
|
||||||
else
|
|
||||||
count.to_s
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def issuable_reference(issuable)
|
def issuable_reference(issuable)
|
||||||
@show_full_reference ? issuable.to_reference(full: true) : issuable.to_reference(@group || @project)
|
@show_full_reference ? issuable.to_reference(full: true) : issuable.to_reference(@group || @project)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -40,14 +40,6 @@ module NavHelper
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
def user_dropdown_class
|
|
||||||
class_names = []
|
|
||||||
class_names << 'header-user-dropdown-toggle'
|
|
||||||
class_names << 'impersonated-user' if session[:impersonator_id]
|
|
||||||
|
|
||||||
class_names
|
|
||||||
end
|
|
||||||
|
|
||||||
def page_has_markdown?
|
def page_has_markdown?
|
||||||
current_path?('projects/merge_requests#show') ||
|
current_path?('projects/merge_requests#show') ||
|
||||||
current_path?('projects/merge_requests/conflicts#show') ||
|
current_path?('projects/merge_requests/conflicts#show') ||
|
||||||
|
|
|
||||||
|
|
@ -51,8 +51,7 @@ module Organizations
|
||||||
|
|
||||||
def home_organization_setting_app_data
|
def home_organization_setting_app_data
|
||||||
{
|
{
|
||||||
# TODO: use real setting - https://gitlab.com/gitlab-org/gitlab/-/issues/428668
|
initial_selection: current_user.home_organization_id
|
||||||
initial_selection: 1
|
|
||||||
}.to_json
|
}.to_json
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -5,10 +5,6 @@ module TodosHelper
|
||||||
@todos_pending_count ||= current_user.todos_pending_count
|
@todos_pending_count ||= current_user.todos_pending_count
|
||||||
end
|
end
|
||||||
|
|
||||||
def todos_count_format(count)
|
|
||||||
count > 99 ? '99+' : count.to_s
|
|
||||||
end
|
|
||||||
|
|
||||||
def todos_done_count
|
def todos_done_count
|
||||||
@todos_done_count ||= current_user.todos_done_count
|
@todos_done_count ||= current_user.todos_done_count
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -758,6 +758,11 @@ class Issue < ApplicationRecord
|
||||||
Gitlab::HookData::IssueBuilder.new(self).build
|
Gitlab::HookData::IssueBuilder.new(self).build
|
||||||
end
|
end
|
||||||
|
|
||||||
|
override :gfm_reference
|
||||||
|
def gfm_reference(from = nil)
|
||||||
|
"#{work_item_type_with_default.name.underscore} #{to_reference(from)}"
|
||||||
|
end
|
||||||
|
|
||||||
private
|
private
|
||||||
|
|
||||||
def project_level_readable_by?(user)
|
def project_level_readable_by?(user)
|
||||||
|
|
|
||||||
|
|
@ -400,6 +400,7 @@ class User < MainClusterwide::ApplicationRecord
|
||||||
:pinned_nav_items, :pinned_nav_items=,
|
:pinned_nav_items, :pinned_nav_items=,
|
||||||
:achievements_enabled, :achievements_enabled=,
|
:achievements_enabled, :achievements_enabled=,
|
||||||
:enabled_following, :enabled_following=,
|
:enabled_following, :enabled_following=,
|
||||||
|
:home_organization, :home_organization_id, :home_organization_id=,
|
||||||
to: :user_preference
|
to: :user_preference
|
||||||
|
|
||||||
delegate :path, to: :namespace, allow_nil: true, prefix: true
|
delegate :path, to: :namespace, allow_nil: true, prefix: true
|
||||||
|
|
@ -613,6 +614,10 @@ class User < MainClusterwide::ApplicationRecord
|
||||||
|
|
||||||
strip_attributes! :name
|
strip_attributes! :name
|
||||||
|
|
||||||
|
def user_belongs_to_organization?(organization)
|
||||||
|
organization_users.exists?(organization: organization)
|
||||||
|
end
|
||||||
|
|
||||||
def preferred_language
|
def preferred_language
|
||||||
read_attribute('preferred_language').presence || Gitlab::CurrentSettings.default_preferred_language
|
read_attribute('preferred_language').presence || Gitlab::CurrentSettings.default_preferred_language
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ class UserPreference < MainClusterwide::ApplicationRecord
|
||||||
TIME_DISPLAY_FORMATS = { system: 0, non_iso_format: 1, iso_format: 2 }.freeze
|
TIME_DISPLAY_FORMATS = { system: 0, non_iso_format: 1, iso_format: 2 }.freeze
|
||||||
|
|
||||||
belongs_to :user
|
belongs_to :user
|
||||||
|
belongs_to :home_organization, class_name: "Organizations::Organization", optional: true
|
||||||
|
|
||||||
scope :with_user, -> { joins(:user) }
|
scope :with_user, -> { joins(:user) }
|
||||||
scope :gitpod_enabled, -> { where(gitpod_enabled: true) }
|
scope :gitpod_enabled, -> { where(gitpod_enabled: true) }
|
||||||
|
|
@ -30,6 +31,8 @@ class UserPreference < MainClusterwide::ApplicationRecord
|
||||||
|
|
||||||
validates :time_display_format, inclusion: { in: TIME_DISPLAY_FORMATS.values }, presence: true
|
validates :time_display_format, inclusion: { in: TIME_DISPLAY_FORMATS.values }, presence: true
|
||||||
|
|
||||||
|
validate :user_belongs_to_home_organization, if: :home_organization_changed?
|
||||||
|
|
||||||
# 2023-06-22 is after 16.1 release and during 16.2 release https://docs.gitlab.com/ee/development/database/avoiding_downtime_in_migrations.html#ignoring-the-column-release-m
|
# 2023-06-22 is after 16.1 release and during 16.2 release https://docs.gitlab.com/ee/development/database/avoiding_downtime_in_migrations.html#ignoring-the-column-release-m
|
||||||
ignore_columns :use_legacy_web_ide, remove_with: '16.2', remove_after: '2023-06-22'
|
ignore_columns :use_legacy_web_ide, remove_with: '16.2', remove_after: '2023-06-22'
|
||||||
|
|
||||||
|
|
@ -52,6 +55,16 @@ class UserPreference < MainClusterwide::ApplicationRecord
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def user_belongs_to_home_organization
|
||||||
|
# If we don't ignore the default organization id below then all users need to have their corresponding entry
|
||||||
|
# with default organization id as organization id in the `organization_users` table.
|
||||||
|
# Otherwise, the user won't be able to the default organization as the home organization.
|
||||||
|
return if home_organization_id == Organizations::Organization::DEFAULT_ORGANIZATION_ID
|
||||||
|
return if user.user_belongs_to_organization?(home_organization_id)
|
||||||
|
|
||||||
|
errors.add(:user, _("is not part of the given organization"))
|
||||||
|
end
|
||||||
|
|
||||||
def set_notes_filter(filter_id, issuable)
|
def set_notes_filter(filter_id, issuable)
|
||||||
# No need to update the column if the value is already set.
|
# No need to update the column if the value is already set.
|
||||||
if filter_id && NOTES_FILTERS.value?(filter_id)
|
if filter_id && NOTES_FILTERS.value?(filter_id)
|
||||||
|
|
|
||||||
|
|
@ -12,8 +12,8 @@ module Groups
|
||||||
noteable_owner +
|
noteable_owner +
|
||||||
participants_in_noteable +
|
participants_in_noteable +
|
||||||
all_members +
|
all_members +
|
||||||
groups +
|
group_hierarchy_users +
|
||||||
group_hierarchy_users
|
groups
|
||||||
|
|
||||||
render_participants_as_hash(participants.uniq)
|
render_participants_as_hash(participants.uniq)
|
||||||
end
|
end
|
||||||
|
|
|
||||||
|
|
@ -35,8 +35,6 @@ module MergeRequests
|
||||||
result = maybe_rebase!(**result)
|
result = maybe_rebase!(**result)
|
||||||
result = maybe_merge!(**result)
|
result = maybe_merge!(**result)
|
||||||
|
|
||||||
update_merge_request!(merge_request, result)
|
|
||||||
|
|
||||||
ServiceResponse.success(payload: result)
|
ServiceResponse.success(payload: result)
|
||||||
rescue CreateRefError => error
|
rescue CreateRefError => error
|
||||||
ServiceResponse.error(message: error.message)
|
ServiceResponse.error(message: error.message)
|
||||||
|
|
@ -118,10 +116,6 @@ module MergeRequests
|
||||||
).compact
|
).compact
|
||||||
end
|
end
|
||||||
|
|
||||||
def update_merge_request!(merge_request, result)
|
|
||||||
# overridden in EE
|
|
||||||
end
|
|
||||||
|
|
||||||
def safe_gitaly_operation
|
def safe_gitaly_operation
|
||||||
yield
|
yield
|
||||||
rescue Gitlab::Git::PreReceiveError, Gitlab::Git::CommandError, ArgumentError => error
|
rescue Gitlab::Git::PreReceiveError, Gitlab::Git::CommandError, ArgumentError => error
|
||||||
|
|
|
||||||
|
|
@ -1,50 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Namespaces
|
|
||||||
class InProductMarketingEmailsService
|
|
||||||
TRACKS = {
|
|
||||||
create: {
|
|
||||||
interval_days: [1, 5, 10],
|
|
||||||
completed_actions: [:created],
|
|
||||||
incomplete_actions: [:git_write]
|
|
||||||
},
|
|
||||||
team_short: {
|
|
||||||
interval_days: [1],
|
|
||||||
completed_actions: [:git_write],
|
|
||||||
incomplete_actions: [:user_added]
|
|
||||||
},
|
|
||||||
trial_short: {
|
|
||||||
interval_days: [2],
|
|
||||||
completed_actions: [:git_write],
|
|
||||||
incomplete_actions: [:trial_started]
|
|
||||||
},
|
|
||||||
admin_verify: {
|
|
||||||
interval_days: [3],
|
|
||||||
completed_actions: [:git_write],
|
|
||||||
incomplete_actions: [:pipeline_created]
|
|
||||||
},
|
|
||||||
verify: {
|
|
||||||
interval_days: [4, 8, 13],
|
|
||||||
completed_actions: [:git_write],
|
|
||||||
incomplete_actions: [:pipeline_created]
|
|
||||||
},
|
|
||||||
trial: {
|
|
||||||
interval_days: [1, 5, 10],
|
|
||||||
completed_actions: [:git_write, :pipeline_created],
|
|
||||||
incomplete_actions: [:trial_started]
|
|
||||||
},
|
|
||||||
team: {
|
|
||||||
interval_days: [1, 5, 10],
|
|
||||||
completed_actions: [:git_write, :pipeline_created, :trial_started],
|
|
||||||
incomplete_actions: [:user_added]
|
|
||||||
}
|
|
||||||
}.freeze
|
|
||||||
|
|
||||||
def self.email_count_for_track(track)
|
|
||||||
interval_days = TRACKS.dig(track.to_sym, :interval_days)
|
|
||||||
interval_days&.count || 0
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
Namespaces::InProductMarketingEmailsService.prepend_mod
|
|
||||||
|
|
@ -1,26 +0,0 @@
|
||||||
# frozen_string_literal: true
|
|
||||||
|
|
||||||
module Users
|
|
||||||
class InProductMarketingEmailRecords
|
|
||||||
attr_reader :records
|
|
||||||
|
|
||||||
def initialize
|
|
||||||
@records = []
|
|
||||||
end
|
|
||||||
|
|
||||||
def save!
|
|
||||||
Users::InProductMarketingEmail.bulk_insert!(@records)
|
|
||||||
@records = []
|
|
||||||
end
|
|
||||||
|
|
||||||
def add(user, track: nil, series: nil)
|
|
||||||
@records << Users::InProductMarketingEmail.new(
|
|
||||||
user: user,
|
|
||||||
track: track,
|
|
||||||
series: series,
|
|
||||||
created_at: Time.zone.now,
|
|
||||||
updated_at: Time.zone.now
|
|
||||||
)
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
@ -62,7 +62,7 @@
|
||||||
|
|
||||||
= yield :page_specific_javascripts
|
= yield :page_specific_javascripts
|
||||||
|
|
||||||
= webpack_bundle_tag 'super_sidebar' if show_super_sidebar?
|
= webpack_bundle_tag 'super_sidebar'
|
||||||
|
|
||||||
= webpack_controller_bundle_tags
|
= webpack_controller_bundle_tags
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,51 +0,0 @@
|
||||||
- return unless current_user
|
|
||||||
|
|
||||||
%ul
|
|
||||||
%li.current-user
|
|
||||||
- if current_user_menu?(:profile)
|
|
||||||
= link_to current_user, class: 'gl-line-height-20!', data: { user: current_user.username, testid: 'user-profile-link', track_action: "click_link", track_label: "user_profile", track_property: "navigation_top" } do
|
|
||||||
= render 'layouts/header/current_user_dropdown_item'
|
|
||||||
- else
|
|
||||||
.gl-py-3.gl-px-4
|
|
||||||
= render 'layouts/header/current_user_dropdown_item'
|
|
||||||
%li.divider
|
|
||||||
- if can?(current_user, :update_user_status, current_user)
|
|
||||||
%li
|
|
||||||
= render Pajamas::ButtonComponent.new(button_options: { class: 'menu-item js-set-status-modal-trigger' }) do
|
|
||||||
- if current_user.status&.busy? || current_user.status&.customized?
|
|
||||||
= s_('SetStatusModal|Edit status')
|
|
||||||
- else
|
|
||||||
= s_('SetStatusModal|Set status')
|
|
||||||
= dispensable_render_if_exists 'layouts/header/start_trial'
|
|
||||||
- if current_user_menu?(:settings)
|
|
||||||
%li
|
|
||||||
= link_to s_("CurrentUser|Edit profile"), profile_path, data: { testid: 'edit_profile_link', track_action: "click_link", track_label: "user_edit_profile", track_property: "navigation_top" }
|
|
||||||
%li
|
|
||||||
= link_to s_("CurrentUser|Preferences"), profile_preferences_path, data: { track_action: "click_link", track_label: "user_preferences", track_property: "navigation_top" }
|
|
||||||
= render_if_exists 'layouts/header/buy_pipeline_minutes', project: @project, namespace: @group
|
|
||||||
|
|
||||||
- if current_user_menu?(:help)
|
|
||||||
%li.divider.d-md-none
|
|
||||||
%li.d-md-none
|
|
||||||
= link_to _("Help"), help_path, data: {track_action: 'click_link', track_label: 'help', track_property: 'navigation_top'}
|
|
||||||
%li.d-md-none
|
|
||||||
= link_to _("Support"), support_url, data: {track_action: 'click_link', track_label: 'support', track_property: 'navigation_top'}
|
|
||||||
%li.d-md-none
|
|
||||||
= render 'shared/help_dropdown_forum_link'
|
|
||||||
%li.d-md-none
|
|
||||||
= link_to _("Submit feedback"), Gitlab::Utils.append_path(promo_url, "submit-feedback"), data: {track_action: 'click_link', track_label: 'submit_feedback', track_property: 'navigation_top'}
|
|
||||||
- if current_user_menu?(:help) || current_user_menu?(:settings) || current_user_menu?(:profile)
|
|
||||||
%li.d-md-none
|
|
||||||
= render 'shared/user_dropdown_contributing_link'
|
|
||||||
= render 'shared/user_dropdown_instance_review'
|
|
||||||
- if Gitlab.com_but_not_canary?
|
|
||||||
%li.d-md-none
|
|
||||||
= link_to _("Switch to GitLab Next"), Gitlab::Saas.canary_toggle_com_url, data: { track_action: "click_link", track_label: "switch_to_canary", track_property: "navigation_top" }
|
|
||||||
|
|
||||||
%li.divider
|
|
||||||
.js-new-nav-toggle{ data: { enabled: show_super_sidebar?.to_s, endpoint: profile_preferences_path} }
|
|
||||||
|
|
||||||
- if current_user_menu?(:sign_out)
|
|
||||||
%li.divider
|
|
||||||
%li
|
|
||||||
= link_to _("Sign out"), destroy_user_session_path, method: :post, class: "sign-out-link", data: { testid: 'sign_out_link', track_action: "click_link", track_label: "user_sign_out", track_property: "navigation_top" }
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
.gl-font-weight-bold
|
|
||||||
= current_user.name
|
|
||||||
- if current_user.status&.busy?
|
|
||||||
= render Pajamas::BadgeComponent.new(s_('UserProfile|Busy'), size: 'sm', variant: 'warning')
|
|
||||||
= current_user.to_reference
|
|
||||||
- if current_user.status
|
|
||||||
.user-status.d-flex.align-items-center.gl-mt-2.gl-mr-0.gl-font-sm.has-tooltip{ title: current_user.status.message_html, data: { html: 'true', placement: 'bottom' } }
|
|
||||||
- if current_user.status.customized?
|
|
||||||
.user-status-emoji.d-flex.align-items-center
|
|
||||||
= emoji_icon current_user.status.emoji
|
|
||||||
%span.user-status-message.str-truncated
|
|
||||||
= current_user.status.message_html.html_safe
|
|
||||||
|
|
@ -1,6 +1,3 @@
|
||||||
- has_impersonation_link = header_link?(:admin_impersonation)
|
|
||||||
- user_status_data = user_status_properties(current_user)
|
|
||||||
|
|
||||||
%header.navbar.navbar-gitlab.navbar-expand-sm.js-navbar.legacy-top-bar{ data: { testid: 'navbar' } }
|
%header.navbar.navbar-gitlab.navbar-expand-sm.js-navbar.legacy-top-bar{ data: { testid: 'navbar' } }
|
||||||
%a.gl-sr-only.gl-accessibility{ href: "#content-body" } Skip to content
|
%a.gl-sr-only.gl-accessibility{ href: "#content-body" } Skip to content
|
||||||
.container-fluid
|
.container-fluid
|
||||||
|
|
@ -12,64 +9,6 @@
|
||||||
%ul.nav.navbar-nav.gl-w-full.gl-align-items-center.gl-justify-content-end
|
%ul.nav.navbar-nav.gl-w-full.gl-align-items-center.gl-justify-content-end
|
||||||
- if current_user
|
- if current_user
|
||||||
= render 'layouts/header/new_dropdown', class: 'gl-display-none gl-sm-display-block gl-white-space-nowrap gl-text-right'
|
= render 'layouts/header/new_dropdown', class: 'gl-display-none gl-sm-display-block gl-white-space-nowrap gl-text-right'
|
||||||
- if header_link?(:issues)
|
|
||||||
= nav_link(path: 'dashboard#issues', html_options: { class: "user-counter" }) do
|
|
||||||
= link_to assigned_issues_dashboard_path, title: _('Issues'), class: 'dashboard-shortcuts-issues js-prefetch-document', aria: { label: _('Issues') },
|
|
||||||
data: { testid: 'issues_shortcut_button', toggle: 'tooltip', placement: 'bottom',
|
|
||||||
track_label: 'main_navigation',
|
|
||||||
track_action: 'click_issues_link',
|
|
||||||
track_property: 'navigation_top',
|
|
||||||
container: 'body' } do
|
|
||||||
= sprite_icon('issues')
|
|
||||||
- issues_count = assigned_issuables_count(:issues)
|
|
||||||
= gl_badge_tag({ size: :sm, variant: :success }, { class: "gl-ml-n2 #{'gl-display-none' if issues_count == 0}", "aria-label": n_("%d assigned issue", "%d assigned issues", issues_count) % issues_count }) do
|
|
||||||
= assigned_open_issues_count_text
|
|
||||||
- if header_link?(:merge_requests)
|
|
||||||
= nav_link(path: 'dashboard#merge_requests', html_options: { class: "user-counter dropdown" }) do
|
|
||||||
- top_level_link = assigned_mrs_dashboard_path
|
|
||||||
= link_to top_level_link, class: 'dashboard-shortcuts-merge_requests has-tooltip', title: _('Merge requests'), aria: { label: _('Merge requests') },
|
|
||||||
data: { testid: 'merge_requests_shortcut_button',
|
|
||||||
toggle: "dropdown",
|
|
||||||
placement: 'bottom',
|
|
||||||
track_label: 'merge_requests_menu',
|
|
||||||
track_action: 'click_dropdown',
|
|
||||||
track_property: 'navigation_top',
|
|
||||||
container: 'body' } do
|
|
||||||
= sprite_icon('git-merge')
|
|
||||||
= gl_badge_tag({ size: :sm, variant: :warning }, { class: "js-merge-requests-count gl-ml-n2 #{'gl-display-none' if user_merge_requests_counts[:total] == 0}", "aria-label": n_("%d merge request", "%d merge requests", user_merge_requests_counts[:total]) % user_merge_requests_counts[:total] }) do
|
|
||||||
= number_with_delimiter(user_merge_requests_counts[:total])
|
|
||||||
= sprite_icon('chevron-down', css_class: 'caret-down gl-mx-0!')
|
|
||||||
.dropdown-menu.dropdown-menu-right
|
|
||||||
%ul
|
|
||||||
%li.dropdown-header
|
|
||||||
= _('Merge requests')
|
|
||||||
%li
|
|
||||||
= link_to assigned_mrs_dashboard_path,
|
|
||||||
class: 'gl-display-flex! gl-align-items-center js-prefetch-document',
|
|
||||||
data: {track_action: 'click_link', track_label: 'merge_requests_assigned', track_property: 'navigation_top'} do
|
|
||||||
= _('Assigned')
|
|
||||||
= gl_badge_tag({ variant: :neutral, size: :sm }, { class: "js-assigned-mr-count gl-ml-auto" }) do
|
|
||||||
= user_merge_requests_counts[:assigned]
|
|
||||||
%li
|
|
||||||
= link_to reviewer_mrs_dashboard_path,
|
|
||||||
class: 'dashboard-shortcuts-review_requests gl-display-flex! gl-align-items-center js-prefetch-document',
|
|
||||||
data: {track_action: 'click_link', track_label: 'merge_requests_to_review', track_property: 'navigation_top'} do
|
|
||||||
= _('Review requests')
|
|
||||||
= gl_badge_tag({ variant: :neutral, size: :sm }, { class: "js-reviewer-mr-count gl-ml-auto" }) do
|
|
||||||
= user_merge_requests_counts[:review_requested]
|
|
||||||
- if header_link?(:todos)
|
|
||||||
= nav_link(controller: 'dashboard/todos', html_options: { class: "user-counter" }) do
|
|
||||||
= link_to dashboard_todos_path, title: _('To-Do List'), aria: { label: _('To-Do List') }, class: 'shortcuts-todos js-prefetch-document',
|
|
||||||
data: { testid: 'todos-shortcut-button', toggle: 'tooltip', placement: 'bottom',
|
|
||||||
track_label: 'main_navigation',
|
|
||||||
track_action: 'click_to_do_link',
|
|
||||||
track_property: 'navigation_top',
|
|
||||||
container: 'body' } do
|
|
||||||
= sprite_icon('todo-done')
|
|
||||||
-# The todos' counter badge's visibility is being toggled by adding or removing the .hidden class in Js.
|
|
||||||
-# We'll eventually migrate to .gl-display-none: https://gitlab.com/gitlab-org/gitlab/-/issues/351792.
|
|
||||||
= gl_badge_tag({ size: :sm, variant: :info }, { class: "js-todos-count gl-ml-n2 #{'hidden' if todos_pending_count == 0}", "aria-label": _("Todos count") }) do
|
|
||||||
= todos_count_format(todos_pending_count)
|
|
||||||
%li.nav-item.header-help.dropdown.d-none.d-md-block
|
%li.nav-item.header-help.dropdown.d-none.d-md-block
|
||||||
= link_to help_path, class: 'header-help-dropdown-toggle gl-relative', data: { toggle: "dropdown", track_action: 'click_question_mark_link', track_label: 'main_navigation', track_property: 'navigation_top' } do
|
= link_to help_path, class: 'header-help-dropdown-toggle gl-relative', data: { toggle: "dropdown", track_action: 'click_question_mark_link', track_label: 'main_navigation', track_property: 'navigation_top' } do
|
||||||
%span.gl-sr-only
|
%span.gl-sr-only
|
||||||
|
|
@ -79,27 +18,6 @@
|
||||||
= sprite_icon('chevron-down', css_class: 'caret-down')
|
= sprite_icon('chevron-down', css_class: 'caret-down')
|
||||||
.dropdown-menu.dropdown-menu-right
|
.dropdown-menu.dropdown-menu-right
|
||||||
= render 'layouts/header/help_dropdown'
|
= render 'layouts/header/help_dropdown'
|
||||||
- if header_link?(:user_dropdown)
|
|
||||||
%li.nav-item.header-user.js-nav-user-dropdown.dropdown{ data: { testid: 'user-dropdown' }, class: ('mr-0' if has_impersonation_link) }
|
|
||||||
= link_to current_user, class: user_dropdown_class, data: { toggle: "dropdown", track_label: "profile_dropdown", track_action: "click_dropdown", track_property: "navigation_top" } do
|
|
||||||
= render Pajamas::AvatarComponent.new(current_user, size: 24, class: 'header-user-avatar', avatar_options: { data: { testid: 'user-avatar-content' } })
|
|
||||||
= render_if_exists 'layouts/header/user_notification_dot', project: project, namespace: group
|
|
||||||
= sprite_icon('chevron-down', css_class: 'caret-down')
|
|
||||||
.dropdown-menu.dropdown-menu-right
|
|
||||||
= render 'layouts/header/current_user_dropdown'
|
|
||||||
- if has_impersonation_link
|
|
||||||
%li.nav-item.impersonation.ml-0
|
|
||||||
= render Pajamas::ButtonComponent.new(href: admin_impersonation_path, icon: 'incognito', button_options: { title: _('Stop impersonation'), class: 'impersonation-btn', aria: { label: _('Stop impersonation') }, data: { method: :delete, toggle: 'tooltip', placement: 'bottom', container: 'body', testid: 'stop_impersonation_btn' } })
|
|
||||||
- if header_link?(:sign_in)
|
|
||||||
- if allow_signup?
|
|
||||||
%li.nav-item
|
|
||||||
= render Pajamas::ButtonComponent.new(href: new_user_registration_path) do
|
|
||||||
= _('Register')
|
|
||||||
%li.nav-item{ class: 'gl-flex-grow-0! gl-flex-basis-half!' }
|
|
||||||
= link_to _('Sign in'), new_session_path(:user, redirect_to_referer: 'yes')
|
|
||||||
|
|
||||||
- if display_whats_new?
|
- if display_whats_new?
|
||||||
#whats-new-app{ data: { version_digest: whats_new_version_digest } }
|
#whats-new-app{ data: { version_digest: whats_new_version_digest } }
|
||||||
|
|
||||||
- if can?(current_user, :update_user_status, current_user)
|
|
||||||
.js-set-status-modal-wrapper{ data: user_status_data }
|
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
- @breadcrumb_title = _("Help")
|
- @breadcrumb_title = _("Help")
|
||||||
- page_title _("Help")
|
- page_title _("Help")
|
||||||
- header_title _("Help"), help_path
|
- header_title _("Help"), help_path
|
||||||
- if show_super_sidebar?
|
- @force_desktop_expanded_sidebar = true
|
||||||
- @force_desktop_expanded_sidebar = true
|
|
||||||
|
|
||||||
= render template: "layouts/application"
|
= render template: "layouts/application"
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
- page_title _("Search")
|
- page_title _("Search")
|
||||||
- header_title _("Search"), search_path
|
- header_title _("Search"), search_path
|
||||||
- add_page_specific_style 'page_bundles/search'
|
- add_page_specific_style 'page_bundles/search'
|
||||||
- if show_super_sidebar?
|
- @force_desktop_expanded_sidebar = true
|
||||||
- @force_desktop_expanded_sidebar = true
|
|
||||||
|
|
||||||
= render template: "layouts/application"
|
= render template: "layouts/application"
|
||||||
|
|
|
||||||
|
|
@ -18,6 +18,7 @@
|
||||||
selected_file_template_project_id: "#{@project.service_desk_setting&.file_template_project_id}",
|
selected_file_template_project_id: "#{@project.service_desk_setting&.file_template_project_id}",
|
||||||
outgoing_name: "#{@project.service_desk_setting&.outgoing_name}",
|
outgoing_name: "#{@project.service_desk_setting&.outgoing_name}",
|
||||||
project_key: "#{@project.service_desk_setting&.project_key}",
|
project_key: "#{@project.service_desk_setting&.project_key}",
|
||||||
|
reopen_issue_on_external_participant_note: "#{@project.service_desk_setting&.reopen_issue_on_external_participant_note}",
|
||||||
add_external_participants_from_cc: "#{@project.service_desk_setting&.add_external_participants_from_cc}",
|
add_external_participants_from_cc: "#{@project.service_desk_setting&.add_external_participants_from_cc}",
|
||||||
templates: available_service_desk_templates_for(@project),
|
templates: available_service_desk_templates_for(@project),
|
||||||
public_project: "#{@project.public?}",
|
public_project: "#{@project.public?}",
|
||||||
|
|
|
||||||
|
|
@ -8,9 +8,7 @@
|
||||||
- elsif @search_objects.blank?
|
- elsif @search_objects.blank?
|
||||||
= render partial: "search/results/empty"
|
= render partial: "search/results/empty"
|
||||||
- else
|
- else
|
||||||
- statusBarClass = !show_super_sidebar? ? 'gl-lg-pl-5' : ''
|
.section
|
||||||
|
|
||||||
.section{ class: statusBarClass }
|
|
||||||
- if @scope == 'commits'
|
- if @scope == 'commits'
|
||||||
%ul.content-list.commit-list
|
%ul.content-list.commit-list
|
||||||
= render partial: "search/results/commit", collection: @search_objects
|
= render partial: "search/results/commit", collection: @search_objects
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,4 @@
|
||||||
- statusBarClass = !show_super_sidebar? ? 'gl-lg-pl-5' : ''
|
.section{ class: ('gl-lg-display-none' if @search_objects.to_a.empty?) }
|
||||||
- statusBarClass = statusBarClass + ' gl-lg-display-none' if @search_objects.to_a.empty?
|
|
||||||
|
|
||||||
.section{ class: statusBarClass }
|
|
||||||
.search-results-status
|
.search-results-status
|
||||||
.gl-display-flex.gl-flex-direction-column
|
.gl-display-flex.gl-flex-direction-column
|
||||||
.gl-p-5.gl-display-flex.gl-flex-wrap
|
.gl-p-5.gl-display-flex.gl-flex-wrap
|
||||||
|
|
|
||||||
|
|
@ -16,8 +16,8 @@
|
||||||
- page_description(_("%{count} %{scope} for term '%{term}'") % { count: @search_results.formatted_count(@scope), scope: @scope, term: @search_term })
|
- page_description(_("%{count} %{scope} for term '%{term}'") % { count: @search_results.formatted_count(@scope), scope: @scope, term: @search_term })
|
||||||
- page_card_attributes("Namespace" => @group&.full_path, "Project" => @project&.full_path)
|
- page_card_attributes("Namespace" => @group&.full_path, "Project" => @project&.full_path)
|
||||||
|
|
||||||
#js-search-topbar{ data: { "group-initial-json": group_attributes.to_json, "project-initial-json": project_attributes.to_json, "default-branch-name": @project&.default_branch } }
|
#js-search-topbar{ data: { "default-branch-name": @project&.default_branch } }
|
||||||
.results.gl-lg-display-flex.gl-mt-0
|
.results.gl-lg-display-flex.gl-mt-0
|
||||||
#js-search-sidebar{ data: { navigation_json: search_navigation_json, search_type: search_service.search_type } }
|
#js-search-sidebar{ data: { navigation_json: search_navigation_json, search_type: search_service.search_type, group_initial_json: group_attributes.to_json, project_initial_json: project_attributes.to_json, } }
|
||||||
- if @search_term
|
- if @search_term
|
||||||
= render 'search/results'
|
= render 'search/results'
|
||||||
|
|
|
||||||
|
|
@ -1,2 +1 @@
|
||||||
- current_href = Feature.enabled?(:global_ci_catalog, @user) ? href : nil
|
= render Pajamas::BadgeComponent.new(s_('CiCatalog|CI/CD catalog resource'), variant: 'info', icon: 'catalog-checkmark', class: css_class, href: href)
|
||||||
= render Pajamas::BadgeComponent.new(s_('CiCatalog|CI/CD catalog resource'), variant: 'info', icon: 'catalog-checkmark', class: css_class, href: current_href)
|
|
||||||
|
|
|
||||||
|
|
@ -19,4 +19,4 @@
|
||||||
|
|
||||||
%p
|
%p
|
||||||
= s_("Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run.")
|
= s_("Runners|Tags control which type of jobs a runner can handle. By tagging a runner, you make sure shared runners only handle the jobs they are equipped to run.")
|
||||||
= link_to _("Learn more."), help_page_path("ci/runners/configure_runners", anchor: "use-tags-to-control-which-jobs-a-runner-can-run"), target: '_blank'
|
= link_to _("Learn more."), help_page_path("ci/runners/configure_runners", anchor: "how-the-runner-uses-tags"), target: '_blank'
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
---
|
---
|
||||||
name: global_ci_catalog
|
name: encoding_logs_tree
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/133885
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/136323
|
||||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/427940
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/432559
|
||||||
milestone: '16.6'
|
milestone: '16.7'
|
||||||
type: development
|
type: development
|
||||||
group: group::pipeline authoring
|
group: group::source code
|
||||||
default_enabled: false
|
default_enabled: false
|
||||||
|
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
name: product_analytics_beta_optin
|
||||||
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/138469
|
||||||
|
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/433344
|
||||||
|
milestone: '16.7'
|
||||||
|
type: development
|
||||||
|
group: group::product analytics
|
||||||
|
default_enabled: false
|
||||||
|
|
@ -187,6 +187,8 @@
|
||||||
- 1
|
- 1
|
||||||
- - compliance_management_pending_status_check
|
- - compliance_management_pending_status_check
|
||||||
- 1
|
- 1
|
||||||
|
- - compliance_management_standards_adherence_export_mailer
|
||||||
|
- 1
|
||||||
- - compliance_management_standards_gitlab_at_least_two_approvals
|
- - compliance_management_standards_gitlab_at_least_two_approvals
|
||||||
- 1
|
- 1
|
||||||
- - compliance_management_standards_gitlab_base
|
- - compliance_management_standards_gitlab_base
|
||||||
|
|
|
||||||
|
|
@ -4,3 +4,4 @@ description: Backfill missing vulnerability dimissal information as a result of
|
||||||
feature_category: vulnerability_management
|
feature_category: vulnerability_management
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/126253
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/126253
|
||||||
milestone: '16.2'
|
milestone: '16.2'
|
||||||
|
finalized_by: '20231207220935'
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
---
|
---
|
||||||
migration_job_name: BackfillRootStorageStatisticsForkStorageSizes
|
migration_job_name: BackfillRootStorageStatisticsForkStorageSizes
|
||||||
description: Backfill the public_forks_storage_size, internal_forks_storage_size, and private_forks_storage_size columns on the namespace_root_storage_statistics table
|
description: Backfill the public_forks_storage_size, internal_forks_storage_size,
|
||||||
|
and private_forks_storage_size columns on the namespace_root_storage_statistics
|
||||||
|
table
|
||||||
feature_category: consumables_cost_management
|
feature_category: consumables_cost_management
|
||||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120916
|
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/120916
|
||||||
milestone: '16.1'
|
milestone: '16.1'
|
||||||
|
finalized_by: '20231207221036'
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,10 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddHomeOrganizationIdToUserPreferences < Gitlab::Database::Migration[2.2]
|
||||||
|
enable_lock_retries!
|
||||||
|
milestone '16.7'
|
||||||
|
|
||||||
|
def change
|
||||||
|
add_column(:user_preferences, :home_organization_id, :bigint, null: true)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddHomeOrganizationIdIndexToUserPreferences < Gitlab::Database::Migration[2.2]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
milestone '16.7'
|
||||||
|
|
||||||
|
INDEX = 'index_user_preferences_on_home_organization_id'
|
||||||
|
|
||||||
|
def up
|
||||||
|
add_concurrent_index(:user_preferences, :home_organization_id, name: INDEX)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
remove_concurrent_index_by_name(:user_preferences, name: INDEX)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class AddHomeOrganizationIdFkToUserPreferences < Gitlab::Database::Migration[2.2]
|
||||||
|
disable_ddl_transaction!
|
||||||
|
milestone '16.7'
|
||||||
|
|
||||||
|
def up
|
||||||
|
add_concurrent_foreign_key(:user_preferences, :organizations, column: :home_organization_id, on_delete: :nullify)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down
|
||||||
|
with_lock_retries do
|
||||||
|
remove_foreign_key_if_exists :user_preferences, column: :home_organization_id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class FinalizeBackfillMissingVulnerabilityDismissalDetails < Gitlab::Database::Migration[2.2]
|
||||||
|
milestone '16.7'
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||||
|
|
||||||
|
def up
|
||||||
|
ensure_batched_background_migration_is_finished(
|
||||||
|
job_class_name: 'BackfillMissingVulnerabilityDismissalDetails',
|
||||||
|
table_name: :vulnerabilities,
|
||||||
|
column_name: :id,
|
||||||
|
job_arguments: [],
|
||||||
|
finalize: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down; end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1,21 @@
|
||||||
|
# frozen_string_literal: true
|
||||||
|
|
||||||
|
class FinalizeBackfillRootStorageStatisticsForkStorageSizes < Gitlab::Database::Migration[2.2]
|
||||||
|
milestone '16.7'
|
||||||
|
|
||||||
|
disable_ddl_transaction!
|
||||||
|
|
||||||
|
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||||
|
|
||||||
|
def up
|
||||||
|
ensure_batched_background_migration_is_finished(
|
||||||
|
job_class_name: 'BackfillRootStorageStatisticsForkStorageSizes',
|
||||||
|
table_name: :namespace_root_storage_statistics,
|
||||||
|
column_name: :namespace_id,
|
||||||
|
job_arguments: [],
|
||||||
|
finalize: true
|
||||||
|
)
|
||||||
|
end
|
||||||
|
|
||||||
|
def down; end
|
||||||
|
end
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
624bef2f1f8ebd81bdc49c0007a72d77bad34db215dfee01101d976000964e28
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
4d4539b21d0f9ea2ade7a1223953f2aea36c4432e5f3b042266e98d71f6a9a48
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
7078ee3b40cd12e32c0d8f2cc1e55e19b4352dac8d2c708b617a2ff03e979c3a
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
644dfd3c7371feff5431900510e25fc2dc0c661c7ee9142bd26431c10d929416
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
5afbc4c287ce349c58ab70e2c8b44c833f075fe114cf2af2a29aaf4247053d82
|
||||||
|
|
@ -24663,6 +24663,7 @@ CREATE TABLE user_preferences (
|
||||||
enabled_zoekt boolean DEFAULT true NOT NULL,
|
enabled_zoekt boolean DEFAULT true NOT NULL,
|
||||||
keyboard_shortcuts_enabled boolean DEFAULT true NOT NULL,
|
keyboard_shortcuts_enabled boolean DEFAULT true NOT NULL,
|
||||||
time_display_format smallint DEFAULT 0 NOT NULL,
|
time_display_format smallint DEFAULT 0 NOT NULL,
|
||||||
|
home_organization_id bigint,
|
||||||
CONSTRAINT check_89bf269f41 CHECK ((char_length(diffs_deletion_color) <= 7)),
|
CONSTRAINT check_89bf269f41 CHECK ((char_length(diffs_deletion_color) <= 7)),
|
||||||
CONSTRAINT check_d07ccd35f7 CHECK ((char_length(diffs_addition_color) <= 7))
|
CONSTRAINT check_d07ccd35f7 CHECK ((char_length(diffs_addition_color) <= 7))
|
||||||
);
|
);
|
||||||
|
|
@ -34896,6 +34897,8 @@ CREATE INDEX index_user_phone_validations_on_dial_code_phone_number ON user_phon
|
||||||
|
|
||||||
CREATE INDEX index_user_preferences_on_gitpod_enabled ON user_preferences USING btree (gitpod_enabled);
|
CREATE INDEX index_user_preferences_on_gitpod_enabled ON user_preferences USING btree (gitpod_enabled);
|
||||||
|
|
||||||
|
CREATE INDEX index_user_preferences_on_home_organization_id ON user_preferences USING btree (home_organization_id);
|
||||||
|
|
||||||
CREATE UNIQUE INDEX index_user_preferences_on_user_id ON user_preferences USING btree (user_id);
|
CREATE UNIQUE INDEX index_user_preferences_on_user_id ON user_preferences USING btree (user_id);
|
||||||
|
|
||||||
CREATE INDEX index_user_project_callouts_on_project_id ON user_project_callouts USING btree (project_id);
|
CREATE INDEX index_user_project_callouts_on_project_id ON user_project_callouts USING btree (project_id);
|
||||||
|
|
@ -38158,6 +38161,9 @@ ALTER TABLE ONLY gitlab_subscriptions
|
||||||
ALTER TABLE ONLY abuse_events
|
ALTER TABLE ONLY abuse_events
|
||||||
ADD CONSTRAINT fk_e5ce49c215 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
|
ADD CONSTRAINT fk_e5ce49c215 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||||
|
|
||||||
|
ALTER TABLE ONLY user_preferences
|
||||||
|
ADD CONSTRAINT fk_e5e029c10b FOREIGN KEY (home_organization_id) REFERENCES organizations(id) ON DELETE SET NULL;
|
||||||
|
|
||||||
ALTER TABLE ONLY merge_requests
|
ALTER TABLE ONLY merge_requests
|
||||||
ADD CONSTRAINT fk_e719a85f8a FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
|
ADD CONSTRAINT fk_e719a85f8a FOREIGN KEY (author_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1249,8 +1249,15 @@ By default, Gitaly doesn't sign commits made using GitLab UI. For example, commi
|
||||||
- Web IDE.
|
- Web IDE.
|
||||||
- Merge requests.
|
- Merge requests.
|
||||||
|
|
||||||
You can configure Gitaly to sign commits made with the GitLab UI. The commits show as unverified and signed by an unknown
|
You can configure Gitaly to sign commits made with the GitLab UI.
|
||||||
user. Support for improvements is proposed in [issue 19185](https://gitlab.com/gitlab-org/gitlab/-/issues/19185).
|
|
||||||
|
By default, Gitaly sets the author of a commit as the committer. In this case,
|
||||||
|
it is harder to [Verify commits locally](../../user/project/repository/signed_commits/ssh.md#verify-commits-locally)
|
||||||
|
because the signature belongs to neither the author nor the committer of the commit.
|
||||||
|
|
||||||
|
You can configure Gitaly to reflect that a commit has been committed by your instance by
|
||||||
|
setting `committer_email` and `committer_name`. For example, on GitLab.com these configuration options are
|
||||||
|
set to `noreply@gitlab.com` and `GitLab`.
|
||||||
|
|
||||||
Configure Gitaly to sign commits made with the GitLab UI in one of two ways:
|
Configure Gitaly to sign commits made with the GitLab UI in one of two ways:
|
||||||
|
|
||||||
|
|
@ -1281,7 +1288,10 @@ Configure Gitaly to sign commits made with the GitLab UI in one of two ways:
|
||||||
# ...
|
# ...
|
||||||
git: {
|
git: {
|
||||||
# ...
|
# ...
|
||||||
|
committer_name: 'Your Instance',
|
||||||
|
committer_email: 'noreply@yourinstance.com',
|
||||||
signing_key: '/etc/gitlab/gitaly/signing_key.gpg',
|
signing_key: '/etc/gitlab/gitaly/signing_key.gpg',
|
||||||
|
# ...
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
@ -1310,6 +1320,8 @@ Configure Gitaly to sign commits made with the GitLab UI in one of two ways:
|
||||||
|
|
||||||
```toml
|
```toml
|
||||||
[git]
|
[git]
|
||||||
|
committer_name = "Your Instance"
|
||||||
|
committer_email = "noreply@yourinstance.com"
|
||||||
signing_key = "/etc/gitlab/gitaly/signing_key.gpg"
|
signing_key = "/etc/gitlab/gitaly/signing_key.gpg"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -435,7 +435,7 @@ You can change the maximum time a job can run before it times out:
|
||||||
|
|
||||||
- At the project-level in the [project's CI/CD settings](../ci/pipelines/settings.md#set-a-limit-for-how-long-jobs-can-run)
|
- At the project-level in the [project's CI/CD settings](../ci/pipelines/settings.md#set-a-limit-for-how-long-jobs-can-run)
|
||||||
for a given project. This limit must be between 10 minutes and 1 month.
|
for a given project. This limit must be between 10 minutes and 1 month.
|
||||||
- At the [runner level](../ci/runners/configure_runners.md#set-maximum-job-timeout-for-a-runner).
|
- At the [runner level](../ci/runners/configure_runners.md#set-the-maximum-job-timeout).
|
||||||
This limit must be 10 minutes or longer.
|
This limit must be 10 minutes or longer.
|
||||||
|
|
||||||
### Maximum number of deployment jobs in a pipeline
|
### Maximum number of deployment jobs in a pipeline
|
||||||
|
|
|
||||||
|
|
@ -108,13 +108,24 @@ Notify.test_email(u.email, "Test email for #{u.name}", 'Test email').deliver_now
|
||||||
## Disable database statement timeout
|
## Disable database statement timeout
|
||||||
|
|
||||||
You can disable the PostgreSQL statement timeout for the current Rails console
|
You can disable the PostgreSQL statement timeout for the current Rails console
|
||||||
session by running:
|
session.
|
||||||
|
|
||||||
|
In GitLab 15.11 and earlier, to disable the database statement timeout, run:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
ActiveRecord::Base.connection.execute('SET statement_timeout TO 0')
|
ActiveRecord::Base.connection.execute('SET statement_timeout TO 0')
|
||||||
```
|
```
|
||||||
|
|
||||||
This change only affects the current Rails console session and is
|
In GitLab 16.0 and later, [GitLab uses two database connections by default](../../update/versions/gitlab_16_changes.md#1600). To disable the database statement timeout, run:
|
||||||
|
|
||||||
|
```ruby
|
||||||
|
ActiveRecord::Base.connection.execute('SET statement_timeout TO 0')
|
||||||
|
Ci::ApplicationRecord.connection.execute('SET statement_timeout TO 0')
|
||||||
|
```
|
||||||
|
|
||||||
|
Instances running GitLab 16.0 and later reconfigured to use a single database connection should disable the database statement timeout using the code for GitLab 15.11 and earlier.
|
||||||
|
|
||||||
|
Disabling the database statement timeout affects only the current Rails console session and is
|
||||||
not persisted in the GitLab production environment or in the next Rails
|
not persisted in the GitLab production environment or in the next Rails
|
||||||
console session.
|
console session.
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -109,8 +109,7 @@ Prerequisites:
|
||||||
If you need support for namespace in the URL path to remove the requirement for wildcard DNS:
|
If you need support for namespace in the URL path to remove the requirement for wildcard DNS:
|
||||||
|
|
||||||
1. Enable the GitLab Pages flag for this feature by adding
|
1. Enable the GitLab Pages flag for this feature by adding
|
||||||
`gitlab_pages["namespace_in_path"] = true` to `gitlab.rb`. For more information,
|
`gitlab_pages["namespace_in_path"] = true` to `/etc/gitlab/gitlab.rb`.
|
||||||
see [Use environment variables](#use-environment-variables).
|
|
||||||
1. In your DNS provider, add entries for `example.com` and `projects.example.com`.
|
1. In your DNS provider, add entries for `example.com` and `projects.example.com`.
|
||||||
In both lines, replace `example.com` with your domain name, and `192.0.0.0` with
|
In both lines, replace `example.com` with your domain name, and `192.0.0.0` with
|
||||||
the IPv4 version of your IP address. The entries look like this:
|
the IPv4 version of your IP address. The entries look like this:
|
||||||
|
|
@ -214,8 +213,7 @@ Prerequisites:
|
||||||
|
|
||||||
pages_nginx['enable'] = true
|
pages_nginx['enable'] = true
|
||||||
|
|
||||||
# Set this feature flag to enable this feature
|
# Set this flag to enable this feature
|
||||||
# For more information, see https://docs.gitlab.com/ee/administration/pages/index.html#use-environment-variables
|
|
||||||
gitlab_pages["namespace_in_path"] = true
|
gitlab_pages["namespace_in_path"] = true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
@ -304,8 +302,7 @@ daemon doesn't listen to the outside world:
|
||||||
pages_nginx['enable'] = true
|
pages_nginx['enable'] = true
|
||||||
pages_nginx['redirect_http_to_https'] = true
|
pages_nginx['redirect_http_to_https'] = true
|
||||||
|
|
||||||
# Set this feature flag to enable this feature
|
# Set this flag to enable this feature
|
||||||
# For more information, see https://docs.gitlab.com/ee/administration/pages/index.html#use-environment-variables
|
|
||||||
gitlab_pages["namespace_in_path"] = true
|
gitlab_pages["namespace_in_path"] = true
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -20281,6 +20281,31 @@ Returns [`WorkItem`](#workitem).
|
||||||
| ---- | ---- | ----------- |
|
| ---- | ---- | ----------- |
|
||||||
| <a id="groupworkitemiid"></a>`iid` | [`String!`](#string) | IID of the work item. |
|
| <a id="groupworkitemiid"></a>`iid` | [`String!`](#string) | IID of the work item. |
|
||||||
|
|
||||||
|
##### `Group.workItemStateCounts`
|
||||||
|
|
||||||
|
Counts of work items by state for the namespace. Returns `null` if the `namespace_level_work_items` feature flag is disabled.
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
**Introduced** in 16.7.
|
||||||
|
This feature is an Experiment. It can be changed or removed at any time.
|
||||||
|
|
||||||
|
Returns [`WorkItemStateCountsType`](#workitemstatecountstype).
|
||||||
|
|
||||||
|
###### Arguments
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| <a id="groupworkitemstatecountsauthorusername"></a>`authorUsername` **{warning-solid}** | [`String`](#string) | **Introduced** in 15.9. This feature is an Experiment. It can be changed or removed at any time. Filter work items by author username. |
|
||||||
|
| <a id="groupworkitemstatecountsiid"></a>`iid` | [`String`](#string) | IID of the work item. For example, "1". |
|
||||||
|
| <a id="groupworkitemstatecountsiids"></a>`iids` | [`[String!]`](#string) | List of IIDs of work items. For example, `["1", "2"]`. |
|
||||||
|
| <a id="groupworkitemstatecountsin"></a>`in` | [`[IssuableSearchableField!]`](#issuablesearchablefield) | Specify the fields to perform the search in. Defaults to `[TITLE, DESCRIPTION]`. Requires the `search` argument.'. |
|
||||||
|
| <a id="groupworkitemstatecountsrequirementlegacywidget"></a>`requirementLegacyWidget` **{warning-solid}** | [`RequirementLegacyFilterInput`](#requirementlegacyfilterinput) | **Deprecated** in 15.9. Use work item IID filter instead. |
|
||||||
|
| <a id="groupworkitemstatecountssearch"></a>`search` | [`String`](#string) | Search query for title or description. |
|
||||||
|
| <a id="groupworkitemstatecountssort"></a>`sort` | [`WorkItemSort`](#workitemsort) | Sort work items by criteria. |
|
||||||
|
| <a id="groupworkitemstatecountsstate"></a>`state` | [`IssuableState`](#issuablestate) | Current state of the work item. |
|
||||||
|
| <a id="groupworkitemstatecountsstatuswidget"></a>`statusWidget` | [`StatusFilterInput`](#statusfilterinput) | Input for status widget filter. Ignored if `work_items_mvc_2` is disabled. |
|
||||||
|
| <a id="groupworkitemstatecountstypes"></a>`types` | [`[IssueType!]`](#issuetype) | Filter work items by the given work item types. |
|
||||||
|
|
||||||
##### `Group.workItemTypes`
|
##### `Group.workItemTypes`
|
||||||
|
|
||||||
Work item types available to the group.
|
Work item types available to the group.
|
||||||
|
|
@ -25587,6 +25612,31 @@ Returns [`VulnerabilitySeveritiesCount`](#vulnerabilityseveritiescount).
|
||||||
| <a id="projectvulnerabilityseveritiescountseverity"></a>`severity` | [`[VulnerabilitySeverity!]`](#vulnerabilityseverity) | Filter vulnerabilities by severity. |
|
| <a id="projectvulnerabilityseveritiescountseverity"></a>`severity` | [`[VulnerabilitySeverity!]`](#vulnerabilityseverity) | Filter vulnerabilities by severity. |
|
||||||
| <a id="projectvulnerabilityseveritiescountstate"></a>`state` | [`[VulnerabilityState!]`](#vulnerabilitystate) | Filter vulnerabilities by state. |
|
| <a id="projectvulnerabilityseveritiescountstate"></a>`state` | [`[VulnerabilityState!]`](#vulnerabilitystate) | Filter vulnerabilities by state. |
|
||||||
|
|
||||||
|
##### `Project.workItemStateCounts`
|
||||||
|
|
||||||
|
Counts of work items by state for the project.
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
**Introduced** in 16.7.
|
||||||
|
This feature is an Experiment. It can be changed or removed at any time.
|
||||||
|
|
||||||
|
Returns [`WorkItemStateCountsType`](#workitemstatecountstype).
|
||||||
|
|
||||||
|
###### Arguments
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| <a id="projectworkitemstatecountsauthorusername"></a>`authorUsername` **{warning-solid}** | [`String`](#string) | **Introduced** in 15.9. This feature is an Experiment. It can be changed or removed at any time. Filter work items by author username. |
|
||||||
|
| <a id="projectworkitemstatecountsiid"></a>`iid` | [`String`](#string) | IID of the work item. For example, "1". |
|
||||||
|
| <a id="projectworkitemstatecountsiids"></a>`iids` | [`[String!]`](#string) | List of IIDs of work items. For example, `["1", "2"]`. |
|
||||||
|
| <a id="projectworkitemstatecountsin"></a>`in` | [`[IssuableSearchableField!]`](#issuablesearchablefield) | Specify the fields to perform the search in. Defaults to `[TITLE, DESCRIPTION]`. Requires the `search` argument.'. |
|
||||||
|
| <a id="projectworkitemstatecountsrequirementlegacywidget"></a>`requirementLegacyWidget` **{warning-solid}** | [`RequirementLegacyFilterInput`](#requirementlegacyfilterinput) | **Deprecated** in 15.9. Use work item IID filter instead. |
|
||||||
|
| <a id="projectworkitemstatecountssearch"></a>`search` | [`String`](#string) | Search query for title or description. |
|
||||||
|
| <a id="projectworkitemstatecountssort"></a>`sort` | [`WorkItemSort`](#workitemsort) | Sort work items by criteria. |
|
||||||
|
| <a id="projectworkitemstatecountsstate"></a>`state` | [`IssuableState`](#issuablestate) | Current state of the work item. |
|
||||||
|
| <a id="projectworkitemstatecountsstatuswidget"></a>`statusWidget` | [`StatusFilterInput`](#statusfilterinput) | Input for status widget filter. Ignored if `work_items_mvc_2` is disabled. |
|
||||||
|
| <a id="projectworkitemstatecountstypes"></a>`types` | [`[IssueType!]`](#issuetype) | Filter work items by the given work item types. |
|
||||||
|
|
||||||
##### `Project.workItemTypes`
|
##### `Project.workItemTypes`
|
||||||
|
|
||||||
Work item types available to the project.
|
Work item types available to the project.
|
||||||
|
|
@ -28684,6 +28734,18 @@ Check permissions for the current user on a work item.
|
||||||
| <a id="workitempermissionssetworkitemmetadata"></a>`setWorkItemMetadata` | [`Boolean!`](#boolean) | If `true`, the user can perform `set_work_item_metadata` on this resource. |
|
| <a id="workitempermissionssetworkitemmetadata"></a>`setWorkItemMetadata` | [`Boolean!`](#boolean) | If `true`, the user can perform `set_work_item_metadata` on this resource. |
|
||||||
| <a id="workitempermissionsupdateworkitem"></a>`updateWorkItem` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_work_item` on this resource. |
|
| <a id="workitempermissionsupdateworkitem"></a>`updateWorkItem` | [`Boolean!`](#boolean) | If `true`, the user can perform `update_work_item` on this resource. |
|
||||||
|
|
||||||
|
### `WorkItemStateCountsType`
|
||||||
|
|
||||||
|
Represents total number of work items for the represented states.
|
||||||
|
|
||||||
|
#### Fields
|
||||||
|
|
||||||
|
| Name | Type | Description |
|
||||||
|
| ---- | ---- | ----------- |
|
||||||
|
| <a id="workitemstatecountstypeall"></a>`all` | [`Int`](#int) | Number of work items for the project or group. |
|
||||||
|
| <a id="workitemstatecountstypeclosed"></a>`closed` | [`Int`](#int) | Number of work items with state CLOSED for the project or group. |
|
||||||
|
| <a id="workitemstatecountstypeopened"></a>`opened` | [`Int`](#int) | Number of work items with state OPENED for the project or group. |
|
||||||
|
|
||||||
### `WorkItemType`
|
### `WorkItemType`
|
||||||
|
|
||||||
#### Fields
|
#### Fields
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load Diff
|
|
@ -45,7 +45,7 @@ can't link to files outside it.
|
||||||
|
|
||||||
To ensure maximum availability of the cache, do one or more of the following:
|
To ensure maximum availability of the cache, do one or more of the following:
|
||||||
|
|
||||||
- [Tag your runners](../runners/configure_runners.md#use-tags-to-control-which-jobs-a-runner-can-run) and use the tag on jobs
|
- [Tag your runners](../runners/configure_runners.md#control-jobs-that-a-runner-can-run) and use the tag on jobs
|
||||||
that share the cache.
|
that share the cache.
|
||||||
- [Use runners that are only available to a particular project](../runners/runners_scope.md#prevent-a-project-runner-from-being-enabled-for-other-projects).
|
- [Use runners that are only available to a particular project](../runners/runners_scope.md#prevent-a-project-runner-from-being-enabled-for-other-projects).
|
||||||
- [Use a `key`](../yaml/index.md#cachekey) that fits your workflow. For example,
|
- [Use a `key`](../yaml/index.md#cachekey) that fits your workflow. For example,
|
||||||
|
|
|
||||||
|
|
@ -216,6 +216,17 @@ If you disable [catalog resource setting](#set-a-component-project-as-a-catalog-
|
||||||
the component project and all versions are removed from the catalog. To publish it again,
|
the component project and all versions are removed from the catalog. To publish it again,
|
||||||
you must re-enable the setting and release a new version.
|
you must re-enable the setting and release a new version.
|
||||||
|
|
||||||
|
### Unpublish a component project
|
||||||
|
|
||||||
|
To remove a component project from the catalog, turn off the [**CI/CD Catalog resource**](#set-a-component-project-as-a-catalog-resource) toggle.
|
||||||
|
in the project settings.
|
||||||
|
|
||||||
|
WARNING:
|
||||||
|
This action destroys the metadata about the component project and its versions published
|
||||||
|
in the catalog. The project and its repository still exist, but are not visible in the catalog.
|
||||||
|
|
||||||
|
To publish the component project in the catalog again, you need to [publish a new release](#publish-a-new-release).
|
||||||
|
|
||||||
## Best practices
|
## Best practices
|
||||||
|
|
||||||
This section describes some best practices for creating high quality component projects.
|
This section describes some best practices for creating high quality component projects.
|
||||||
|
|
|
||||||
|
|
@ -466,7 +466,7 @@ Some key details about runners:
|
||||||
|
|
||||||
- Runners can be [configured](../runners/runners_scope.md) to be shared across an instance,
|
- Runners can be [configured](../runners/runners_scope.md) to be shared across an instance,
|
||||||
a group, or dedicated to a single project.
|
a group, or dedicated to a single project.
|
||||||
- You can use the [`tags` keyword](../runners/configure_runners.md#use-tags-to-control-which-jobs-a-runner-can-run)
|
- You can use the [`tags` keyword](../runners/configure_runners.md#control-jobs-that-a-runner-can-run)
|
||||||
for finer control, and associate runners with specific jobs. For example, you can use a tag for jobs that
|
for finer control, and associate runners with specific jobs. For example, you can use a tag for jobs that
|
||||||
require dedicated, more powerful, or specific hardware.
|
require dedicated, more powerful, or specific hardware.
|
||||||
- GitLab has [autoscaling for runners](https://docs.gitlab.com/runner/configuration/autoscale.html).
|
- GitLab has [autoscaling for runners](https://docs.gitlab.com/runner/configuration/autoscale.html).
|
||||||
|
|
|
||||||
|
|
@ -482,7 +482,7 @@ Some key details about runners:
|
||||||
|
|
||||||
- Runners can be [configured](../runners/runners_scope.md) to be shared across an instance,
|
- Runners can be [configured](../runners/runners_scope.md) to be shared across an instance,
|
||||||
a group, or dedicated to a single project.
|
a group, or dedicated to a single project.
|
||||||
- You can use the [`tags` keyword](../runners/configure_runners.md#use-tags-to-control-which-jobs-a-runner-can-run)
|
- You can use the [`tags` keyword](../runners/configure_runners.md#control-jobs-that-a-runner-can-run)
|
||||||
for finer control, and associate runners with specific jobs. For example, you can use a tag for jobs that
|
for finer control, and associate runners with specific jobs. For example, you can use a tag for jobs that
|
||||||
require dedicated, more powerful, or specific hardware.
|
require dedicated, more powerful, or specific hardware.
|
||||||
- GitLab has [autoscaling for runners](https://docs.gitlab.com/runner/configuration/autoscale.html).
|
- GitLab has [autoscaling for runners](https://docs.gitlab.com/runner/configuration/autoscale.html).
|
||||||
|
|
|
||||||
|
|
@ -225,7 +225,7 @@ You can define how long a job can run before it times out.
|
||||||
|
|
||||||
Jobs that exceed the timeout are marked as failed.
|
Jobs that exceed the timeout are marked as failed.
|
||||||
|
|
||||||
You can override this value [for individual runners](../runners/configure_runners.md#set-maximum-job-timeout-for-a-runner).
|
You can override this value [for individual runners](../runners/configure_runners.md#set-the-maximum-job-timeout).
|
||||||
|
|
||||||
## Pipeline badges
|
## Pipeline badges
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -11,53 +11,79 @@ If you have installed your own runners, you can configure and secure them in Git
|
||||||
If you need to configure runners on the machine where you installed GitLab Runner, see
|
If you need to configure runners on the machine where you installed GitLab Runner, see
|
||||||
[the GitLab Runner documentation](https://docs.gitlab.com/runner/configuration/).
|
[the GitLab Runner documentation](https://docs.gitlab.com/runner/configuration/).
|
||||||
|
|
||||||
## Manually clear the runner cache
|
## Set the maximum job timeout
|
||||||
|
|
||||||
Read [clearing the cache](../caching/index.md#clearing-the-cache).
|
You can specify a maximum job timeout for each runner to prevent projects
|
||||||
|
with longer job timeouts from using the runner. The maximum job timeout is
|
||||||
|
used of it is shorter than the job timeout defined in the project.
|
||||||
|
|
||||||
## Set maximum job timeout for a runner
|
### For a shared runner
|
||||||
|
|
||||||
For each runner, you can specify a *maximum job timeout*. This timeout,
|
Prerequisites:
|
||||||
if smaller than the [project defined timeout](../pipelines/settings.md#set-a-limit-for-how-long-jobs-can-run), takes precedence.
|
|
||||||
|
|
||||||
This feature can be used to prevent your shared runner from being overwhelmed
|
- You must be an administrator.
|
||||||
by a project that has jobs with a long timeout (for example, one week).
|
|
||||||
|
|
||||||
On GitLab.com, you cannot override the job timeout for shared runners and must use the [project defined timeout](../pipelines/settings.md#set-a-limit-for-how-long-jobs-can-run).
|
On GitLab.com, you cannot override the job timeout for shared runners and must use the [project defined timeout](../pipelines/settings.md#set-a-limit-for-how-long-jobs-can-run) instead.
|
||||||
|
|
||||||
|
To set the maximum job timeout:
|
||||||
|
|
||||||
|
1. On the left sidebar, at the bottom, select **Admin Area**.
|
||||||
|
1. Select **CI/CD > Runners**.
|
||||||
|
1. To the right of the runner, you want to edit, select **Edit** (**{pencil}**).
|
||||||
|
1. In the **Maximum job timeout** field, enter a value in seconds. The minimum amount is 600 seconds (10 minutes).
|
||||||
|
1. Select **Save changes**.
|
||||||
|
|
||||||
|
### For a group runner
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You must have the Owner role for the group.
|
||||||
|
|
||||||
|
To set the maximum job timeout:
|
||||||
|
|
||||||
|
1. On the left sidebar, select **Search or go to** and find your group.
|
||||||
|
1. Select **Build > Runners**.
|
||||||
|
1. To the right of the runner you want to edit, select **Edit** (**{pencil}**).
|
||||||
|
1. In the **Maximum job timeout** field, enter a value in seconds. The minimum amount is 600 seconds (10 minutes).
|
||||||
|
1. Select **Save changes**.
|
||||||
|
|
||||||
|
### For a project runner
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You must have the Owner role for the project.
|
||||||
|
|
||||||
To set the maximum job timeout:
|
To set the maximum job timeout:
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to** and find your project.
|
1. On the left sidebar, select **Search or go to** and find your project.
|
||||||
1. Select **Settings > CI/CD**.
|
1. Select **Settings > CI/CD**.
|
||||||
1. Expand **Runners**.
|
1. Expand **Runners**.
|
||||||
1. Select your project runner to edit the settings.
|
1. To the right of the runner you want to edit, select **Edit** (**{pencil}**).
|
||||||
1. Enter a value under **Maximum job timeout**. Must be 10 minutes or more. If not
|
1. In the **Maximum job timeout** field, enter a value in seconds. The minimum amount is 600 seconds (10 minutes). If not defined, the [job timeout for the project](../pipelines/settings.md#set-a-limit-for-how-long-jobs-can-run) is used instead.
|
||||||
defined, the [project's job timeout setting](../pipelines/settings.md#set-a-limit-for-how-long-jobs-can-run)
|
|
||||||
is used.
|
|
||||||
1. Select **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
How this feature works:
|
## How maximum job timeout works
|
||||||
|
|
||||||
**Example 1 - Runner timeout bigger than project timeout**
|
**Example 1 - Runner timeout bigger than project timeout**
|
||||||
|
|
||||||
1. You set the _maximum job timeout_ for a runner to 24 hours
|
1. You set the _maximum job timeout_ for a runner to 24 hours.
|
||||||
1. You set the _CI/CD Timeout_ for a project to **2 hours**
|
1. You set the _CI/CD Timeout_ for a project to **2 hours**.
|
||||||
1. You start a job
|
1. You start a job.
|
||||||
1. The job, if running longer, times out after **2 hours**
|
1. The job, if running longer, times out after **2 hours**.
|
||||||
|
|
||||||
**Example 2 - Runner timeout not configured**
|
**Example 2 - Runner timeout not configured**
|
||||||
|
|
||||||
1. You remove the _maximum job timeout_ configuration from a runner
|
1. You remove the _maximum job timeout_ configuration from a runner.
|
||||||
1. You set the _CI/CD Timeout_ for a project to **2 hours**
|
1. You set the _CI/CD Timeout_ for a project to **2 hours**.
|
||||||
1. You start a job
|
1. You start a job.
|
||||||
1. The job, if running longer, times out after **2 hours**
|
1. The job, if running longer, times out after **2 hours**.
|
||||||
|
|
||||||
**Example 3 - Runner timeout smaller than project timeout**
|
**Example 3 - Runner timeout smaller than project timeout**
|
||||||
|
|
||||||
1. You set the _maximum job timeout_ for a runner to **30 minutes**
|
1. You set the _maximum job timeout_ for a runner to **30 minutes**.
|
||||||
1. You set the _CI/CD Timeout_ for a project to 2 hours
|
1. You set the _CI/CD Timeout_ for a project to 2 hours.
|
||||||
1. You start a job
|
1. You start a job.
|
||||||
1. The job, if running longer, times out after **30 minutes**
|
1. The job, if running longer, times out after **30 minutes**.
|
||||||
|
|
||||||
## Set `script` and `after_script` timeouts
|
## Set `script` and `after_script` timeouts
|
||||||
|
|
||||||
|
|
@ -66,7 +92,7 @@ How this feature works:
|
||||||
To control the amount of time `script` and `after_script` runs before it terminates, you can set specify a timeout.
|
To control the amount of time `script` and `after_script` runs before it terminates, you can set specify a timeout.
|
||||||
|
|
||||||
For example, you can specify a timeout to terminate a long-running `script` early, so that artifacts and caches can still be uploaded
|
For example, you can specify a timeout to terminate a long-running `script` early, so that artifacts and caches can still be uploaded
|
||||||
before the [job timeout](#set-maximum-job-timeout-for-a-runner) is exceeded.
|
before the job timeout is exceeded.
|
||||||
|
|
||||||
- To set a timeout for `script`, use the job variable `RUNNER_SCRIPT_TIMEOUT`.
|
- To set a timeout for `script`, use the job variable `RUNNER_SCRIPT_TIMEOUT`.
|
||||||
- To set a timeout for `after_script`, and override the default of 5 minutes, use the job variable `RUNNER_AFTER_SCRIPT_TIMEOUT`.
|
- To set a timeout for `after_script`, and override the default of 5 minutes, use the job variable `RUNNER_AFTER_SCRIPT_TIMEOUT`.
|
||||||
|
|
@ -105,26 +131,11 @@ of shared runners on large GitLab instances. This ensures that you
|
||||||
control access to your GitLab instances and secure [runner executors](https://docs.gitlab.com/runner/executors/).
|
control access to your GitLab instances and secure [runner executors](https://docs.gitlab.com/runner/executors/).
|
||||||
|
|
||||||
If certain executors run a job, the file system, the code the runner executes,
|
If certain executors run a job, the file system, the code the runner executes,
|
||||||
and the runner authentication token may be exposed. This means that anyone that runs jobs
|
and the runner authentication token may be exposed. This means that anyone who runs jobs
|
||||||
on a _shared runner_ can access another user's code that runs on the runner.
|
on a _shared runner_ can access another user's code that runs on the runner.
|
||||||
Users with access to the runner authentication token can use it to create a clone of
|
Users with access to the runner authentication token can use it to create a clone of
|
||||||
a runner and submit false jobs in a vector attack. For more information, see [Security Considerations](https://docs.gitlab.com/runner/security/).
|
a runner and submit false jobs in a vector attack. For more information, see [Security Considerations](https://docs.gitlab.com/runner/security/).
|
||||||
|
|
||||||
### Prevent runners from revealing sensitive information
|
|
||||||
|
|
||||||
To ensure runners don't reveal sensitive information, you can configure them to only run jobs
|
|
||||||
on [protected branches](../../user/project/protected_branches.md), or jobs that have [protected tags](../../user/project/protected_tags.md).
|
|
||||||
|
|
||||||
To prevent runners from revealing sensitive information:
|
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to** and find your project.
|
|
||||||
1. Select **Settings > CI/CD**.
|
|
||||||
1. Expand **Runners**.
|
|
||||||
1. Find the runner you want to protect or unprotect. Make sure the runner is enabled.
|
|
||||||
1. Select **Edit** (**{pencil}**).
|
|
||||||
1. Select the **Protected** checkbox.
|
|
||||||
1. Select **Save changes**.
|
|
||||||
|
|
||||||
### Using shared runners in forked projects
|
### Using shared runners in forked projects
|
||||||
|
|
||||||
When a project is forked, the job settings related to jobs are copied. If you have shared runners
|
When a project is forked, the job settings related to jobs are copied. If you have shared runners
|
||||||
|
|
@ -179,37 +190,129 @@ To reset the runner authentication token:
|
||||||
- [Create a project runner](runners_scope.md#create-a-project-runner-with-a-runner-authentication-token).
|
- [Create a project runner](runners_scope.md#create-a-project-runner-with-a-runner-authentication-token).
|
||||||
1. Optional. To verify that the previous runner authentication token has been revoked, use the [Runners API](../../api/runners.md#verify-authentication-for-a-registered-runner).
|
1. Optional. To verify that the previous runner authentication token has been revoked, use the [Runners API](../../api/runners.md#verify-authentication-for-a-registered-runner).
|
||||||
|
|
||||||
## Use tags to control which jobs a runner can run
|
### Automatically rotate runner authentication tokens
|
||||||
|
|
||||||
You can use [tags](../yaml/index.md#tags) to ensure that runners only run the jobs they are equipped
|
You can specify an interval for runner authentication tokens to rotate.
|
||||||
to run. For example, you can specify the `rails` tag for runners that have the dependencies to run
|
This rotation helps ensure the security of the tokens assigned to your runners.
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- Runners must use [GitLab Runner 15.3 or later](https://docs.gitlab.com/runner/#gitlab-runner-versions).
|
||||||
|
- You must be an administrator.
|
||||||
|
|
||||||
|
To automatically rotate runner authentication tokens:
|
||||||
|
|
||||||
|
1. On the left sidebar, at the bottom, select **Admin Area**.
|
||||||
|
1. On the left sidebar, select **Settings > CI/CD**.
|
||||||
|
1. Expand **Continuous Integration and Deployment**
|
||||||
|
1. Set a **Runners expiration** time for runners, leave empty for no expiration.
|
||||||
|
1. Select **Save changes**.
|
||||||
|
|
||||||
|
Before the interval expires, runners automatically request a new runner authentication token.
|
||||||
|
|
||||||
|
## Prevent runners from revealing sensitive information
|
||||||
|
|
||||||
|
To ensure runners don't reveal sensitive information, you can configure them to only run jobs
|
||||||
|
on [protected branches](../../user/project/protected_branches.md), or jobs that have [protected tags](../../user/project/protected_tags.md).
|
||||||
|
|
||||||
|
### For a shared runner
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You must be an administrator.
|
||||||
|
|
||||||
|
1. On the left sidebar, at the bottom, select **Admin Area**.
|
||||||
|
1. Select **CI/CD > Runners**.
|
||||||
|
1. To the right of the runner you want to protect, select **Edit** (**{pencil}**).
|
||||||
|
1. Select the **Protected** checkbox.
|
||||||
|
1. Select **Save changes**.
|
||||||
|
|
||||||
|
### For a group runner
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You must have the Owner role for the group.
|
||||||
|
|
||||||
|
1. On the left sidebar, select **Search or go to** and find your group.
|
||||||
|
1. Select **Build > Runners**.
|
||||||
|
1. To the right of the runner you want to protect, select **Edit** (**{pencil}**).
|
||||||
|
1. Select the **Protected** checkbox.
|
||||||
|
1. Select **Save changes**.
|
||||||
|
|
||||||
|
### For a project runner
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You must have the Owner role for the project.
|
||||||
|
|
||||||
|
1. On the left sidebar, select **Search or go to** and find your project.
|
||||||
|
1. Select **Settings > CI/CD**.
|
||||||
|
1. Expand **Runners**.
|
||||||
|
1. To the right of the runner you want to protect, select **Edit** (**{pencil}**).
|
||||||
|
1. Select the **Protected** checkbox.
|
||||||
|
1. Select **Save changes**.
|
||||||
|
|
||||||
|
## Control jobs that a runner can run
|
||||||
|
|
||||||
|
You can use [tags](../yaml/index.md#tags) to control the jobs a runner can run.
|
||||||
|
For example, you can specify the `rails` tag for runners that have the dependencies to run
|
||||||
Rails test suites.
|
Rails test suites.
|
||||||
|
|
||||||
GitLab CI/CD tags are different to Git tags. GitLab CI/CD tags are associated with runners.
|
GitLab CI/CD tags are different to Git tags. GitLab CI/CD tags are associated with runners.
|
||||||
Git tags are associated with commits.
|
Git tags are associated with commits.
|
||||||
|
|
||||||
### Set a runner to run untagged jobs
|
### For a shared runner
|
||||||
|
|
||||||
When you [register a runner](https://docs.gitlab.com/runner/register/), its default behavior is to **only pick**
|
Prerequisites:
|
||||||
[tagged jobs](../yaml/index.md#tags).
|
|
||||||
To change this, you must have the Owner role for the project.
|
|
||||||
|
|
||||||
To make a runner pick untagged jobs:
|
- You must be an administrator.
|
||||||
|
|
||||||
|
To set the maximum job timeout:
|
||||||
|
|
||||||
|
1. On the left sidebar, at the bottom, select **Admin Area**.
|
||||||
|
1. Select **CI/CD > Runners**.
|
||||||
|
1. To the right of the runner you want to edit, select **Edit** (**{pencil}**).
|
||||||
|
1. Set the runner to run tagged or untagged jobs:
|
||||||
|
- To run tagged jobs, in the **Tags** field, enter the job tags separated with a comma. For example, `macos`, `rails`.
|
||||||
|
- To run untagged jobs, select the **Run untagged jobs** checkbox.
|
||||||
|
1. Select **Save changes**.
|
||||||
|
|
||||||
|
### For a group runner
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You must have the Owner role for the group.
|
||||||
|
|
||||||
|
To set the maximum job timeout:
|
||||||
|
|
||||||
|
1. On the left sidebar, select **Search or go to** and find your group.
|
||||||
|
1. Select **Build > Runners**.
|
||||||
|
1. To the right of the runner you want to edit, select **Edit** (**{pencil}**).
|
||||||
|
1. Set the runner to run tagged or untagged jobs:
|
||||||
|
- To run tagged jobs, in the **Tags** field, enter the job tags separated with a comma. For example, `macos`, `ruby`.
|
||||||
|
- To run untagged jobs, select the **Run untagged jobs** checkbox.
|
||||||
|
1. Select **Save changes**.
|
||||||
|
|
||||||
|
### For a project runner
|
||||||
|
|
||||||
|
Prerequisites:
|
||||||
|
|
||||||
|
- You must have the Owner role for the project.
|
||||||
|
|
||||||
|
To set a runner to run tagged jobs:
|
||||||
|
|
||||||
1. On the left sidebar, select **Search or go to** and find your project.
|
1. On the left sidebar, select **Search or go to** and find your project.
|
||||||
1. Select **Settings > CI/CD**.
|
1. Select **Settings > CI/CD**.
|
||||||
1. Expand **Runners**.
|
1. Expand **Runners**.
|
||||||
1. Find the runner you want to pick untagged jobs and make sure it's enabled.
|
1. To the right of the runner you want to edit, select **Edit** (**{pencil}**).
|
||||||
1. Select **Edit** (**{pencil}**).
|
1. Set the runner to run tagged or untagged jobs:
|
||||||
1. Select the **Run untagged jobs** checkbox.
|
- To run tagged jobs, in the **Tags** field, enter the job tags separated with a comma. For example, `macos`, `ruby`.
|
||||||
|
- To run untagged jobs, select the **Run untagged jobs** checkbox.
|
||||||
1. Select **Save changes**.
|
1. Select **Save changes**.
|
||||||
|
|
||||||
NOTE:
|
### How the runner uses tags
|
||||||
The runner tags list cannot be empty when it's not allowed to pick untagged jobs.
|
|
||||||
|
|
||||||
Below are some example scenarios of different variations.
|
#### Runner runs only tagged jobs
|
||||||
|
|
||||||
### Runner runs only tagged jobs
|
|
||||||
|
|
||||||
The following examples illustrate the potential impact of the runner being set
|
The following examples illustrate the potential impact of the runner being set
|
||||||
to run only tagged jobs.
|
to run only tagged jobs.
|
||||||
|
|
@ -229,7 +332,7 @@ Example 3:
|
||||||
1. The runner is configured to run only tagged jobs and has the `docker` tag.
|
1. The runner is configured to run only tagged jobs and has the `docker` tag.
|
||||||
1. A job that has no tags defined is executed and stuck.
|
1. A job that has no tags defined is executed and stuck.
|
||||||
|
|
||||||
### Runner is allowed to run untagged jobs
|
#### Runner is allowed to run untagged jobs
|
||||||
|
|
||||||
The following examples illustrate the potential impact of the runner being set
|
The following examples illustrate the potential impact of the runner being set
|
||||||
to run tagged and untagged jobs.
|
to run tagged and untagged jobs.
|
||||||
|
|
@ -246,7 +349,7 @@ Example 2:
|
||||||
1. A job that has no tags defined is executed and run.
|
1. A job that has no tags defined is executed and run.
|
||||||
1. A second job that has a `docker` tag defined is stuck.
|
1. A second job that has a `docker` tag defined is stuck.
|
||||||
|
|
||||||
### A runner and a job have multiple tags
|
#### A runner and a job have multiple tags
|
||||||
|
|
||||||
The selection logic that matches the job and runner is based on the list of `tags`
|
The selection logic that matches the job and runner is based on the list of `tags`
|
||||||
defined in the job.
|
defined in the job.
|
||||||
|
|
@ -273,7 +376,9 @@ Example 3:
|
||||||
|
|
||||||
You can use tags to run different jobs on different platforms. For
|
You can use tags to run different jobs on different platforms. For
|
||||||
example, if you have an OS X runner with tag `osx` and a Windows runner with tag
|
example, if you have an OS X runner with tag `osx` and a Windows runner with tag
|
||||||
`windows`, you can run a job on each platform:
|
`windows`, you can run a job on each platform.
|
||||||
|
|
||||||
|
Update the `tags` field in the `config.toml`:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
windows job:
|
windows job:
|
||||||
|
|
@ -295,7 +400,7 @@ osx job:
|
||||||
|
|
||||||
> Introduced in [GitLab 14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/35742).
|
> Introduced in [GitLab 14.1](https://gitlab.com/gitlab-org/gitlab/-/issues/35742).
|
||||||
|
|
||||||
You can use [CI/CD variables](../variables/index.md) with `tags` for dynamic runner selection:
|
In the `.gitlab-ci.yml` file, use [CI/CD variables](../variables/index.md) with `tags` for dynamic runner selection:
|
||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
variables:
|
variables:
|
||||||
|
|
@ -928,22 +1033,3 @@ No manual intervention should be required, and no running jobs should be affecte
|
||||||
|
|
||||||
If you need to manually update the runner authentication token, you can run a
|
If you need to manually update the runner authentication token, you can run a
|
||||||
command to [reset the token](https://docs.gitlab.com/runner/commands/#gitlab-runner-reset-token).
|
command to [reset the token](https://docs.gitlab.com/runner/commands/#gitlab-runner-reset-token).
|
||||||
|
|
||||||
### Automatically rotate runner authentication tokens
|
|
||||||
|
|
||||||
You can specify an interval for runner authentication tokens to rotate.
|
|
||||||
This rotation helps ensure the security of the tokens assigned to your runners.
|
|
||||||
|
|
||||||
Prerequisites:
|
|
||||||
|
|
||||||
- Ensure your runners are using [GitLab Runner 15.3 or later](https://docs.gitlab.com/runner/#gitlab-runner-versions).
|
|
||||||
|
|
||||||
To automatically rotate runner authentication tokens:
|
|
||||||
|
|
||||||
1. On the left sidebar, at the bottom, select **Admin Area**.
|
|
||||||
1. On the left sidebar, select **Settings > CI/CD**.
|
|
||||||
1. Expand **Continuous Integration and Deployment**
|
|
||||||
1. Set a **Runners expiration** time for runners, leave empty for no expiration.
|
|
||||||
1. Select **Save**.
|
|
||||||
|
|
||||||
Before the interval expires, runners automatically request a new runner authentication token.
|
|
||||||
|
|
|
||||||
|
|
@ -20,7 +20,7 @@ For more information about the cost factor applied to the machine type based on
|
||||||
The number of minutes you can use on these runners depends on the [maximum number of units of compute](../pipelines/cicd_minutes.md)
|
The number of minutes you can use on these runners depends on the [maximum number of units of compute](../pipelines/cicd_minutes.md)
|
||||||
in your [subscription plan](https://about.gitlab.com/pricing/).
|
in your [subscription plan](https://about.gitlab.com/pricing/).
|
||||||
|
|
||||||
[Untagged](../../ci/runners/configure_runners.md#use-tags-to-control-which-jobs-a-runner-can-run) jobs automatically run in containers
|
[Untagged](../../ci/runners/configure_runners.md#control-jobs-that-a-runner-can-run) jobs automatically run in containers
|
||||||
on the `small` Linux runners.
|
on the `small` Linux runners.
|
||||||
|
|
||||||
The objective is to make 90% of CI/CD jobs start executing in 120 seconds or less. The error rate should be less than 0.5%.
|
The objective is to make 90% of CI/CD jobs start executing in 120 seconds or less. The error rate should be less than 0.5%.
|
||||||
|
|
|
||||||
|
|
@ -4568,7 +4568,7 @@ In this example, only runners with *both* the `ruby` and `postgres` tags can run
|
||||||
|
|
||||||
**Related topics**:
|
**Related topics**:
|
||||||
|
|
||||||
- [Use tags to control which jobs a runner can run](../runners/configure_runners.md#use-tags-to-control-which-jobs-a-runner-can-run).
|
- [Use tags to control which jobs a runner can run](../runners/configure_runners.md#control-jobs-that-a-runner-can-run).
|
||||||
- [Select different runner tags for each parallel matrix job](../jobs/job_control.md#select-different-runner-tags-for-each-parallel-matrix-job).
|
- [Select different runner tags for each parallel matrix job](../jobs/job_control.md#select-different-runner-tags-for-each-parallel-matrix-job).
|
||||||
|
|
||||||
### `timeout`
|
### `timeout`
|
||||||
|
|
@ -4579,7 +4579,7 @@ Use `timeout` to configure a timeout for a specific job. If the job runs for lon
|
||||||
than the timeout, the job fails.
|
than the timeout, the job fails.
|
||||||
|
|
||||||
The job-level timeout can be longer than the [project-level timeout](../pipelines/settings.md#set-a-limit-for-how-long-jobs-can-run),
|
The job-level timeout can be longer than the [project-level timeout](../pipelines/settings.md#set-a-limit-for-how-long-jobs-can-run),
|
||||||
but can't be longer than the [runner's timeout](../runners/configure_runners.md#set-maximum-job-timeout-for-a-runner).
|
but can't be longer than the [runner's timeout](../runners/configure_runners.md#set-the-maximum-job-timeout).
|
||||||
|
|
||||||
**Keyword type**: Job keyword. You can use it only as part of a job or in the
|
**Keyword type**: Job keyword. You can use it only as part of a job or in the
|
||||||
[`default` section](#default).
|
[`default` section](#default).
|
||||||
|
|
|
||||||
|
|
@ -38,8 +38,8 @@ For more information on:
|
||||||
gitlab_rails['omniauth_block_auto_created_users'] = false
|
gitlab_rails['omniauth_block_auto_created_users'] = false
|
||||||
```
|
```
|
||||||
|
|
||||||
1. Optional. You can automatically link SAML users with existing GitLab users if their
|
1. Optional. You should automatically link a first-time SAML sign-in with existing GitLab users if their
|
||||||
email addresses match by adding the following setting in `/etc/gitlab/gitlab.rb`:
|
email addresses match. To do this, add the following setting in `/etc/gitlab/gitlab.rb`:
|
||||||
|
|
||||||
```ruby
|
```ruby
|
||||||
gitlab_rails['omniauth_auto_link_saml_user'] = true
|
gitlab_rails['omniauth_auto_link_saml_user'] = true
|
||||||
|
|
@ -728,6 +728,9 @@ On GitLab.com, Microsoft Azure/Entra ID attributes are introduced
|
||||||
[with a flag](../administration/feature_flags.md) named `saml_microsoft_attribute_names`.
|
[with a flag](../administration/feature_flags.md) named `saml_microsoft_attribute_names`.
|
||||||
On GitLab.com, this feature is unavailable but can be configured by GitLab.com administrators only.
|
On GitLab.com, this feature is unavailable but can be configured by GitLab.com administrators only.
|
||||||
|
|
||||||
|
NOTE:
|
||||||
|
The attributes are case-sensitive.
|
||||||
|
|
||||||
| Field | Supported default keys |
|
| Field | Supported default keys |
|
||||||
|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
|-----------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
||||||
| Email (required)| `email`, `mail`, `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`, `http://schemas.microsoft.com/ws/2008/06/identity/claims/emailaddress` |
|
| Email (required)| `email`, `mail`, `http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress`, `http://schemas.microsoft.com/ws/2008/06/identity/claims/emailaddress` |
|
||||||
|
|
|
||||||
|
|
@ -90,7 +90,7 @@ To create a project runner:
|
||||||
1. Expand the **Runners** section.
|
1. Expand the **Runners** section.
|
||||||
1. Select **New project runner**.
|
1. Select **New project runner**.
|
||||||
1. Select your operating system.
|
1. Select your operating system.
|
||||||
1. In the **Tags** section, select the **Run untagged** checkbox. [Tags](../../ci/runners/configure_runners.md#use-tags-to-control-which-jobs-a-runner-can-run) specify which jobs
|
1. In the **Tags** section, select the **Run untagged** checkbox. [Tags](../../ci/runners/configure_runners.md#control-jobs-that-a-runner-can-run) specify which jobs
|
||||||
the runner can run and are optional.
|
the runner can run and are optional.
|
||||||
1. Select **Create runner**.
|
1. Select **Create runner**.
|
||||||
1. Follow the on-screen instructions to register the runner from the command line. When prompted:
|
1. Follow the on-screen instructions to register the runner from the command line. When prompted:
|
||||||
|
|
|
||||||
|
|
@ -541,6 +541,10 @@ by this issue.
|
||||||
[throw errors on startup](../../install/docker.md#threaderror-cant-create-thread-operation-not-permitted).
|
[throw errors on startup](../../install/docker.md#threaderror-cant-create-thread-operation-not-permitted).
|
||||||
- Starting with 16.0, GitLab self-managed installations now have two database connections by default, instead of one. This change doubles the number of PostgreSQL connections. It makes self-managed versions of GitLab behave similarly to GitLab.com, and is a step toward enabling a separate database for CI features for self-managed versions of GitLab. Before upgrading to 16.0, determine if you need to [increase max connections for PostgreSQL](https://docs.gitlab.com/omnibus/settings/database.html#configuring-multiple-database-connections).
|
- Starting with 16.0, GitLab self-managed installations now have two database connections by default, instead of one. This change doubles the number of PostgreSQL connections. It makes self-managed versions of GitLab behave similarly to GitLab.com, and is a step toward enabling a separate database for CI features for self-managed versions of GitLab. Before upgrading to 16.0, determine if you need to [increase max connections for PostgreSQL](https://docs.gitlab.com/omnibus/settings/database.html#configuring-multiple-database-connections).
|
||||||
- This change applies to installation methods with Linux packages (Omnibus), GitLab Helm chart, GitLab Operator, GitLab Docker images, and self-compiled installations.
|
- This change applies to installation methods with Linux packages (Omnibus), GitLab Helm chart, GitLab Operator, GitLab Docker images, and self-compiled installations.
|
||||||
|
- The second database connection can be disabled:
|
||||||
|
- [Linux package and Docker installations](https://docs.gitlab.com/omnibus/settings/database.html#configuring-multiple-database-connections).
|
||||||
|
- [Helm chart and GitLab Operator installations](https://docs.gitlab.com/charts/charts/globals.html#configure-multiple-database-connections).
|
||||||
|
- [Self-compiled installations](../../install/installation.md#configure-gitlab-db-settings).
|
||||||
- Container registry using Azure storage might be empty with zero tags. You can fix this by following the [breaking change instructions](../deprecations.md#azure-storage-driver-defaults-to-the-correct-root-prefix).
|
- Container registry using Azure storage might be empty with zero tags. You can fix this by following the [breaking change instructions](../deprecations.md#azure-storage-driver-defaults-to-the-correct-root-prefix).
|
||||||
|
|
||||||
### Linux package installations
|
### Linux package installations
|
||||||
|
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue