diff --git a/.gitlab/merge_request_templates/Documentation.md b/.gitlab/merge_request_templates/Documentation.md index 6617184cad7..83c2c6fbd25 100644 --- a/.gitlab/merge_request_templates/Documentation.md +++ b/.gitlab/merge_request_templates/Documentation.md @@ -13,9 +13,9 @@ - [Documentation process](https://docs.gitlab.com/ee/development/documentation/workflow.html). - [Documentation guidelines](https://docs.gitlab.com/ee/development/documentation/). - [Style Guide](https://docs.gitlab.com/ee/development/documentation/styleguide/). -- [ ] If you're adding or changing the main heading of the page (H1), ensure that the [product tier badge](https://docs.gitlab.com/ee/development/documentation/styleguide/index.html#product-tier-badges) is added. +- [ ] If you're adding a new page, add the [product tier badge](https://docs.gitlab.com/ee/development/documentation/styleguide/index.html#product-tier-badges) under the H1 topic title. - [ ] If you are a GitLab team member, [request a review](https://docs.gitlab.com/ee/development/code_review.html#dogfooding-the-reviewers-feature) based on: - - The documentation page's [metadata](https://docs.gitlab.com/ee/development/documentation/#metadata). + - The documentation page's [metadata](https://docs.gitlab.com/ee/development/documentation/metadata.html). - The [associated Technical Writer](https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments). If you are a GitLab team member and only adding documentation, do not add any of the following labels: @@ -36,9 +36,9 @@ If you aren't sure which tech writer to ask, use [roulette](https://gitlab-org.g - [ ] If the content requires it, ensure the information is reviewed by a subject matter expert. - Technical writer review items: - [ ] Ensure docs metadata is present and up-to-date. - - [ ] Ensure the appropriate [labels](https://about.gitlab.com/handbook/product/ux/technical-writing/workflow/#labels) are added to this MR. + - [ ] Ensure the appropriate [labels](https://handbook.gitlab.com/handbook/product/ux/technical-writing/workflow/#labels) are added to this MR. - [ ] Ensure a release milestone is set. - - If relevant to this MR, ensure [content topic type](https://docs.gitlab.com/ee/development/documentation/structure.html) principles are in use, including: + - If relevant to this MR, ensure [content topic type](https://docs.gitlab.com/ee/development/documentation/topic_types/) principles are in use, including: - [ ] The headings should be something you'd do a Google search for. Instead of `Default behavior`, say something like `Default behavior when you close an issue`. - [ ] The headings (other than the page title) should be active. Instead of `Configuring GDK`, say something like `Configure GDK`. - [ ] Any task steps should be written as a numbered list. diff --git a/.rubocop_todo/capybara/testid_finders.yml b/.rubocop_todo/capybara/testid_finders.yml index 0e02f3e3219..e41264d37af 100644 --- a/.rubocop_todo/capybara/testid_finders.yml +++ b/.rubocop_todo/capybara/testid_finders.yml @@ -1,20 +1,6 @@ --- Capybara/TestidFinders: Exclude: - - 'spec/features/issues/issue_sidebar_spec.rb' - - 'spec/features/issues/issue_state_spec.rb' - - 'spec/features/issues/user_creates_issue_spec.rb' - - 'spec/features/issues/user_edits_issue_spec.rb' - - 'spec/features/issues/user_resets_their_incoming_email_token_spec.rb' - - 'spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb' - - 'spec/features/issues/user_toggles_subscription_spec.rb' - - 'spec/features/labels_hierarchy_spec.rb' - - 'spec/features/merge_request/merge_request_discussion_lock_spec.rb' - - 'spec/features/merge_request/user_accepts_merge_request_spec.rb' - - 'spec/features/merge_request/user_assigns_themselves_spec.rb' - - 'spec/features/merge_request/user_comments_on_diff_spec.rb' - - 'spec/features/merge_request/user_comments_on_whitespace_hidden_diff_spec.rb' - - 'spec/features/merge_request/user_creates_mr_spec.rb' - 'spec/features/merge_request/user_interacts_with_batched_mr_diffs_spec.rb' - 'spec/features/merge_request/user_sees_pipelines_spec.rb' - 'spec/features/merge_request/user_sees_suggest_pipeline_spec.rb' diff --git a/.rubocop_todo/fips/md5.yml b/.rubocop_todo/fips/md5.yml index 4a1994635b7..af4ceb50038 100644 --- a/.rubocop_todo/fips/md5.yml +++ b/.rubocop_todo/fips/md5.yml @@ -3,7 +3,6 @@ Fips/MD5: Exclude: - 'app/experiments/application_experiment.rb' - 'app/models/concerns/checksummable.rb' - - 'app/services/gravatar_service.rb' - 'app/services/packages/debian/generate_distribution_service.rb' - 'app/services/packages/go/create_package_service.rb' - 'app/services/packages/maven/metadata/append_package_file_service.rb' @@ -16,4 +15,3 @@ Fips/MD5: - 'spec/lib/gitlab/ci/trace/archive_spec.rb' - 'spec/lib/gitlab/ci/trace/remote_checksum_spec.rb' - 'spec/models/concerns/checksummable_spec.rb' - - 'spec/services/gravatar_service_spec.rb' diff --git a/app/assets/javascripts/accordion/index.js b/app/assets/javascripts/accordion/index.js new file mode 100644 index 00000000000..44296d44465 --- /dev/null +++ b/app/assets/javascripts/accordion/index.js @@ -0,0 +1,30 @@ +import { spriteIcon } from '~/lib/utils/common_utils'; + +/** + * This adds interactivity to accordions created via HAML + */ +export default (el) => { + if (!el) return; + + const accordionTrigger = el.querySelector('button'); + const accordionItem = el.querySelector('.accordion-item'); + const iconClass = 's16 gl-icon gl-button-icon js-chevron-icon'; + const chevronRight = spriteIcon('chevron-right', iconClass); + const chevronDown = spriteIcon('chevron-down', iconClass); + + accordionTrigger.addEventListener('click', () => { + const chevronIcon = el.querySelector('.js-chevron-icon'); + accordionItem.classList.toggle('show'); + + if (accordionItem.classList.contains('show')) { + // eslint-disable-next-line no-unsanitized/property + chevronIcon.outerHTML = chevronDown; + accordionTrigger.setAttribute('aria-expanded', 'true'); + return; + } + + // eslint-disable-next-line no-unsanitized/property + chevronIcon.outerHTML = chevronRight; + accordionTrigger.setAttribute('aria-expanded', 'false'); + }); +}; diff --git a/app/assets/javascripts/achievements/components/achievements_app.vue b/app/assets/javascripts/achievements/components/achievements_app.vue index 5f40231856f..1f64c5060d3 100644 --- a/app/assets/javascripts/achievements/components/achievements_app.vue +++ b/app/assets/javascripts/achievements/components/achievements_app.vue @@ -1,31 +1,105 @@ diff --git a/app/assets/javascripts/achievements/components/graphql/get_group_achievements.query.graphql b/app/assets/javascripts/achievements/components/graphql/get_group_achievements.query.graphql new file mode 100644 index 00000000000..8d1bf0ec677 --- /dev/null +++ b/app/assets/javascripts/achievements/components/graphql/get_group_achievements.query.graphql @@ -0,0 +1,23 @@ +#import "~/graphql_shared/fragments/page_info.fragment.graphql" + +query getGroupAchievements( + $groupFullPath: ID! + $first: Int + $last: Int + $before: String + $after: String +) { + group(fullPath: $groupFullPath) { + id + achievements(first: $first, last: $last, after: $after, before: $before) { + nodes { + id + name + description + } + pageInfo { + ...PageInfo + } + } + } +} diff --git a/app/assets/javascripts/issues/show/components/header_actions.vue b/app/assets/javascripts/issues/show/components/header_actions.vue index 4d8b4c162da..91332547e84 100644 --- a/app/assets/javascripts/issues/show/components/header_actions.vue +++ b/app/assets/javascripts/issues/show/components/header_actions.vue @@ -325,7 +325,7 @@ export default { :auto-close="false" data-testid="mobile-dropdown" :loading="isToggleStateButtonLoading" - placement="right" + placement="left" > - - @@ -356,6 +352,9 @@ export default { + {{ copyMailAddressText }} { return new Vue({ el, + name: 'AchievementsAppRoot', router, apolloProvider, provide: convertObjectPropsToCamelCase(provide), diff --git a/app/assets/javascripts/projects/new/index.js b/app/assets/javascripts/projects/new/index.js index a5a833dc73b..1560e47c33e 100644 --- a/app/assets/javascripts/projects/new/index.js +++ b/app/assets/javascripts/projects/new/index.js @@ -2,6 +2,7 @@ import Vue from 'vue'; import VueApollo from 'vue-apollo'; import createDefaultClient from '~/lib/graphql'; import { parseBoolean } from '~/lib/utils/common_utils'; +import initAccordion from '~/accordion'; import NewProjectCreationApp from './components/app.vue'; import NewProjectUrlSelect from './components/new_project_url_select.vue'; import DeploymentTargetSelect from './components/deployment_target_select.vue'; @@ -89,3 +90,5 @@ export function initDeploymentTargetSelect() { render: (createElement) => createElement(DeploymentTargetSelect), }); } + +initAccordion(document.getElementById('js-experimental-setting-accordion')); diff --git a/app/assets/javascripts/work_items/components/shared/work_item_sidebar_dropdown_widget_with_edit.vue b/app/assets/javascripts/work_items/components/shared/work_item_sidebar_dropdown_widget_with_edit.vue index 1fd0f056431..1d93af8c138 100644 --- a/app/assets/javascripts/work_items/components/shared/work_item_sidebar_dropdown_widget_with_edit.vue +++ b/app/assets/javascripts/work_items/components/shared/work_item_sidebar_dropdown_widget_with_edit.vue @@ -164,7 +164,7 @@ export default { data-testid="edit-button" category="tertiary" size="small" - class="gl-ml-auto gl-mr-2" + class="gl-ml-auto" :disabled="updateInProgress" @click="isEditing = true" >{{ $options.i18n.editButtonLabel }}{{ $options.i18n.applyButtonLabel }}{{ __('Edit') }}{{ __('Apply') }}{{ __('Edit') }}{{ __('Apply') }} { order(semver_major: :desc, semver_minor: :desc, semver_patch: :desc) } + scope :order_by_semantic_version_asc, -> { order(semver_major: :asc, semver_minor: :asc, semver_patch: :asc) } private def semver_format diff --git a/app/models/group.rb b/app/models/group.rb index a43815781f2..de0b5ee71be 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -854,7 +854,7 @@ class Group < Namespace end def crm_enabled? - crm_settings&.enabled? + crm_settings.nil? || crm_settings.enabled? end def shared_with_group_links_visible_to_user(user) diff --git a/app/models/group/crm_settings.rb b/app/models/group/crm_settings.rb index 30fbe6ae07f..f8dfbd8a305 100644 --- a/app/models/group/crm_settings.rb +++ b/app/models/group/crm_settings.rb @@ -1,10 +1,14 @@ # frozen_string_literal: true class Group::CrmSettings < ApplicationRecord + include SafelyChangeColumnDefault + self.primary_key = :group_id self.table_name = 'group_crm_settings' belongs_to :group, -> { where(type: Group.sti_name) }, foreign_key: 'group_id' validates :group, presence: true + + columns_changing_default :enabled end diff --git a/app/models/project.rb b/app/models/project.rb index 2f1fc9ae5a9..f8924e3c51e 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -2401,12 +2401,8 @@ class Project < ApplicationRecord end def has_ci_config_file? - if ::Feature.enabled?(:ci_refactor_has_ci_config_file, self, type: :gitlab_com_derisk) - strong_memoize(:has_ci_config_file) do - ci_config_for('HEAD').present? - end - else - repository.gitlab_ci_yml.present? + strong_memoize(:has_ci_config_file) do + ci_config_for('HEAD').present? end end diff --git a/app/models/repository.rb b/app/models/repository.rb index cd3c4f7500f..6045b899743 100644 --- a/app/models/repository.rb +++ b/app/models/repository.rb @@ -675,7 +675,6 @@ class Repository cache_method :gitignore # Deprecated, use `project.has_ci_config_file?` instead. - # Can be removed with the FF `ci_refactor_has_ci_config_file`. def gitlab_ci_yml file_on_head(:gitlab_ci) end @@ -1296,8 +1295,7 @@ class Repository end def blank_ref - return Gitlab::Git::SHA1_BLANK_SHA unless exists? && - Feature.enabled?(:determine_blank_ref_based_on_gitaly_object_format, project, type: :gitlab_com_derisk) + return Gitlab::Git::SHA1_BLANK_SHA unless exists? case object_format when FORMAT_SHA1 diff --git a/app/services/gravatar_service.rb b/app/services/gravatar_service.rb index 9d5990f2c8a..c9c6fae5cc6 100644 --- a/app/services/gravatar_service.rb +++ b/app/services/gravatar_service.rb @@ -2,13 +2,12 @@ class GravatarService def execute(email, size = nil, scale = 2, username: nil) - return if Gitlab::FIPS.enabled? return unless Gitlab::CurrentSettings.gravatar_enabled? identifier = email.presence || username.presence return unless identifier - hash = Digest::MD5.hexdigest(identifier.strip.downcase) + hash = Digest::SHA256.hexdigest(identifier.strip.downcase) size = Groups::GroupMembersHelper::AVATAR_SIZE unless size && size > 0 sprintf gravatar_url, diff --git a/app/views/projects/_new_project_fields.html.haml b/app/views/projects/_new_project_fields.html.haml index 58ae445fc02..302e7e9bcd5 100644 --- a/app/views/projects/_new_project_fields.html.haml +++ b/app/views/projects/_new_project_fields.html.haml @@ -93,12 +93,15 @@ = link_to _('Learn more.'), help_page_path('user/application_security/sast/index'), target: '_blank', rel: 'noopener noreferrer', data: { track_action: 'followed' } - if display_sha256_repository - .form-group - = render Pajamas::CheckboxTagComponent.new(name: 'project[use_sha256_repository]') do |c| - - c.with_label do - = s_('ProjectsNew|Use SHA-256 as the repository hashing algorithm') - - c.with_help_text do - = s_('ProjectsNew|Default hashing algorithm is SHA-1.') + #js-experimental-setting-accordion.form-group.gl-mb-6 + = render Pajamas::AccordionItemComponent.new(title: s_("ProjectsNew|Experimental settings"), state: :closed) do + = render Pajamas::CheckboxTagComponent.new(name: 'project[use_sha256_repository]') do |c| + - c.with_label do + = s_('ProjectsNew|Use SHA-256 for repository hashing algorithm') + = render_if_exists 'shared/experimental_badge_tag' + - c.with_help_text do + = s_("ProjectsNew|Might break existing functionality with other repositories or APIs. It's not possible to change SHA-256 repositories back to the default SHA-1 hashing algorithm.") + -# this partial is from JiHu, see details in https://jihulab.com/gitlab-cn/gitlab/-/merge_requests/675 = render_if_exists 'shared/other_project_options', f: f, visibility_level: visibility_level, track_label: track_label diff --git a/app/views/projects/commits/_commit.html.haml b/app/views/projects/commits/_commit.html.haml index 9f0c910c1c0..db70d596679 100644 --- a/app/views/projects/commits/_commit.html.haml +++ b/app/views/projects/commits/_commit.html.haml @@ -20,6 +20,7 @@ - link_data_attrs = local_assigns.fetch(:link_data_attrs, {}) - link = commit_path(project, commit, merge_request: merge_request) - show_project_name = local_assigns.fetch(:show_project_name, false) +- toggle_commit_message = _("Toggle commit description") %li{ class: ["commit flex-row", ("js-toggle-container" if collapsible)], id: "commit-#{commit.short_id}" } .avatar-cell.d-none.d-sm-block @@ -36,7 +37,7 @@ = commit.short_id - if commit.description? && collapsible = render Pajamas::ButtonComponent.new(icon: 'ellipsis_h', - button_options: { class: 'button-ellipsis-horizontal text-expander js-toggle-button', data: { toggle: 'tooltip', container: 'body', collapse_title: _("Toggle commit description"), expand_title: _("Toggle commit description") }, :title => _("Toggle commit description"), aria: { label: _("Toggle commit description") }}) + button_options: { class: 'button-ellipsis-horizontal text-expander js-toggle-button', data: { toggle: 'tooltip', container: 'body', collapse_title: toggle_commit_message, expand_title: toggle_commit_message }, title: toggle_commit_message, aria: { label: toggle_commit_message }}) .committer - commit_author_link = commit_author_link(commit, avatar: false, size: 24) diff --git a/app/views/shared/runners/_shared_runners_description.html.haml b/app/views/shared/runners/_shared_runners_description.html.haml index aab78fe35d1..59876a9ead4 100644 --- a/app/views/shared/runners/_shared_runners_description.html.haml +++ b/app/views/shared/runners/_shared_runners_description.html.haml @@ -1,4 +1,4 @@ -- shared_link_start = ''.html_safe % { url: help_page_path('ci/runners/runners_scope', anchor: 'shared-runners') } +- shared_link_start = ''.html_safe % { url: help_page_path('ci/runners/runners_scope', anchor: 'instance-runners') } %h4 = s_('Runners|Instance runners') diff --git a/config/feature_flags/gitlab_com_derisk/ci_refactor_has_ci_config_file.yml b/config/feature_flags/gitlab_com_derisk/ci_refactor_has_ci_config_file.yml deleted file mode 100644 index b083a7873f1..00000000000 --- a/config/feature_flags/gitlab_com_derisk/ci_refactor_has_ci_config_file.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: ci_refactor_has_ci_config_file -feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/26169 -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/141990 -rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17406 -milestone: '16.9' -group: group::pipeline authoring -type: gitlab_com_derisk -default_enabled: false diff --git a/config/feature_flags/gitlab_com_derisk/determine_blank_ref_based_on_gitaly_object_format.yml b/config/feature_flags/gitlab_com_derisk/determine_blank_ref_based_on_gitaly_object_format.yml deleted file mode 100644 index 35443130efc..00000000000 --- a/config/feature_flags/gitlab_com_derisk/determine_blank_ref_based_on_gitaly_object_format.yml +++ /dev/null @@ -1,9 +0,0 @@ ---- -name: determine_blank_ref_based_on_gitaly_object_format -feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/434693 -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/140395 -rollout_issue_url: https://gitlab.com/gitlab-com/gl-infra/production/-/issues/17317 -milestone: '16.8' -group: group::source code -type: gitlab_com_derisk -default_enabled: false diff --git a/config/gitlab_loose_foreign_keys.yml b/config/gitlab_loose_foreign_keys.yml index b59a97d0906..c491d45a5f3 100644 --- a/config/gitlab_loose_foreign_keys.yml +++ b/config/gitlab_loose_foreign_keys.yml @@ -334,6 +334,10 @@ projects_visits: - table: users column: user_id on_delete: async_delete +push_rules: + - table: organizations + column: organization_id + on_delete: async_delete requirements_management_test_reports: - table: ci_builds column: build_id diff --git a/config/sidekiq_queues.yml b/config/sidekiq_queues.yml index a7182e33418..ddb3830d37b 100644 --- a/config/sidekiq_queues.yml +++ b/config/sidekiq_queues.yml @@ -753,6 +753,8 @@ - 1 - - vulnerabilities_mark_dropped_as_resolved - 1 +- - vulnerabilities_process_transfer_events + - 1 - - vulnerabilities_remove_all_vulnerabilities - 1 - - vulnerabilities_statistics_adjustment diff --git a/data/deprecations/16-9-markdown-anchors.yml b/data/deprecations/16-9-markdown-anchors.yml new file mode 100644 index 00000000000..aa673a5302a --- /dev/null +++ b/data/deprecations/16-9-markdown-anchors.yml @@ -0,0 +1,26 @@ +- title: "Autogenerated Markdown anchor links with dash (`-`) characters" + # The milestones for the deprecation announcement, and the removal. + removal_milestone: "17.0" + announcement_milestone: "16.9" + # Change breaking_change to false if needed. + breaking_change: true + # The stage and GitLab username of the person reporting the change, + # and a link to the deprecation issue + reporter: digitalmoksha + stage: plan + issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/440733 + impact: low # Can be one of: [critical, high, medium, low] + scope: project # Can be one or a combination of: [instance, group, project] + resolution_role: Developer # Can be one of: [Admin, Owner, Maintainer, Developer] + manual_task: true # Can be true or false. Use this to denote whether a resolution action must be performed manually (true), or if it can be automated by using the API or other automation (false). + body: | # (required) Don't change this line. + GitLab automatically creates anchor links for all headings, so you can link to + a specific place in a Markdown document or wiki page. But in some edge cases, + the autogenerated anchor is created with fewer dash (`-`) characters than many users expect. + For example, with a heading with `## Step - 1`, most other Markdown tools and linters would expect `#step---1`. + But GitLab generates an anchor of `#step-1`, with consecutive dashes compressed down to one. + + In GitLab 17.0, we will align our autogenerated anchors to the industry standard by no longer stripping consecutive dashes. + If you have Markdown documents and link to headings that could have multiple dashes in 17.0, + you should update the heading to avoid this edge case. With the example above, you + can change `## Step - 1` to `## Step 1` to ensure in-page links continue to work. diff --git a/db/docs/cluster_agent_tokens.yml b/db/docs/cluster_agent_tokens.yml index 36e843406b0..a4771e445c2 100644 --- a/db/docs/cluster_agent_tokens.yml +++ b/db/docs/cluster_agent_tokens.yml @@ -7,4 +7,19 @@ feature_categories: description: Tokens used by cluster agents to connect to GitLab introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33228 milestone: '13.3' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: agent_id + table: cluster_agents + sharding_key: project_id + belongs_to: agent diff --git a/db/docs/csv_issue_imports.yml b/db/docs/csv_issue_imports.yml index c5bdd72e6e4..31f10fb2773 100644 --- a/db/docs/csv_issue_imports.yml +++ b/db/docs/csv_issue_imports.yml @@ -7,4 +7,12 @@ feature_categories: description: Used to report the unique user usage of the CSV Issue Import feature introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44742 milestone: '13.6' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +sharding_key: + project_id: projects diff --git a/db/docs/deployment_clusters.yml b/db/docs/deployment_clusters.yml index 011c5252593..dc79d50d718 100644 --- a/db/docs/deployment_clusters.yml +++ b/db/docs/deployment_clusters.yml @@ -7,4 +7,19 @@ feature_categories: description: "(Deprecated) Join table between `deployments` and `clusters`" introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/24235 milestone: '12.8' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: deployment_id + table: deployments + sharding_key: project_id + belongs_to: deployment diff --git a/db/docs/group_import_states.yml b/db/docs/group_import_states.yml index 1a47b0e0af4..b7f59c1c280 100644 --- a/db/docs/group_import_states.yml +++ b/db/docs/group_import_states.yml @@ -4,7 +4,10 @@ classes: - GroupImportState feature_categories: - importers -description: Used to store and track the group import status when using the Import/Export feature +description: Used to store and track the group import status when using the Import/Export + feature introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/29588 milestone: '13.0' gitlab_schema: gitlab_main_cell +sharding_key: + group_id: namespaces diff --git a/db/docs/p_ci_job_artifacts.yml b/db/docs/p_ci_job_artifacts.yml new file mode 100644 index 00000000000..5bb3dc580c7 --- /dev/null +++ b/db/docs/p_ci_job_artifacts.yml @@ -0,0 +1,10 @@ +--- +table_name: p_ci_job_artifacts +classes: +- Ci::JobArtifact +feature_categories: +- continuous_integration +description: Routing table for ci_job_artifacts +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/143039 +milestone: '16.10' +gitlab_schema: gitlab_ci diff --git a/db/docs/project_export_jobs.yml b/db/docs/project_export_jobs.yml index 2eb6aa51202..a2ab82eee48 100644 --- a/db/docs/project_export_jobs.yml +++ b/db/docs/project_export_jobs.yml @@ -7,4 +7,12 @@ feature_categories: description: Used to track and control project export status introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23664 milestone: '12.9' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +sharding_key: + project_id: projects diff --git a/db/docs/project_mirror_data.yml b/db/docs/project_mirror_data.yml index 5ac43215b26..f71b7a93026 100644 --- a/db/docs/project_mirror_data.yml +++ b/db/docs/project_mirror_data.yml @@ -4,7 +4,16 @@ classes: - ProjectImportState feature_categories: - importers -description: Used to store and track the project import status when using the Import/Export feature +description: Used to store and track the project import status when using the Import/Export + feature introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/0ca479d1ce0eadfcdc0e29d0e18136f5790d5b2f milestone: '9.3' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +sharding_key: + project_id: projects diff --git a/db/docs/vulnerability_external_issue_links.yml b/db/docs/vulnerability_external_issue_links.yml index 4c2dcd8d8d6..12ac652b4c8 100644 --- a/db/docs/vulnerability_external_issue_links.yml +++ b/db/docs/vulnerability_external_issue_links.yml @@ -4,7 +4,23 @@ classes: - Vulnerabilities::ExternalIssueLink feature_categories: - vulnerability_management -description: Stores information about connections between external issue trackers and vulnerabilities +description: Stores information about connections between external issue trackers + and vulnerabilities introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48465 milestone: '13.7' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: vulnerability_id + table: vulnerabilities + sharding_key: project_id + belongs_to: vulnerability diff --git a/db/docs/vulnerability_finding_evidences.yml b/db/docs/vulnerability_finding_evidences.yml index 35ecfd57fe3..4bb6bec600d 100644 --- a/db/docs/vulnerability_finding_evidences.yml +++ b/db/docs/vulnerability_finding_evidences.yml @@ -7,4 +7,19 @@ feature_categories: description: Stores evidence used to identify presence of a vulnerability introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56790 milestone: '13.11' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: vulnerability_occurrence_id + table: vulnerability_occurrences + sharding_key: project_id + belongs_to: finding diff --git a/db/docs/vulnerability_finding_links.yml b/db/docs/vulnerability_finding_links.yml index 267355dd873..f848d17addd 100644 --- a/db/docs/vulnerability_finding_links.yml +++ b/db/docs/vulnerability_finding_links.yml @@ -7,4 +7,19 @@ feature_categories: description: Stores URLs relevant to the vulnerability findings introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46555 milestone: '13.6' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: vulnerability_occurrence_id + table: vulnerability_occurrences + sharding_key: project_id + belongs_to: finding diff --git a/db/docs/vulnerability_finding_signatures.yml b/db/docs/vulnerability_finding_signatures.yml index 9a1e59697cf..3e4541502f8 100644 --- a/db/docs/vulnerability_finding_signatures.yml +++ b/db/docs/vulnerability_finding_signatures.yml @@ -4,7 +4,23 @@ classes: - Vulnerabilities::FindingSignature feature_categories: - vulnerability_management -description: Stores signatures of vulnerability locations which are used to improve tracking +description: Stores signatures of vulnerability locations which are used to improve + tracking introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57840 milestone: '13.11' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: finding_id + table: vulnerability_occurrences + sharding_key: project_id + belongs_to: finding diff --git a/db/docs/vulnerability_flags.yml b/db/docs/vulnerability_flags.yml index fabc8a48200..9b0071bf96b 100644 --- a/db/docs/vulnerability_flags.yml +++ b/db/docs/vulnerability_flags.yml @@ -4,7 +4,23 @@ classes: - Vulnerabilities::Flag feature_categories: - vulnerability_management -description: Stores additional information for vulnerabilities, for example if a vulnerability is identified as a false positive +description: Stores additional information for vulnerabilities, for example if a vulnerability + is identified as a false positive introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/65573 milestone: '14.1' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: vulnerability_occurrence_id + table: vulnerability_occurrences + sharding_key: project_id + belongs_to: finding diff --git a/db/docs/vulnerability_issue_links.yml b/db/docs/vulnerability_issue_links.yml index 4bbc587707e..0a3441e7fae 100644 --- a/db/docs/vulnerability_issue_links.yml +++ b/db/docs/vulnerability_issue_links.yml @@ -7,4 +7,19 @@ feature_categories: description: Join table between Vulnerabilities and Issues introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/19852 milestone: '12.5' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: vulnerability_id + table: vulnerabilities + sharding_key: project_id + belongs_to: vulnerability diff --git a/db/docs/vulnerability_merge_request_links.yml b/db/docs/vulnerability_merge_request_links.yml index 8cc71b2a76a..ce1e9a7a27f 100644 --- a/db/docs/vulnerability_merge_request_links.yml +++ b/db/docs/vulnerability_merge_request_links.yml @@ -7,4 +7,19 @@ feature_categories: description: Join table between Vulnerabilities and Merge Requests introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/92096 milestone: '15.2' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: vulnerability_id + table: vulnerabilities + sharding_key: project_id + belongs_to: vulnerability diff --git a/db/docs/vulnerability_occurrence_identifiers.yml b/db/docs/vulnerability_occurrence_identifiers.yml index cd2236631aa..1fe7cd1585f 100644 --- a/db/docs/vulnerability_occurrence_identifiers.yml +++ b/db/docs/vulnerability_occurrence_identifiers.yml @@ -7,4 +7,19 @@ feature_categories: description: Join table between Findings and Identifiers introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6896 milestone: '11.4' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: occurrence_id + table: vulnerability_occurrences + sharding_key: project_id + belongs_to: finding diff --git a/db/docs/vulnerability_occurrence_pipelines.yml b/db/docs/vulnerability_occurrence_pipelines.yml index 542d4026824..6039fac8b15 100644 --- a/db/docs/vulnerability_occurrence_pipelines.yml +++ b/db/docs/vulnerability_occurrence_pipelines.yml @@ -7,4 +7,19 @@ feature_categories: description: Join table between Findings and Pipelines introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/7578 milestone: '11.5' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: occurrence_id + table: vulnerability_occurrences + sharding_key: project_id + belongs_to: finding diff --git a/db/docs/vulnerability_state_transitions.yml b/db/docs/vulnerability_state_transitions.yml index 1a669b1527d..0e028ee6a57 100644 --- a/db/docs/vulnerability_state_transitions.yml +++ b/db/docs/vulnerability_state_transitions.yml @@ -7,4 +7,19 @@ feature_categories: description: Stores state transitions of a Vulnerability introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/87957 milestone: '15.1' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: vulnerability_id + table: vulnerabilities + sharding_key: project_id + belongs_to: vulnerability diff --git a/db/docs/vulnerability_user_mentions.yml b/db/docs/vulnerability_user_mentions.yml index 9a95c834726..296245fb2cc 100644 --- a/db/docs/vulnerability_user_mentions.yml +++ b/db/docs/vulnerability_user_mentions.yml @@ -7,4 +7,19 @@ feature_categories: description: Stores notes for a given vulnerability introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27515 milestone: '13.0' -gitlab_schema: gitlab_main +gitlab_schema: gitlab_main_cell +allow_cross_joins: +- gitlab_main_clusterwide +allow_cross_transactions: +- gitlab_main_clusterwide +allow_cross_foreign_keys: +- gitlab_main_clusterwide +desired_sharding_key: + project_id: + references: projects + backfill_via: + parent: + foreign_key: vulnerability_id + table: vulnerabilities + sharding_key: project_id + belongs_to: vulnerability diff --git a/db/migrate/20240126095808_add_subrelation_column_to_bulk_import_failures.rb b/db/migrate/20240126095808_add_subrelation_column_to_bulk_import_failures.rb new file mode 100644 index 00000000000..c045b7be519 --- /dev/null +++ b/db/migrate/20240126095808_add_subrelation_column_to_bulk_import_failures.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddSubrelationColumnToBulkImportFailures < Gitlab::Database::Migration[2.2] + milestone '16.9' + + # rubocop:disable Migration/AddLimitToTextColumns -- added in a separate migration + def change + add_column :bulk_import_failures, :subrelation, :text + end + # rubocop:enable Migration/AddLimitToTextColumns +end diff --git a/db/migrate/20240126100509_add_text_limit_to_bulk_import_failures_subrelation_column.rb b/db/migrate/20240126100509_add_text_limit_to_bulk_import_failures_subrelation_column.rb new file mode 100644 index 00000000000..959ec91b263 --- /dev/null +++ b/db/migrate/20240126100509_add_text_limit_to_bulk_import_failures_subrelation_column.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class AddTextLimitToBulkImportFailuresSubrelationColumn < Gitlab::Database::Migration[2.2] + milestone '16.9' + disable_ddl_transaction! + + def up + add_text_limit :bulk_import_failures, :subrelation, 255 + end + + def down + remove_text_limit :bulk_import_failures, :subrelation + end +end diff --git a/db/migrate/20240201141351_add_organization_id_to_push_rules.rb b/db/migrate/20240201141351_add_organization_id_to_push_rules.rb new file mode 100644 index 00000000000..033320d399b --- /dev/null +++ b/db/migrate/20240201141351_add_organization_id_to_push_rules.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class AddOrganizationIdToPushRules < Gitlab::Database::Migration[2.2] + milestone '16.9' + + INDEX_NAME = 'index_push_rules_on_organization_id' + + disable_ddl_transaction! + + def up + add_column :push_rules, :organization_id, :bigint, null: true + + add_concurrent_index :push_rules, :organization_id, name: INDEX_NAME + end + + def down + remove_concurrent_index_by_name :push_rules, INDEX_NAME + + remove_column :push_rules, :organization_id + end +end diff --git a/db/migrate/20240201141705_assign_default_organization_id_to_push_rules.rb b/db/migrate/20240201141705_assign_default_organization_id_to_push_rules.rb new file mode 100644 index 00000000000..228d348e9ab --- /dev/null +++ b/db/migrate/20240201141705_assign_default_organization_id_to_push_rules.rb @@ -0,0 +1,18 @@ +# frozen_string_literal: true + +class AssignDefaultOrganizationIdToPushRules < Gitlab::Database::Migration[2.2] + DEFAULT_ORGANIZATION_ID = 1 + + restrict_gitlab_migration gitlab_schema: :gitlab_main + enable_lock_retries! + + milestone '16.9' + + def up + execute "UPDATE push_rules SET organization_id = #{DEFAULT_ORGANIZATION_ID} WHERE is_sample = true" + end + + def down + execute 'UPDATE push_rules SET organization_id = NULL WHERE is_sample = true' + end +end diff --git a/db/post_migrate/20240129082324_partition_ci_job_artifacts_add_fk_to_ci_builds.rb b/db/post_migrate/20240129082324_partition_ci_job_artifacts_add_fk_to_ci_builds.rb new file mode 100644 index 00000000000..76af6fd112b --- /dev/null +++ b/db/post_migrate/20240129082324_partition_ci_job_artifacts_add_fk_to_ci_builds.rb @@ -0,0 +1,84 @@ +# frozen_string_literal: true + +class PartitionCiJobArtifactsAddFkToCiBuilds < Gitlab::Database::Migration[2.2] + include Gitlab::Database::PartitioningMigrationHelpers::TableManagementHelpers + + milestone '16.10' + disable_ddl_transaction! + + TABLE_NAME = :ci_job_artifacts + PARENT_TABLE_NAME = :p_ci_job_artifacts + FIRST_PARTITION = [100, 101] + PARTITION_COLUMN = :partition_id + BUILDS_TABLE = :p_ci_builds + + def up + convert_table_to_first_list_partition( + table_name: TABLE_NAME, + partitioning_column: PARTITION_COLUMN, + parent_table_name: PARENT_TABLE_NAME, + initial_partitioning_value: FIRST_PARTITION + ) + end + + def down + # rubocop:disable Migration/WithLockRetriesDisallowedMethod -- we're calling methods defined here + with_lock_retries(raise_on_exhaustion: true) do + drop_foreign_key + + execute(<<~SQL) + ALTER TABLE #{PARENT_TABLE_NAME} DETACH PARTITION #{TABLE_NAME}; + ALTER SEQUENCE ci_job_artifacts_id_seq OWNED BY #{TABLE_NAME}.id; + SQL + + drop_table PARENT_TABLE_NAME + recreate_foreign_key + end + # rubocop:enable Migration/WithLockRetriesDisallowedMethod + + finalize_foreign_key_creation + + prepare_constraint_for_list_partitioning( + table_name: TABLE_NAME, + partitioning_column: PARTITION_COLUMN, + parent_table_name: PARENT_TABLE_NAME, + initial_partitioning_value: FIRST_PARTITION + ) + end + + private + + def foreign_key + @foreign_key ||= Gitlab::Database::PostgresForeignKey + .by_constrained_table_name(PARENT_TABLE_NAME) + .by_referenced_table_name(BUILDS_TABLE) + .first + end + + def drop_foreign_key + raise "Expected to find a foreign key between #{PARENT_TABLE_NAME} and #{BUILDS_TABLE}" unless foreign_key.present? + + remove_foreign_key_if_exists PARENT_TABLE_NAME, name: foreign_key.name + end + + def recreate_foreign_key + execute(<<~SQL) + ALTER TABLE #{TABLE_NAME} + ADD CONSTRAINT #{foreign_key.name} FOREIGN KEY (partition_id, job_id) + REFERENCES #{BUILDS_TABLE}(partition_id, id) + ON UPDATE CASCADE ON DELETE CASCADE NOT VALID; + SQL + end + + def finalize_foreign_key_creation + fk = foreign_key || new_foreign_key + validate_foreign_key TABLE_NAME, nil, name: fk.name + end + + def new_foreign_key + Gitlab::Database::PostgresForeignKey + .by_constrained_table_name(TABLE_NAME) + .by_referenced_table_name(BUILDS_TABLE) + .first + end +end diff --git a/db/post_migrate/20240207130350_change_group_crm_settings_enabled_default.rb b/db/post_migrate/20240207130350_change_group_crm_settings_enabled_default.rb new file mode 100644 index 00000000000..0fa050f95c1 --- /dev/null +++ b/db/post_migrate/20240207130350_change_group_crm_settings_enabled_default.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class ChangeGroupCrmSettingsEnabledDefault < Gitlab::Database::Migration[2.2] + milestone '16.9' + + enable_lock_retries! + + def change + change_column_default('group_crm_settings', 'enabled', from: false, to: true) + end +end diff --git a/db/post_migrate/20240208094017_add_partitioning_constraint_for_ci_stages.rb b/db/post_migrate/20240208094017_add_partitioning_constraint_for_ci_stages.rb new file mode 100644 index 00000000000..4b6d9c814a5 --- /dev/null +++ b/db/post_migrate/20240208094017_add_partitioning_constraint_for_ci_stages.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class AddPartitioningConstraintForCiStages < Gitlab::Database::Migration[2.2] + include Gitlab::Database::PartitioningMigrationHelpers::TableManagementHelpers + + milestone '16.10' + disable_ddl_transaction! + TABLE_NAME = :ci_stages + PARENT_TABLE_NAME = :p_ci_stages + FIRST_PARTITION = [100, 101] + PARTITION_COLUMN = :partition_id + + def up + prepare_constraint_for_list_partitioning( + table_name: TABLE_NAME, + partitioning_column: PARTITION_COLUMN, + parent_table_name: PARENT_TABLE_NAME, + initial_partitioning_value: FIRST_PARTITION, + async: true + ) + end + + def down + revert_preparing_constraint_for_list_partitioning( + table_name: TABLE_NAME, + partitioning_column: PARTITION_COLUMN, + parent_table_name: PARENT_TABLE_NAME, + initial_partitioning_value: FIRST_PARTITION + ) + end +end diff --git a/db/schema_migrations/20240126095808 b/db/schema_migrations/20240126095808 new file mode 100644 index 00000000000..922b326347c --- /dev/null +++ b/db/schema_migrations/20240126095808 @@ -0,0 +1 @@ +d76973ec94918d5c96c95fb98b76e89ec1ea762b98ed8b2859be69441313adb4 \ No newline at end of file diff --git a/db/schema_migrations/20240126100509 b/db/schema_migrations/20240126100509 new file mode 100644 index 00000000000..2730fc6d297 --- /dev/null +++ b/db/schema_migrations/20240126100509 @@ -0,0 +1 @@ +6d39c0690922407f3abef747fa9d7e50a7be65d8a0351276616d2a8858a6927e \ No newline at end of file diff --git a/db/schema_migrations/20240129082324 b/db/schema_migrations/20240129082324 new file mode 100644 index 00000000000..c3f33c47eac --- /dev/null +++ b/db/schema_migrations/20240129082324 @@ -0,0 +1 @@ +330758b6a63cd5f4e5f1de986c99082c502e9499568bf600765eba2e8a7eee0e \ No newline at end of file diff --git a/db/schema_migrations/20240201141351 b/db/schema_migrations/20240201141351 new file mode 100644 index 00000000000..6a8753b41e7 --- /dev/null +++ b/db/schema_migrations/20240201141351 @@ -0,0 +1 @@ +633790bdc2e2024ff5a88bd7c69854d847f5bd5e057aa994fd9139f48c3648c8 \ No newline at end of file diff --git a/db/schema_migrations/20240201141705 b/db/schema_migrations/20240201141705 new file mode 100644 index 00000000000..94c863edeca --- /dev/null +++ b/db/schema_migrations/20240201141705 @@ -0,0 +1 @@ +d30b986a177b8a2806a6f0e307a6d17a4e40db895794e988b10379a9c200b090 \ No newline at end of file diff --git a/db/schema_migrations/20240207130350 b/db/schema_migrations/20240207130350 new file mode 100644 index 00000000000..acca6b36968 --- /dev/null +++ b/db/schema_migrations/20240207130350 @@ -0,0 +1 @@ +555c4cad3d4d75edd6bc75e504ebd551a6f51172b267a3924bcc75ada25d1775 \ No newline at end of file diff --git a/db/schema_migrations/20240208094017 b/db/schema_migrations/20240208094017 new file mode 100644 index 00000000000..4ac88a47c65 --- /dev/null +++ b/db/schema_migrations/20240208094017 @@ -0,0 +1 @@ +74cf13414b035b623dd44401794ac00e0377b1340110a9719f4f9e73cf6a21b4 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index 1efe8fff109..eca1ac35b7d 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -13983,13 +13983,15 @@ CREATE TABLE bulk_import_failures ( pipeline_step text, source_url text, source_title text, + subrelation text, CONSTRAINT check_053d65c7a4 CHECK ((char_length(pipeline_class) <= 255)), CONSTRAINT check_6eca8f972e CHECK ((char_length(exception_message) <= 255)), CONSTRAINT check_721a422375 CHECK ((char_length(pipeline_step) <= 255)), CONSTRAINT check_74414228d4 CHECK ((char_length(source_title) <= 255)), CONSTRAINT check_c7dba8398e CHECK ((char_length(exception_class) <= 255)), CONSTRAINT check_e035a720ad CHECK ((char_length(source_url) <= 255)), - CONSTRAINT check_e787285882 CHECK ((char_length(correlation_id_value) <= 255)) + CONSTRAINT check_e787285882 CHECK ((char_length(correlation_id_value) <= 255)), + CONSTRAINT check_f99665a440 CHECK ((char_length(subrelation) <= 255)) ); CREATE SEQUENCE bulk_import_failures_id_seq @@ -14496,7 +14498,7 @@ CREATE TABLE ci_job_artifact_states ( CONSTRAINT check_df832b66ea CHECK ((char_length(verification_failure) <= 255)) ); -CREATE TABLE ci_job_artifacts ( +CREATE TABLE p_ci_job_artifacts ( project_id integer NOT NULL, file_type integer NOT NULL, size bigint, @@ -14515,9 +14517,9 @@ CREATE TABLE ci_job_artifacts ( accessibility smallint DEFAULT 0 NOT NULL, file_final_path text, CONSTRAINT check_27f0f6dbab CHECK ((file_store IS NOT NULL)), - CONSTRAINT check_9f04410cf4 CHECK ((char_length(file_final_path) <= 1024)), - CONSTRAINT partitioning_constraint CHECK ((partition_id = ANY (ARRAY[(100)::bigint, (101)::bigint]))) -); + CONSTRAINT check_9f04410cf4 CHECK ((char_length(file_final_path) <= 1024)) +) +PARTITION BY LIST (partition_id); CREATE SEQUENCE ci_job_artifacts_id_seq START WITH 1 @@ -14526,7 +14528,29 @@ CREATE SEQUENCE ci_job_artifacts_id_seq NO MAXVALUE CACHE 1; -ALTER SEQUENCE ci_job_artifacts_id_seq OWNED BY ci_job_artifacts.id; +ALTER SEQUENCE ci_job_artifacts_id_seq OWNED BY p_ci_job_artifacts.id; + +CREATE TABLE ci_job_artifacts ( + project_id integer NOT NULL, + file_type integer NOT NULL, + size bigint, + created_at timestamp with time zone NOT NULL, + updated_at timestamp with time zone NOT NULL, + expire_at timestamp with time zone, + file character varying, + file_store integer DEFAULT 1, + file_sha256 bytea, + file_format smallint, + file_location smallint, + id bigint DEFAULT nextval('ci_job_artifacts_id_seq'::regclass) NOT NULL, + job_id bigint NOT NULL, + locked smallint DEFAULT 2, + partition_id bigint NOT NULL, + accessibility smallint DEFAULT 0 NOT NULL, + file_final_path text, + CONSTRAINT check_27f0f6dbab CHECK ((file_store IS NOT NULL)), + CONSTRAINT check_9f04410cf4 CHECK ((char_length(file_final_path) <= 1024)) +); CREATE TABLE ci_job_token_group_scope_links ( id bigint NOT NULL, @@ -17735,7 +17759,7 @@ CREATE TABLE group_crm_settings ( group_id bigint NOT NULL, created_at timestamp with time zone NOT NULL, updated_at timestamp with time zone NOT NULL, - enabled boolean DEFAULT false NOT NULL + enabled boolean DEFAULT true NOT NULL ); CREATE SEQUENCE group_crm_settings_group_id_seq @@ -23185,6 +23209,7 @@ CREATE TABLE push_rules ( commit_message_negative_regex character varying, reject_non_dco_commits boolean, commit_committer_name_check boolean DEFAULT false NOT NULL, + organization_id bigint, CONSTRAINT author_email_regex_size_constraint CHECK ((char_length((author_email_regex)::text) <= 511)), CONSTRAINT branch_name_regex_size_constraint CHECK ((char_length((branch_name_regex)::text) <= 511)), CONSTRAINT commit_message_negative_regex_size_constraint CHECK ((char_length((commit_message_negative_regex)::text) <= 2047)), @@ -26964,6 +26989,8 @@ ALTER TABLE ONLY p_ci_builds ATTACH PARTITION ci_builds FOR VALUES IN ('100'); ALTER TABLE ONLY p_ci_builds_metadata ATTACH PARTITION ci_builds_metadata FOR VALUES IN ('100'); +ALTER TABLE ONLY p_ci_job_artifacts ATTACH PARTITION ci_job_artifacts FOR VALUES IN ('100', '101'); + ALTER TABLE ONLY p_ci_pipeline_variables ATTACH PARTITION ci_pipeline_variables FOR VALUES IN ('100', '101'); ALTER TABLE ONLY abuse_events ALTER COLUMN id SET DEFAULT nextval('abuse_events_id_seq'::regclass); @@ -27180,8 +27207,6 @@ ALTER TABLE ONLY ci_group_variables ALTER COLUMN id SET DEFAULT nextval('ci_grou ALTER TABLE ONLY ci_instance_variables ALTER COLUMN id SET DEFAULT nextval('ci_instance_variables_id_seq'::regclass); -ALTER TABLE ONLY ci_job_artifacts ALTER COLUMN id SET DEFAULT nextval('ci_job_artifacts_id_seq'::regclass); - ALTER TABLE ONLY ci_job_token_group_scope_links ALTER COLUMN id SET DEFAULT nextval('ci_job_token_group_scope_links_id_seq'::regclass); ALTER TABLE ONLY ci_job_token_project_scope_links ALTER COLUMN id SET DEFAULT nextval('ci_job_token_project_scope_links_id_seq'::regclass); @@ -27714,6 +27739,8 @@ ALTER TABLE ONLY p_ci_builds_metadata ALTER COLUMN id SET DEFAULT nextval('ci_bu ALTER TABLE ONLY p_ci_job_annotations ALTER COLUMN id SET DEFAULT nextval('p_ci_job_annotations_id_seq'::regclass); +ALTER TABLE ONLY p_ci_job_artifacts ALTER COLUMN id SET DEFAULT nextval('ci_job_artifacts_id_seq'::regclass); + ALTER TABLE ONLY packages_build_infos ALTER COLUMN id SET DEFAULT nextval('packages_build_infos_id_seq'::regclass); ALTER TABLE ONLY packages_composer_cache_files ALTER COLUMN id SET DEFAULT nextval('packages_composer_cache_files_id_seq'::regclass); @@ -29267,6 +29294,9 @@ ALTER TABLE ONLY ci_instance_variables ALTER TABLE ONLY ci_job_artifact_states ADD CONSTRAINT ci_job_artifact_states_pkey PRIMARY KEY (job_artifact_id); +ALTER TABLE ONLY p_ci_job_artifacts + ADD CONSTRAINT p_ci_job_artifacts_pkey PRIMARY KEY (id, partition_id); + ALTER TABLE ONLY ci_job_artifacts ADD CONSTRAINT ci_job_artifacts_pkey PRIMARY KEY (id, partition_id); @@ -30338,6 +30368,9 @@ ALTER TABLE ONLY pages_domain_acme_orders ALTER TABLE ONLY pages_domains ADD CONSTRAINT pages_domains_pkey PRIMARY KEY (id); +ALTER TABLE ci_stages + ADD CONSTRAINT partitioning_constraint CHECK ((partition_id = ANY (ARRAY[(100)::bigint, (101)::bigint]))) NOT VALID; + ALTER TABLE ONLY path_locks ADD CONSTRAINT path_locks_pkey PRIMARY KEY (id); @@ -32425,6 +32458,8 @@ CREATE INDEX idx_award_emoji_on_user_emoji_name_awardable_type_awardable_id ON a CREATE INDEX idx_build_artifacts_size_refreshes_state_updated_at ON project_build_artifacts_size_refreshes USING btree (state, updated_at); +CREATE UNIQUE INDEX p_ci_job_artifacts_job_id_file_type_partition_id_idx ON ONLY p_ci_job_artifacts USING btree (job_id, file_type, partition_id); + CREATE UNIQUE INDEX idx_ci_job_artifacts_on_job_id_file_type_and_partition_id_uniq ON ci_job_artifacts USING btree (job_id, file_type, partition_id); CREATE INDEX idx_ci_pipelines_artifacts_locked ON ci_pipelines USING btree (ci_ref_id, id) WHERE (locked = 1); @@ -33155,30 +33190,56 @@ CREATE UNIQUE INDEX index_ci_instance_variables_on_key ON ci_instance_variables CREATE INDEX index_ci_job_artifact_states_on_job_artifact_id_partition_id ON ci_job_artifact_states USING btree (job_artifact_id, partition_id); +CREATE INDEX p_ci_job_artifacts_expire_at_idx ON ONLY p_ci_job_artifacts USING btree (expire_at) WHERE ((locked = 0) AND (file_type <> 3) AND (expire_at IS NOT NULL)); + CREATE INDEX index_ci_job_artifacts_expire_at_unlocked_non_trace ON ci_job_artifacts USING btree (expire_at) WHERE ((locked = 0) AND (file_type <> 3) AND (expire_at IS NOT NULL)); +CREATE INDEX p_ci_job_artifacts_project_id_id_idx ON ONLY p_ci_job_artifacts USING btree (project_id, id) WHERE (file_type = 18); + CREATE INDEX index_ci_job_artifacts_for_terraform_reports ON ci_job_artifacts USING btree (project_id, id) WHERE (file_type = 18); +CREATE INDEX p_ci_job_artifacts_id_idx ON ONLY p_ci_job_artifacts USING btree (id) WHERE (file_type = 18); + CREATE INDEX index_ci_job_artifacts_id_for_terraform_reports ON ci_job_artifacts USING btree (id) WHERE (file_type = 18); +CREATE INDEX p_ci_job_artifacts_expire_at_job_id_idx ON ONLY p_ci_job_artifacts USING btree (expire_at, job_id); + CREATE INDEX index_ci_job_artifacts_on_expire_at_and_job_id ON ci_job_artifacts USING btree (expire_at, job_id); +CREATE INDEX p_ci_job_artifacts_file_final_path_idx ON ONLY p_ci_job_artifacts USING btree (file_final_path) WHERE (file_final_path IS NOT NULL); + CREATE INDEX index_ci_job_artifacts_on_file_final_path ON ci_job_artifacts USING btree (file_final_path) WHERE (file_final_path IS NOT NULL); +CREATE INDEX p_ci_job_artifacts_file_store_idx ON ONLY p_ci_job_artifacts USING btree (file_store); + CREATE INDEX index_ci_job_artifacts_on_file_store ON ci_job_artifacts USING btree (file_store); +CREATE INDEX p_ci_job_artifacts_file_type_project_id_created_at_idx ON ONLY p_ci_job_artifacts USING btree (file_type, project_id, created_at) WHERE (file_type = ANY (ARRAY[5, 6, 8, 23])); + CREATE INDEX index_ci_job_artifacts_on_file_type_for_devops_adoption ON ci_job_artifacts USING btree (file_type, project_id, created_at) WHERE (file_type = ANY (ARRAY[5, 6, 8, 23])); +CREATE INDEX p_ci_job_artifacts_project_id_created_at_id_idx ON ONLY p_ci_job_artifacts USING btree (project_id, created_at, id); + CREATE INDEX index_ci_job_artifacts_on_id_project_id_and_created_at ON ci_job_artifacts USING btree (project_id, created_at, id); +CREATE INDEX p_ci_job_artifacts_project_id_file_type_id_idx ON ONLY p_ci_job_artifacts USING btree (project_id, file_type, id); + CREATE INDEX index_ci_job_artifacts_on_id_project_id_and_file_type ON ci_job_artifacts USING btree (project_id, file_type, id); +CREATE INDEX p_ci_job_artifacts_partition_id_job_id_idx ON ONLY p_ci_job_artifacts USING btree (partition_id, job_id); + CREATE INDEX index_ci_job_artifacts_on_partition_id_job_id ON ci_job_artifacts USING btree (partition_id, job_id); +CREATE INDEX p_ci_job_artifacts_project_id_idx ON ONLY p_ci_job_artifacts USING btree (project_id); + CREATE INDEX index_ci_job_artifacts_on_project_id ON ci_job_artifacts USING btree (project_id); +CREATE INDEX p_ci_job_artifacts_project_id_id_idx1 ON ONLY p_ci_job_artifacts USING btree (project_id, id); + CREATE INDEX index_ci_job_artifacts_on_project_id_and_id ON ci_job_artifacts USING btree (project_id, id); +CREATE INDEX p_ci_job_artifacts_project_id_idx1 ON ONLY p_ci_job_artifacts USING btree (project_id) WHERE (file_type = ANY (ARRAY[5, 6, 7, 8])); + CREATE INDEX index_ci_job_artifacts_on_project_id_for_security_reports ON ci_job_artifacts USING btree (project_id) WHERE (file_type = ANY (ARRAY[5, 6, 7, 8])); CREATE INDEX index_ci_job_token_group_scope_links_on_added_by_id ON ci_job_token_group_scope_links USING btree (added_by_id); @@ -35361,6 +35422,8 @@ CREATE UNIQUE INDEX index_protected_tags_on_project_id_and_name ON protected_tag CREATE INDEX index_push_rules_on_is_sample ON push_rules USING btree (is_sample) WHERE is_sample; +CREATE INDEX index_push_rules_on_organization_id ON push_rules USING btree (organization_id); + CREATE INDEX index_push_rules_on_project_id ON push_rules USING btree (project_id); CREATE UNIQUE INDEX index_raw_usage_data_on_recorded_at ON raw_usage_data USING btree (recorded_at); @@ -36297,6 +36360,8 @@ CREATE INDEX p_ci_builds_scheduled_at_idx ON ONLY p_ci_builds USING btree (sched CREATE UNIQUE INDEX p_ci_builds_token_encrypted_partition_id_idx ON ONLY p_ci_builds USING btree (token_encrypted, partition_id) WHERE (token_encrypted IS NOT NULL); +CREATE INDEX p_ci_job_artifacts_expire_at_job_id_idx1 ON ONLY p_ci_job_artifacts USING btree (expire_at, job_id) WHERE ((locked = 2) AND (expire_at IS NOT NULL)); + CREATE INDEX package_name_index ON packages_packages USING btree (name); CREATE INDEX packages_packages_failed_verification ON packages_package_files USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3); @@ -38177,8 +38242,12 @@ ALTER INDEX p_ci_builds_metadata_pkey ATTACH PARTITION ci_builds_metadata_pkey; ALTER INDEX p_ci_builds_pkey ATTACH PARTITION ci_builds_pkey; +ALTER INDEX p_ci_job_artifacts_pkey ATTACH PARTITION ci_job_artifacts_pkey; + ALTER INDEX p_ci_pipeline_variables_pkey ATTACH PARTITION ci_pipeline_variables_pkey; +ALTER INDEX p_ci_job_artifacts_job_id_file_type_partition_id_idx ATTACH PARTITION idx_ci_job_artifacts_on_job_id_file_type_and_partition_id_uniq; + ALTER INDEX p_ci_builds_commit_id_bigint_artifacts_expire_at_id_idx ATTACH PARTITION index_357cc39ca4; ALTER INDEX p_ci_builds_upstream_pipeline_id_bigint_idx ATTACH PARTITION index_89477d6012; @@ -38229,6 +38298,32 @@ ALTER INDEX p_ci_builds_project_id_status_idx ATTACH PARTITION index_ci_builds_p ALTER INDEX p_ci_builds_runner_id_idx ATTACH PARTITION index_ci_builds_runner_id_running; +ALTER INDEX p_ci_job_artifacts_expire_at_idx ATTACH PARTITION index_ci_job_artifacts_expire_at_unlocked_non_trace; + +ALTER INDEX p_ci_job_artifacts_project_id_id_idx ATTACH PARTITION index_ci_job_artifacts_for_terraform_reports; + +ALTER INDEX p_ci_job_artifacts_id_idx ATTACH PARTITION index_ci_job_artifacts_id_for_terraform_reports; + +ALTER INDEX p_ci_job_artifacts_expire_at_job_id_idx ATTACH PARTITION index_ci_job_artifacts_on_expire_at_and_job_id; + +ALTER INDEX p_ci_job_artifacts_file_final_path_idx ATTACH PARTITION index_ci_job_artifacts_on_file_final_path; + +ALTER INDEX p_ci_job_artifacts_file_store_idx ATTACH PARTITION index_ci_job_artifacts_on_file_store; + +ALTER INDEX p_ci_job_artifacts_file_type_project_id_created_at_idx ATTACH PARTITION index_ci_job_artifacts_on_file_type_for_devops_adoption; + +ALTER INDEX p_ci_job_artifacts_project_id_created_at_id_idx ATTACH PARTITION index_ci_job_artifacts_on_id_project_id_and_created_at; + +ALTER INDEX p_ci_job_artifacts_project_id_file_type_id_idx ATTACH PARTITION index_ci_job_artifacts_on_id_project_id_and_file_type; + +ALTER INDEX p_ci_job_artifacts_partition_id_job_id_idx ATTACH PARTITION index_ci_job_artifacts_on_partition_id_job_id; + +ALTER INDEX p_ci_job_artifacts_project_id_idx ATTACH PARTITION index_ci_job_artifacts_on_project_id; + +ALTER INDEX p_ci_job_artifacts_project_id_id_idx1 ATTACH PARTITION index_ci_job_artifacts_on_project_id_and_id; + +ALTER INDEX p_ci_job_artifacts_project_id_idx1 ATTACH PARTITION index_ci_job_artifacts_on_project_id_for_security_reports; + ALTER INDEX p_ci_builds_commit_id_bigint_type_ref_idx ATTACH PARTITION index_fc42f73fa6; ALTER INDEX p_ci_builds_commit_id_bigint_type_name_ref_idx ATTACH PARTITION index_feafb4d370; @@ -38245,6 +38340,8 @@ ALTER INDEX p_ci_builds_name_id_idx ATTACH PARTITION index_security_ci_builds_on ALTER INDEX p_ci_builds_scheduled_at_idx ATTACH PARTITION partial_index_ci_builds_on_scheduled_at_with_scheduled_jobs; +ALTER INDEX p_ci_job_artifacts_expire_at_job_id_idx1 ATTACH PARTITION tmp_index_ci_job_artifacts_on_expire_at_where_locked_unknown; + ALTER INDEX p_ci_builds_token_encrypted_partition_id_idx ATTACH PARTITION unique_ci_builds_token_encrypted_and_partition_id; CREATE TRIGGER assign_p_ci_builds_id_trigger BEFORE INSERT ON p_ci_builds FOR EACH ROW EXECUTE FUNCTION assign_p_ci_builds_id_value(); @@ -40946,7 +41043,7 @@ ALTER TABLE ONLY related_epic_links ALTER TABLE ONLY boards_epic_board_recent_visits ADD CONSTRAINT fk_rails_c4dcba4a3e FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE; -ALTER TABLE ONLY ci_job_artifacts +ALTER TABLE p_ci_job_artifacts ADD CONSTRAINT fk_rails_c5137cb2c1_p FOREIGN KEY (partition_id, job_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE; ALTER TABLE ONLY organization_settings diff --git a/doc/administration/cicd.md b/doc/administration/cicd.md index 040fe843355..5c99e2ed497 100644 --- a/doc/administration/cicd.md +++ b/doc/administration/cicd.md @@ -105,18 +105,18 @@ to a cron value of `0 */12 * * *` (`00:00` and `12:00` every day). You can disable some important but computationally expensive parts of the application to relieve stress on the database during ongoing downtime. -### Disable fair scheduling on shared runners +### Disable fair scheduling on instance runners When clearing a large backlog of jobs, you can temporarily enable the `ci_queueing_disaster_recovery_disable_fair_scheduling` [feature flag](../administration/feature_flags.md). This flag disables fair scheduling -on shared runners, which reduces system resource usage on the `jobs/request` endpoint. +on instance runners, which reduces system resource usage on the `jobs/request` endpoint. When enabled, jobs are processed in the order they were put in the system, instead of balanced across many projects. ### Disable compute quota enforcement -To disable the enforcement of [compute quotas](../ci/pipelines/cicd_minutes.md) on shared runners, you can temporarily +To disable the enforcement of [compute quotas](../ci/pipelines/cicd_minutes.md) on instance runners, you can temporarily enable the `ci_queueing_disaster_recovery_disable_quota` [feature flag](../administration/feature_flags.md). This flag reduces system resource usage on the `jobs/request` endpoint. diff --git a/doc/administration/libravatar.md b/doc/administration/libravatar.md index ab5b0160af8..5d72e655bd5 100644 --- a/doc/administration/libravatar.md +++ b/doc/administration/libravatar.md @@ -18,13 +18,8 @@ other websites. The Libravatar API is switch to the Libravatar avatar service or even your own Libravatar server. -You cannot use any Libravatar service including Gravatar in [FIPS mode](../development/fips_compliance.md). - ## Change the Libravatar service to your own service -NOTE: -You can use only the MD5 hash in the URL for the Libravatar service. See [issue 370057](https://gitlab.com/gitlab-org/gitlab/-/issues/370057) for adding SHA-256 support. - In the [`gitlab.yml` gravatar section](https://gitlab.com/gitlab-org/gitlab/-/blob/68dac188ec6b1b03d53365e7579422f44cbe7a1c/config/gitlab.yml.example#L469-476), set the configuration options as follows: diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md index a17b05bc8c2..ca9a21a3752 100644 --- a/doc/administration/pages/index.md +++ b/doc/administration/pages/index.md @@ -60,7 +60,7 @@ Before proceeding with the Pages configuration, you must: 1. Configure a **wildcard DNS record**. 1. Optional. Have a **wildcard certificate** for that domain if you decide to serve Pages under HTTPS. -1. Optional but recommended. Enable [Shared runners](../../ci/runners/index.md) +1. Optional but recommended. Enable [instance runners](../../ci/runners/index.md) so that your users don't have to bring their own. 1. For custom domains, have a **secondary IP**. diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md index 6e2ae56ec5c..e33d1a47a8a 100644 --- a/doc/administration/pages/source.md +++ b/doc/administration/pages/source.md @@ -60,7 +60,7 @@ Before proceeding with the Pages configuration, make sure that: Pages artifacts. - Optional. You have a **wildcard certificate** for the Pages domain if you decide to serve Pages (`*.example.io`) under HTTPS. -- Optional but recommended. You have configured and enabled the [shared runners](../../ci/runners/index.md) +- Optional but recommended. You have configured and enabled the [instance runners](../../ci/runners/index.md) so your users don't have to bring their own. ### DNS configuration diff --git a/doc/administration/settings/continuous_integration.md b/doc/administration/settings/continuous_integration.md index dfa0c499edb..5a85357cf7d 100644 --- a/doc/administration/settings/continuous_integration.md +++ b/doc/administration/settings/continuous_integration.md @@ -31,18 +31,18 @@ From now on, every existing project and newly created ones that don't have a If you want to disable it for a specific project, you can do so in [its settings](../../topics/autodevops/index.md#enable-or-disable-auto-devops). -## Enable shared runners for new projects +## Enable instance runners for new projects -You can set all new projects to have the instance's shared runners available by default. +You can set all new projects to have instance runners available by default. 1. On the left sidebar, at the bottom, select **Admin Area**. 1. Select **Settings > CI/CD**. 1. Expand **Continuous Integration and Deployment**. -1. Select the **Enable shared runners for new projects** checkbox. +1. Select the **Enable instance runners for new projects** checkbox. -Any time a new project is created, the shared runners are available. +Any time a new project is created, the instance runners are available. -## Shared runners compute quota +## Instance runners compute quota As an administrator you can set either a global or namespace-specific limit on the number of [compute minutes](../../ci/pipelines/cicd_minutes.md) you can use. @@ -62,17 +62,15 @@ To enable a project runner for more than one project: 1. To the left of the project, select **Enable**. 1. Repeat this process for each additional project. -## Add a message for shared runners +## Add a message for instance runners -To display details about the instance's shared runners in all projects' +To display details about the instance runners in all projects' runner settings: 1. On the left sidebar, at the bottom, select **Admin Area**. 1. Select **Settings > CI/CD**. 1. Expand **Continuous Integration and Deployment**. -1. Enter text, including Markdown if you want, in the **Shared runner details** field. For example: - - ![Shared runner details input](img/continuous_integration_shared_runner_details_input_v14_10.png) +1. Enter text, including Markdown if you want, in the **Instance runner details** field. To view the rendered details: @@ -80,7 +78,7 @@ To view the rendered details: 1. Select **Settings > CI/CD**. 1. Expand **Runners**. -![Shared runner details example](img/continuous_integration_shared_runner_details_v14_10.png) +![Instance runner details example](img/continuous_integration_shared_runner_details_v14_10.png) ## Maximum artifacts size diff --git a/doc/administration/settings/img/continuous_integration_shared_runner_details_input_v14_10.png b/doc/administration/settings/img/continuous_integration_shared_runner_details_input_v14_10.png deleted file mode 100644 index 08451f36962..00000000000 Binary files a/doc/administration/settings/img/continuous_integration_shared_runner_details_input_v14_10.png and /dev/null differ diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 596eccd0586..2ffdcd4e7da 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -2064,6 +2064,29 @@ Input type: `BranchRuleCreateInput` | `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | | `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | +### `Mutation.branchRuleDelete` + +NOTE: +**Introduced** in 16.9. +**Status**: Experiment. + +Input type: `BranchRuleDeleteInput` + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `id` | [`ProjectsBranchRuleID!`](#projectsbranchruleid) | Global ID of the branch rule to destroy. | + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `branchRule` | [`BranchRule`](#branchrule) | Branch rule after mutation. | +| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | + ### `Mutation.branchRuleUpdate` NOTE: diff --git a/doc/api/member_roles.md b/doc/api/member_roles.md index 886cd1d19ef..8473e2301ae 100644 --- a/doc/api/member_roles.md +++ b/doc/api/member_roles.md @@ -75,7 +75,7 @@ Example response: { "id": 2, "name": "Custom + code", - "description: "Custom guest that can read code", + "description": "Custom guest that can read code", "group_id": 84, "base_access_level": 10, "admin_merge_request": false, @@ -92,7 +92,7 @@ Example response: { "id": 3, "name": "Guest + security", - "description: "Custom guest that read and admin security entities", + "description": "Custom guest that read and admin security entities", "group_id": 84, "base_access_level": 10, "admin_vulnerability": true, diff --git a/doc/api/runners.md b/doc/api/runners.md index 395221aff12..2b24b113821 100644 --- a/doc/api/runners.md +++ b/doc/api/runners.md @@ -471,7 +471,7 @@ Example response: ## List project's runners -List all runners available in the project, including from ancestor groups and [any allowed shared runners](../ci/runners/runners_scope.md#enable-shared-runners-for-a-project). +List all runners available in the project, including from ancestor groups and [any allowed shared runners](../ci/runners/runners_scope.md#enable-instance-runners-for-a-project). ```plaintext GET /projects/:id/runners @@ -590,7 +590,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: " "https://git ## List group's runners -List all runners available in the group as well as its ancestor groups, including [any allowed shared runners](../ci/runners/runners_scope.md#enable-shared-runners-for-a-group). +List all runners available in the group as well as its ancestor groups, including [any allowed shared runners](../ci/runners/runners_scope.md#enable-instance-runners-for-a-group). ```plaintext GET /groups/:id/runners diff --git a/doc/architecture/blueprints/ci_build_speed/benchmark.md b/doc/architecture/blueprints/ci_build_speed/benchmark.md new file mode 100644 index 00000000000..830db84ead8 --- /dev/null +++ b/doc/architecture/blueprints/ci_build_speed/benchmark.md @@ -0,0 +1,84 @@ +--- +status: ongoing +creation-date: "2024-01-12" +authors: [ "@grzesiek" ] +coach: "@grzesiek" +approvers: [ "@gabrielengel_gl"] +--- + +# CI Build Speed Benchmarking Framework + +In order to understand how GitLab CI performs in terms of CI build speed, we +plan to build CI Build Speed Benchmarking Framework. + +## Benchmark + +In order to run the benchmark, we will: + +1. Install the benchmarking tool. +1. Start the tool. +1. Runs scenarios. +1. Report results back to GitLab data warehouse. + +In the first iteration, we will focus on measuring the speed of GitLab CI, GitHub Actions, and CircleCI. + +## Principles + +There are a few design principles we should abide by: + +1. Make it CI-platform agnostic. Can run on any Continuous Integration platform. +1. Do not depend on any specific technology that might not be available on some platforms. +1. Easy installation setup, not requiring many dependencies. Zero-dependency would be ideal. +1. Send results back to GitLab through an HTTP request, unless there is a better way. +1. Read as much data about the environment running a build and send details in the telemetry. + +## Benchmarking: Client Side + +The benchmarking tool should be able to measure every step of CI build +execution: + +1. Time from build requested to scenario execution started. +1. Monotonic time to execute each of the steps of the scenario. +1. Thread time to execute each of the steps of the scenario. +1. Time required to report results back to GitLab. + +Ideally the tool could collect this data in the +[Open Telemetry Tracing](https://opentelemetry.io/docs/specs/otel/trace/api/) +format. + +### Go-based tool + +One of the solutions that could meet the requirements / principles listed +above, could be a Go-based binary, which would be installed on different CI +platform using `wget` / `curl` or in a different convinient way. The benefits +of using the binary are: + +1. Easy installation method, without the need to use containers. +1. Few external dependencies for a statically-linked binary. +1. Many libraries available, for tracing or HTTP / API integrations. +1. Multi-threaded execution mode that broadens benchmarking scope. +1. Expressive language that can make it easier to maintain the scenarios. + +### Benchmarking: Server Side + +## Pipelines scheduler + +In order to run the benchmark a new build / pipeline / job will have to be +started on a continuous integration platform under test. Some platforms support +scheduled pipelines, but this could make it difficult to measure the build +start-up time. On alternative to consider during the implementation is to start +pipelines using API trigger endpoints. Most of the CI platforms support this +way of running pipelines, and we could pass the start-up time / pipeline +creation request time in an argument, that then will be consumed by the +benchmarking tool, and forwarded to the data warehouse along with the build +benchmark telemetry. + +## Data warehouse + +The server side, that will receive benchmarking telemetry, will eventually need +to forward the data to a data warehouse, in which we will be able to visualize +results, like Kibana or our Observability / Tracing tooling. + +Before doing that, it could be advisable to persist the payload in object +storage, just in case we need to migrate historical entries to a different data +warehouse later on. diff --git a/doc/architecture/blueprints/ci_build_speed/index.md b/doc/architecture/blueprints/ci_build_speed/index.md new file mode 100644 index 00000000000..bd94cca430f --- /dev/null +++ b/doc/architecture/blueprints/ci_build_speed/index.md @@ -0,0 +1,73 @@ +--- +status: ongoing +creation-date: "2024-01-12" +authors: [ "@grzesiek" ] +coach: "@grzesiek" +approvers: [ "@gabrielengel_gl"] +--- + + + +# CI/CD Build Speed + +## Summary + +GitLab CI is a Continuous Integration platform which is widely used to run a +variety of jobs, builds, pipelines. It was [integrated into GitLab in September 2015](https://about.gitlab.com/releases/2015/09/22/gitlab-8-0-released/) +and has become [one of the most beloved CI/CD solutions](https://about.gitlab.com/blog/2017/09/27/gitlab-leader-continuous-integration-forrester-wave/). + +With years we've added a lot of new features and code to the GitLab CI +platform. In order to retain the "one of the most beloved solutions" status, we +also need keep attention to making it fast, reliable and secure. This design +doc is describing the path towards the former: making GitLab CI fast by +improving CI build speed. + +## Goals + +1. Establish a CI Speed Benchmark, used to compare GitLab CI to other platforms. +1. Build CI Benchmark Framework to measure the GitLab CI speed over the long term. +1. Describe next steps for improving GitLab CI Build Speed. + +## Proposal + +### CI Speed Benchmark + +First, we plan to build a [CI Speed Benchmark](benchmark.md) solution, that +will allow us to run specific scenarios on various CI/CD platform and ingest +results into our data warehouse. + +This will make it possible to define a baseline of the CI Build Speed for many +different scenarios and track the progress we, and other providers, are making +over time. + +The core part of this goal is to define a set of scenarios that will allow us +to build a proxy metrics for build speed. For example, we could run following +scenarios: + +1. Time to first byte of build log for `echo "Hello World"` build. +1. Time to result to perform a CPU-intensive cryptographic operation. +1. Time to result to perform a memory-intensive for a given amount of bytes. +1. Time to result to build a Linux kernel. + +The scenarios should be idempotent and deterministic. + +In the first iteration, we will only focus on the total job execution time, and not go into detail e.g. comparing specific startup times. + +### CI Benchmark Framework + +Once we define scenarios that we want to implement, we should build a +[CI Benchmark Framework](benchmark.md). The framework will be used to run +scenarios in a Continuous Integration environment, and to send the results back +to our data warehouse, for analysis and comparison. + +The main principles behind design choices for the framework, are: + +1. Make it CI-platform agnostic. Can run on any Continuous Integration platform. +1. Do not depend on any specific technology that might not be available on some platforms. +1. Easy installation setup, not requiring many dependencies. Zero-dependency would be ideal. +1. Send results back to GitLab through an HTTP request, unless there is a better way. + +#### Improve CI Build Speed + +Once we can measure CI Build Speed, improving it can be possible. We will +define the next steps for improving the speed once we have initial results. diff --git a/doc/architecture/blueprints/gitlab_services/index.md b/doc/architecture/blueprints/gitlab_services/index.md index 54229b31fa3..cef9c990d15 100644 --- a/doc/architecture/blueprints/gitlab_services/index.md +++ b/doc/architecture/blueprints/gitlab_services/index.md @@ -110,7 +110,7 @@ and grouping it by the **name** of the environments. For example: classDiagram Group "1" o-- "*" Project : There may be multiple projects with services in a group Project "1" <.. "*" Service : A service is part of a project - Project "1" <.. "*" Environment : + Project "1" <.. "*" Environment : An environment is part of project Environment "*" .. "*" Service : A service is linked to 1+ environments Service "1" <|-- "*" ReleaseArtifact : A release artifact packages a specific version of a service ReleaseArtifact "1" <|-- "*" Deployment : A release artifact can be deployed diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md index bc24bff890a..ee19104e5c8 100644 --- a/doc/ci/caching/index.md +++ b/doc/ci/caching/index.md @@ -60,7 +60,7 @@ For runners to work with caches efficiently, you must do one of the following: - Use a single runner for all your jobs. - Use multiple runners that have [distributed caching](https://docs.gitlab.com/runner/configuration/autoscale.html#distributed-runners-caching), - where the cache is stored in S3 buckets. Shared runners on GitLab.com behave this way. These runners can be in autoscale mode, + where the cache is stored in S3 buckets. Instance runners on GitLab.com behave this way. These runners can be in autoscale mode, but they don't have to be. To manage cache objects, apply lifecycle rules to delete the cache objects after a period of time. Lifecycle rules are available on the object storage server. diff --git a/doc/ci/cloud_services/index.md b/doc/ci/cloud_services/index.md index fc327a0876d..a09498c7908 100644 --- a/doc/ci/cloud_services/index.md +++ b/doc/ci/cloud_services/index.md @@ -50,7 +50,7 @@ review for the pipeline, focusing on the additional access. For more information - Removes the need to store secrets in your GitLab group or project. Temporary credentials can be retrieved from your cloud provider through OIDC. - Provides temporary access to cloud resources with granular GitLab conditionals including a group, project, branch, or tag. - Enables you to define separation of duties in the CI/CD job with conditional access to environments. Historically, apps may have been deployed with a designated GitLab Runner that had only access to staging or production environments. This led to Runner sprawl as each machine had dedicated permissions. -- Allows shared runners to securely access multiple cloud accounts. The access is determined by the JWT token, which is specific to the user running the pipeline. +- Allows instance runners to securely access multiple cloud accounts. The access is determined by the JWT token, which is specific to the user running the pipeline. - Removes the need to create logic to rotate secrets by retrieving temporary credentials by default. ## How it works diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md index f71227ae23f..727ecc812f6 100644 --- a/doc/ci/docker/using_docker_build.md +++ b/doc/ci/docker/using_docker_build.md @@ -92,7 +92,7 @@ The Docker image includes all of the `docker` tools and can run the job script in context of the image in privileged mode. You should use Docker-in-Docker with TLS enabled, -which is supported by [GitLab.com shared runners](../runners/index.md). +which is supported by [GitLab.com instance runners](../runners/index.md). You should always pin a specific version of the image, like `docker:24.0.5`. If you use a tag like `docker:latest`, you have no control over which version is used. @@ -638,7 +638,7 @@ When using Docker-in-Docker, Docker downloads all layers of your image every tim ## Use the OverlayFS driver NOTE: -The shared runners on GitLab.com use the `overlay2` driver by default. +The instance runners on GitLab.com use the `overlay2` driver by default. By default, when using `docker:dind`, Docker uses the `vfs` storage driver, which copies the file system on every run. You can avoid this disk-intensive operation by using a different driver, for example `overlay2`. diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md index 47263e9f398..25f2c4cff9d 100644 --- a/doc/ci/docker/using_docker_images.md +++ b/doc/ci/docker/using_docker_images.md @@ -228,7 +228,7 @@ To define which option should be used, the runner process reads the configuratio in GitLab Runner 13.1 and later. - [Credentials Store](#use-a-credentials-store) and [Credential Helpers](#use-credential-helpers) require binaries to be added to the GitLab Runner `$PATH`, and require access to do so. Therefore, - these features are not available on shared runners, or any other runner where the user does not + these features are not available on instance runners, or any other runner where the user does not have access to the environment where the runner is installed. ### Use statically-defined credentials diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md index d042a08f406..c317c87fc8b 100644 --- a/doc/ci/docker/using_kaniko.md +++ b/doc/ci/docker/using_kaniko.md @@ -148,7 +148,7 @@ The [Least Privilege Container Builds with Kaniko on GitLab](https://www.youtube video is a walkthrough of the [Kaniko Docker Build](https://gitlab.com/guided-explorations/containers/kaniko-docker-build) Guided Exploration project pipeline. It was tested on: -- [GitLab.com shared runners](../runners/index.md) +- [GitLab.com instance runners](../runners/index.md) - [The Kubernetes runner executor](https://docs.gitlab.com/runner/executors/kubernetes.html) The example can be copied to your own group or instance for testing. More details diff --git a/doc/ci/examples/php.md b/doc/ci/examples/php.md index 5dc89148deb..0dd03c5a345 100644 --- a/doc/ci/examples/php.md +++ b/doc/ci/examples/php.md @@ -273,7 +273,7 @@ gitlab-runner exec shell test:app We have set up an [Example PHP Project](https://gitlab.com/gitlab-examples/php) for your convenience that runs on [GitLab.com](https://gitlab.com) using our publicly available -[shared runners](../runners/index.md). +[instance runners](../runners/index.md). Want to hack on it? Fork it, commit, and push your changes. Within a few moments the changes are picked by a public runner and the job begins. diff --git a/doc/ci/interactive_web_terminal/index.md b/doc/ci/interactive_web_terminal/index.md index 7e17b564a68..70358f37288 100644 --- a/doc/ci/interactive_web_terminal/index.md +++ b/doc/ci/interactive_web_terminal/index.md @@ -20,7 +20,7 @@ is deployed, some [security precautions](../../administration/integration/termin taken to protect the users. NOTE: -[Shared runners on GitLab.com](../runners/index.md) do not +[Instance runners on GitLab.com](../runners/index.md) do not provide an interactive web terminal. Follow [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/24674) for progress on adding support. For groups and projects hosted on GitLab.com, interactive web diff --git a/doc/ci/migration/circleci.md b/doc/ci/migration/circleci.md index 9d20a16432c..df5cbc660e4 100644 --- a/doc/ci/migration/circleci.md +++ b/doc/ci/migration/circleci.md @@ -285,7 +285,7 @@ Self-managed runners: - Windows - macOS -GitLab.com shared runners: +GitLab.com instance runners: - Linux - [Windows](../runners/saas/windows_saas_runner.md) ([Beta](../../policy/experiment-beta-support.md#beta)). diff --git a/doc/ci/migration/examples/jenkins-maven.md b/doc/ci/migration/examples/jenkins-maven.md index 858f0272502..f7e58c51ed8 100644 --- a/doc/ci/migration/examples/jenkins-maven.md +++ b/doc/ci/migration/examples/jenkins-maven.md @@ -159,7 +159,7 @@ It also increases flexibility for expanding and extending the functionality of t Prerequisites: - A GitLab Runner with the Docker executor that can be used by the project. - If you are using GitLab.com, you can use the public shared runners. + If you are using GitLab.com, you can use the public instance runners. This migrated pipeline configuration consists of three global keywords (`stages`, `default`, and `variables`) followed by 3 jobs. This configuration makes use of additional GitLab CI/CD features diff --git a/doc/ci/migration/github_actions.md b/doc/ci/migration/github_actions.md index a427227c92a..ed9a210fec4 100644 --- a/doc/ci/migration/github_actions.md +++ b/doc/ci/migration/github_actions.md @@ -464,7 +464,7 @@ deploy_staging: #### Runners Runners are the services that execute jobs. If you are using GitLab.com, you can use the -[shared runner fleet](../runners/index.md) to run jobs without provisioning your own self-managed runners. +[instance runner fleet](../runners/index.md) to run jobs without provisioning your own self-managed runners. Some key details about runners: diff --git a/doc/ci/migration/jenkins.md b/doc/ci/migration/jenkins.md index 3783c476cde..450d7f42c87 100644 --- a/doc/ci/migration/jenkins.md +++ b/doc/ci/migration/jenkins.md @@ -475,7 +475,7 @@ deploy_staging: #### Runners Like Jenkins agents, GitLab runners are the hosts that run jobs. If you are using GitLab.com, -you can use the [shared runner fleet](../runners/index.md) to run jobs without provisioning +you can use the [instance runner fleet](../runners/index.md) to run jobs without provisioning your own runners. To convert a Jenkins agent for use with GitLab CI/CD, uninstall the agent and then diff --git a/doc/ci/pipelines/cicd_minutes.md b/doc/ci/pipelines/cicd_minutes.md index 13d4b2e2311..e74c38533ff 100644 --- a/doc/ci/pipelines/cicd_minutes.md +++ b/doc/ci/pipelines/cicd_minutes.md @@ -17,7 +17,7 @@ NOTE: The term `CI/CD minutes` is being renamed to `compute minutes`. During this transition, you might see references in the UI and documentation to `CI/CD minutes`, `CI minutes`, `pipeline minutes`, `CI pipeline minutes`, `pipeline minutes quota`, `compute credits`, `compute units`, and `compute minutes`. For more information, see [epic 2150](https://gitlab.com/groups/gitlab-com/-/epics/2150). Administrators can limit the amount of time that projects can use to run jobs on -[shared runners](../runners/runners_scope.md#shared-runners) each month. This limit +[instance runners](../runners/runners_scope.md#instance-runners) each month. This limit is tracked with a compute quota. By default, one minute of execution time by a single job uses @@ -106,7 +106,7 @@ Prerequisites: ### View Usage Quota Reports for a group -> - Displaying shared runners duration per project [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/355666) in GitLab 15.0. +> - Displaying instance runners duration per project [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/355666) in GitLab 15.0. Prerequisites: @@ -119,13 +119,13 @@ To view compute usage for your group: 1. Select **Settings > Usage Quotas**. 1. Select the **Pipelines** tab. -The projects list shows projects with compute usage or shared runners usage +The projects list shows projects with compute usage or instance runners usage in the current month only. The list includes all projects in the namespace and its subgroups, sorted in descending order of compute usage. ### View Usage Quota reports for a personal namespace -> - Displaying shared runners duration [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345795) in GitLab 15.0. +> - Displaying instance runners duration [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/345795) in GitLab 15.0. Prerequisites: @@ -138,7 +138,7 @@ You can view the compute usage for a personal namespace: 1. On the left sidebar, select **Usage Quotas**. The projects list shows [personal projects](../../user/project/working_with_projects.md#view-personal-projects) -with compute usage or shared runners usage in the current month only. The list +with compute usage or instance runners usage in the current month only. The list is sorted in descending order of compute usage. ## Purchase additional compute minutes @@ -221,7 +221,7 @@ GitLab uses this formula to calculate the compute usage of a job: Job duration * Cost factor ``` -- **Job duration**: The time, in seconds, that a job took to run on a shared runner, +- **Job duration**: The time, in seconds, that a job took to run on a instance runner, not including time spent in the `created` or `pending` statuses. - [**Cost factor**](#cost-factor): A number based on project visibility. @@ -241,7 +241,7 @@ can be higher than the end-to-end duration of a pipeline. ### Cost factor -The cost factors for jobs running on shared runners on GitLab.com are: +The cost factors for jobs running on instance runners on GitLab.com are: - `1` for internal, public, and private projects. - Exceptions for public projects: @@ -257,8 +257,8 @@ The cost factors on self-managed instances are: #### Cost factor for community contributions to GitLab projects -Community contributors can use up to 300,000 minutes on shared runners when contributing to open source projects -maintained by GitLab. The maximum of 300,000 minutes would only be possible if contributing exclusively to projects [part of the GitLab product](https://handbook.gitlab.com/handbook/engineering/metrics/#projects-that-are-part-of-the-product). The total number of minutes available on shared runners +Community contributors can use up to 300,000 minutes on instance runners when contributing to open source projects +maintained by GitLab. The maximum of 300,000 minutes would only be possible if contributing exclusively to projects [part of the GitLab product](https://handbook.gitlab.com/handbook/engineering/metrics/#projects-that-are-part-of-the-product). The total number of minutes available on instance runners is reduced by the compute minutes used by pipelines from other projects. The 300,000 minutes applies to all SaaS tiers, and the cost factor calculation is: @@ -297,7 +297,7 @@ GitLab SaaS runners have different cost factors, depending on the runner type (L ### Monthly reset of compute usage On the first day of each calendar month, the accumulated compute usage is reset to `0` -for all namespaces that use shared runners. This means your full quota is available, and +for all namespaces that use instance runners. This means your full quota is available, and calculations start again from `0`. For example, if you have a monthly quota of `10,000` compute minutes: @@ -327,7 +327,7 @@ Additional compute minutes are a one-time purchase and do not renew or refresh e When the compute quota is used for the current month, GitLab stops processing new jobs. -- Any non-running job that should be picked by shared runners is automatically dropped. +- Any non-running job that should be picked by instance runners is automatically dropped. - Any job being retried is automatically dropped. - Any running job can be dropped at any point if the overall namespace usage goes over-quota by a grace period. @@ -349,7 +349,7 @@ On GitLab SaaS an in-app banner is displayed and an email notification sent to t In some cases, the quota limit is replaced by one of the following labels: - **Unlimited**: For namespaces with unlimited compute quota. -- **Not supported**: For namespaces where active shared runners are not enabled. +- **Not supported**: For namespaces where active instance runners are not enabled. ## Reduce compute quota usage diff --git a/doc/ci/quick_start/index.md b/doc/ci/quick_start/index.md index 83134519623..518937ba521 100644 --- a/doc/ci/quick_start/index.md +++ b/doc/ci/quick_start/index.md @@ -30,7 +30,7 @@ To create and run your first pipeline: 1. [Ensure you have runners available](#ensure-you-have-runners-available) to run your jobs. - If you're using GitLab.com, you can skip this step. GitLab.com provides shared runners for you. + If you're using GitLab.com, you can skip this step. GitLab.com provides instance runners for you. 1. [Create a `.gitlab-ci.yml` file](#create-a-gitlab-ciyml-file) at the root of your repository. This file is where you define the CI/CD jobs. diff --git a/doc/ci/runners/configure_runners.md b/doc/ci/runners/configure_runners.md index 03c572516e3..bf696f71a62 100644 --- a/doc/ci/runners/configure_runners.md +++ b/doc/ci/runners/configure_runners.md @@ -21,13 +21,13 @@ 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. -### For a shared runner +### For an instance runner Prerequisites: - You must be an administrator. -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. +On GitLab.com, you cannot override the job timeout for instance 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: @@ -131,28 +131,28 @@ job-artifact-upload-on-timeout: ## Protecting sensitive information To avoid exposing sensitive information, you can restrict the usage -of shared runners on large GitLab instances. This ensures that you +of instance 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/). 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 who runs jobs -on a _shared runner_ can access another user's code that runs on the runner. +on an _instance 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 a runner and submit false jobs in a vector attack. For more information, see [Security Considerations](https://docs.gitlab.com/runner/security/). -### Using shared runners in forked projects +### Using instance runners in forked projects -When a project is forked, the job settings related to jobs are copied. If you have shared runners -configured for a project and a user forks that project, the shared runners serve jobs of this project. +When a project is forked, the job settings related to jobs are copied. If you have instance runners +configured for a project and a user forks that project, the instance runners serve jobs of this project. Due to a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/364303), if the runner settings of the forked project does not match the new project namespace, the following message displays: `An error occurred while forking the project. Please try again.`. -To work around this issue, ensure that the shared runner settings are consistent in the forked project and the new namespace. +To work around this issue, ensure that the instance runner settings are consistent in the forked project and the new namespace. -- If shared runners are **enabled** on the forked project, then this should also be **enabled** on the new namespace. -- If shared runners are **disabled** on the forked project, then this should also be **disabled** on the new namespace. +- If instance runners are **enabled** on the forked project, then this should also be **enabled** on the new namespace. +- If instance runners are **disabled** on the forked project, then this should also be **disabled** on the new namespace. ### Reset the runner registration token for a project (deprecated) @@ -202,11 +202,11 @@ If a runner authentication token is revealed, an attacker could use the token to To reset the runner authentication token: 1. Delete the runner: - - [Delete a shared runner](runners_scope.md#delete-shared-runners). + - [Delete an instance runner](runners_scope.md#delete-instance-runners). - [Delete a group runner](runners_scope.md#delete-a-group-runner). - [Delete a project runner](runners_scope.md#delete-a-project-runner). 1. Create a new runner so that it is assigned a new runner authentication token: - - [Create a shared runner](runners_scope.md#create-a-shared-runner-with-a-runner-authentication-token). + - [Create an instance runner](runners_scope.md#create-an-instance-runner-with-a-runner-authentication-token). - [Create a group runner](runners_scope.md#create-a-group-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). @@ -238,7 +238,7 @@ on [protected branches](../../user/project/protected_branches.md), or jobs that Runners configured to run jobs on protected branches cannot run jobs in [merge request pipelines](../pipelines/merge_request_pipelines.md). -### For a shared runner +### For an instance runner Prerequisites: @@ -284,7 +284,7 @@ Rails test suites. GitLab CI/CD tags are different to Git tags. GitLab CI/CD tags are associated with runners. Git tags are associated with commits. -### For a shared runner +### For an instance runner Prerequisites: @@ -863,9 +863,9 @@ variables: You can set them globally or per-job in the [`variables`](../yaml/index.md#variables) section. -## System calls not available on GitLab.com shared runners +## System calls not available on GitLab.com instance runners -GitLab.com shared runners run on CoreOS. This means that you cannot use some system calls, like `getlogin`, from the C standard library. +GitLab.com instance runners run on CoreOS. This means that you cannot use some system calls, like `getlogin`, from the C standard library. ## Artifact and cache settings diff --git a/doc/ci/runners/new_creation_workflow.md b/doc/ci/runners/new_creation_workflow.md index e4e195bebb4..b4b5dec84ba 100644 --- a/doc/ci/runners/new_creation_workflow.md +++ b/doc/ci/runners/new_creation_workflow.md @@ -63,7 +63,7 @@ workflow will break. To avoid a broken workflow, you must: -1. [Create a shared runner](runners_scope.md#create-a-shared-runner-with-a-runner-authentication-token) and obtain the authentication token. +1. [Create an instance runner](runners_scope.md#create-an-instance-runner-with-a-runner-authentication-token) and obtain the authentication token. 1. Replace the registration token in your runner registration workflow with the authentication token. diff --git a/doc/ci/runners/runners_scope.md b/doc/ci/runners/runners_scope.md index bb446d545c4..b6d1c52fc87 100644 --- a/doc/ci/runners/runners_scope.md +++ b/doc/ci/runners/runners_scope.md @@ -12,32 +12,31 @@ DETAILS: GitLab Runner has the following types of runners, which are available based on who you want to have access: -- [Shared runners](#shared-runners) are available to all groups and projects in a GitLab instance. +- [Instance runners](#instance-runners) are available to all groups and projects in a GitLab instance. - [Group runners](#group-runners) are available to all projects and subgroups in a group. - [Project runners](#project-runners) are associated with specific projects. Typically, project runners are used by one project at a time. -## Shared runners +## Instance runners -*Shared runners* are available to every project in a GitLab instance. +*Instance runners* are available to every project in a GitLab instance. -Use shared runners when you have multiple jobs with similar requirements. Rather than +Use instance runners when you have multiple jobs with similar requirements. Rather than having multiple runners idling for many projects, you can have a few runners that handle multiple projects. -If you are using a self-managed instance of GitLab: +If you are using a self-managed instance of GitLab, administrators can: -- Your administrator can [install GitLab Runner](https://docs.gitlab.com/runner/install/index.html) and register a shared runner. -- The administrator can also configure a maximum number of shared runner - [compute minutes for each group](../pipelines/cicd_minutes.md#set-the-compute-quota-for-a-specific-namespace). +- [Install GitLab Runner](https://docs.gitlab.com/runner/install/index.html) and register an instance runner. +- Configure a maximum number of instance runner [compute minutes for each group](../pipelines/cicd_minutes.md#set-the-compute-quota-for-a-specific-namespace). If you are using GitLab.com: -- You can select from a list of [shared runners that GitLab maintains](index.md). -- The shared runners consume the [compute minutes](../pipelines/cicd_minutes.md) +- You can select from a list of [instance runners that GitLab maintains](index.md). +- The instance runners consume the [compute minutes](../pipelines/cicd_minutes.md) included with your account. -### Create a shared runner with a runner authentication token +### Create an instance runner with a runner authentication token > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/383139) in GitLab 15.10. Deployed behind the `create_runner_workflow_for_admin` [flag](../../administration/feature_flags.md) > - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/389269) in GitLab 16.0. @@ -49,7 +48,7 @@ Prerequisites: When you create a runner, it is assigned a runner authentication token that you use to register it. The runner uses the token to authenticate with GitLab when picking up jobs from the job queue. -To create a shared runner: +To create an instance runner: 1. On the left sidebar, at the bottom, select **Admin Area**. 1. Select **CI/CD > Runners**. @@ -73,7 +72,7 @@ NOTE: The runner authentication token displays in the UI for a limited period of time during registration. After you register the runner, the authentication token is stored in the `config.toml`. -### Create a shared runner with a registration token (deprecated) +### Create an instance runner with a registration token (deprecated) WARNING: The ability to pass a runner registration token, and support for certain configuration arguments was @@ -84,7 +83,7 @@ Prerequisites: - You must be an administrator. -To create a shared runner: +To create an instance runner: 1. On the left sidebar, at the bottom, select **Admin Area**. 1. Select **CI/CD > Runners**. @@ -92,7 +91,7 @@ To create a shared runner: 1. Copy the registration token. 1. [Register the runner](https://docs.gitlab.com/runner/register/#register-with-a-runner-registration-token-deprecated). -### Pause or resume a shared runner +### Pause or resume an instance runner Prerequisites: @@ -107,92 +106,92 @@ You can pause a runner so that it does not accept jobs from groups and projects - To pause the runner, select **Pause** (**{pause}**). - To resume the runner, select **Resume** (**{play}**). -### Delete shared runners +### Delete instance runners Prerequisites: - You must be an administrator. -When you delete a shared runner, it is permanently deleted from the GitLab instance and can +When you delete an instance runner, it is permanently deleted from the GitLab instance and can no longer be used by groups and projects. If you want to temporarily stop the runner from accepting -jobs, you can [pause](#pause-or-resume-a-shared-runner) the runner instead. +jobs, you can [pause](#pause-or-resume-an-instance-runner) the runner instead. -To delete a single or multiple shared runners: +To delete a single or multiple instance runners: 1. On the left sidebar, at the bottom, select **Admin Area**. 1. Select **CI/CD > Runners**. 1. In the search box, enter the runner description or filter the list of runners. -1. Delete the shared runner: +1. Delete the instance runner: - To delete a single runner, next to the runner, select **Delete runner** (**{remove}**). - - To delete multiple shared runners, select the checkbox for each runner and select **Delete selected**. + - To delete multiple instance runners, select the checkbox for each runner and select **Delete selected**. - To delete all runners, select the checkbox at the top of the runner list and select **Delete selected**. 1. Select **Permanently delete runner**. -### Enable shared runners for a project +### Enable instance runners for a project -On GitLab.com, [shared runners](index.md) are enabled in all projects by +On GitLab.com, [instance runners](index.md) are enabled in all projects by default. On self-managed instances of GitLab, an administrator can -[enable them for all new projects](../../administration/settings/continuous_integration.md#enable-shared-runners-for-new-projects). +[enable them for all new projects](../../administration/settings/continuous_integration.md#enable-instance-runners-for-new-projects). For existing projects, an administrator must [install](https://docs.gitlab.com/runner/install/index.html) and [register](https://docs.gitlab.com/runner/register/index.html) them. -To enable shared runners for a project: +To enable instance runners for a project: 1. On the left sidebar, select **Search or go to** and find your project. 1. Select **Settings > CI/CD**. 1. Expand **Runners**. -1. Turn on the **Enable shared runners for this project** toggle. +1. Turn on the **Enable instance runners for this project** toggle. -### Enable shared runners for a group +### Enable instance runners for a group -To enable shared runners for a group: +To enable instance runners for a group: 1. On the left sidebar, select **Search or go to** and find your group. 1. Select **Settings > CI/CD**. 1. Expand **Runners**. -1. Turn on the **Enable shared runners for this group** toggle. +1. Turn on the **Enable instance runners for this group** toggle. -### Disable shared runners for a project +### Disable instance runners for a project -You can disable shared runners for individual projects or for groups. +You can disable instance runners for individual projects or for groups. You must have the Owner role for the project or group. -To disable shared runners for a project: +To disable instance runners for a project: 1. On the left sidebar, select **Search or go to** and find your project. 1. Select **Settings > CI/CD**. 1. Expand **Runners**. -1. In the **Shared runners** area, turn off the **Enable shared runners for this project** toggle. +1. In the **Instance runners** area, turn off the **Enable instance runners for this project** toggle. -Shared runners are automatically disabled for a project: +instance runners are automatically disabled for a project: -- If the shared runners setting for the parent group is disabled, and +- If the instance runners setting for the parent group is disabled, and - If overriding this setting is not permitted at the project level. -### Disable shared runners for a group +### Disable instance runners for a group -To disable shared runners for a group: +To disable instance runners for a group: 1. On the left sidebar, select **Search or go to** and find your group. 1. Select **Settings > CI/CD**. 1. Expand **Runners**. -1. Turn off the **Enable shared runners for this group** toggle. -1. Optional. To allow shared runners to be enabled for individual projects or subgroups, +1. Turn off the **Enable instance runners for this group** toggle. +1. Optional. To allow instance runners to be enabled for individual projects or subgroups, select **Allow projects and subgroups to override the group setting**. -### How shared runners pick jobs +### How instance runners pick jobs -Shared runners process jobs by using a fair usage queue. This queue prevents +Instance runners process jobs by using a fair usage queue. This queue prevents projects from creating hundreds of jobs and using all available -shared runner resources. +instance runner resources. The fair usage queue algorithm assigns jobs based on the projects that have the -fewest number of jobs already running on shared runners. +fewest number of jobs already running on instance runners. For example, if these jobs are in the queue: @@ -314,7 +313,7 @@ those that are inherited from the instance or other groups. By default, only those that are inherited are shown. -To show all runners available in the instance, including shared runners and +To show all runners available in the instance, including instance runners and those in other groups: 1. On the left sidebar, select **Search or go to** and find your group. @@ -356,7 +355,7 @@ To delete a single or multiple group runners: 1. In the search box, enter the runner description or filter the list of runners. 1. Delete the group runner: - To delete a single runner, next to the runner, select **Delete runner** (**{remove}**). - - To delete multiple shared runners, select the checkbox for each runner and select **Delete selected**. + - To delete multiple instance runners, select the checkbox for each runner and select **Delete selected**. - To delete all runners, select the checkbox at the top of the runner list and select **Delete selected**. 1. Select **Permanently delete runner**. @@ -424,7 +423,7 @@ must be enabled for each project explicitly. Project runners process jobs by using a first in, first out ([FIFO](https://en.wikipedia.org/wiki/FIFO_(computing_and_electronics))) queue. NOTE: -Project runners do not get shared with forked projects automatically. +Project runners do not get instance with forked projects automatically. A fork *does* copy the CI/CD settings of the cloned repository. ### Create a project runner with a runner authentication token @@ -562,7 +561,7 @@ To lock or unlock a project runner: find the project where you want to enable the runner. 1. Select **Settings > CI/CD**. 1. Expand **Runners**. -1. Find the project runner you want to lock or unlock. Make sure it's enabled. You cannot lock shared or group runners. +1. Find the project runner you want to lock or unlock. Make sure it's enabled. You cannot lock instance or group runners. 1. Select **Edit** (**{pencil}**). 1. Select the **Lock to current projects** checkbox. 1. Select **Save changes**. @@ -638,22 +637,22 @@ the source of the HTTP requests it makes to GitLab when polling for jobs. The IP address is always kept up to date so if the runner IP changes it automatically updates in GitLab. -The IP address for shared runners and project runners can be found in +The IP address for instance runners and project runners can be found in different places. -### Determine the IP address of a shared runner +### Determine the IP address of an instance runner Prerequisites: - You must have administrator access to the instance. -To determine the IP address of a shared runner: +To determine the IP address of an instance runner: 1. On the left sidebar, at the bottom, select **Admin Area**. 1. Select **CI/CD > Runners**. 1. Find the runner in the table and view the **IP Address** column. -![shared runner IP address](img/shared_runner_ip_address_14_5.png) +![Instance runner IP address](img/shared_runner_ip_address_14_5.png) ### Determine the IP address of a project runner diff --git a/doc/ci/services/mysql.md b/doc/ci/services/mysql.md index 8c771ef4d39..451f9ab46f1 100644 --- a/doc/ci/services/mysql.md +++ b/doc/ci/services/mysql.md @@ -131,5 +131,5 @@ GitLab Runner with the Shell executor. ## Example project To view a MySQL example, create a fork of this [sample project](https://gitlab.com/gitlab-examples/mysql). -This project uses publicly-available [shared runners](../runners/index.md) on [GitLab.com](https://gitlab.com). +This project uses publicly-available [instance runners](../runners/index.md) on [GitLab.com](https://gitlab.com). Update the README.md file, commit your changes, and view the CI/CD pipeline to see it in action. diff --git a/doc/ci/services/postgres.md b/doc/ci/services/postgres.md index bad0433cf10..f1eceff3e80 100644 --- a/doc/ci/services/postgres.md +++ b/doc/ci/services/postgres.md @@ -146,7 +146,7 @@ Database: nice_marmot We have set up an [Example PostgreSQL Project](https://gitlab.com/gitlab-examples/postgres) for your convenience that runs on [GitLab.com](https://gitlab.com) using our publicly -available [shared runners](../runners/index.md). +available [instance runners](../runners/index.md). Want to hack on it? Fork it, commit, and push your changes. Within a few moments the changes are picked by a public runner and the job begins. diff --git a/doc/ci/services/redis.md b/doc/ci/services/redis.md index c46b0e3fe25..d5c113309f9 100644 --- a/doc/ci/services/redis.md +++ b/doc/ci/services/redis.md @@ -70,7 +70,7 @@ Host: localhost We have set up an [Example Redis Project](https://gitlab.com/gitlab-examples/redis) for your convenience that runs on [GitLab.com](https://gitlab.com) using our publicly available -[shared runners](../runners/index.md). +[instance runners](../runners/index.md). Want to hack on it? Fork it, commit and push your changes. Within a few moments the changes are picked by a public runner and the job begins. diff --git a/doc/ci/testing/code_quality.md b/doc/ci/testing/code_quality.md index 73c3863eadf..92da8ff5604 100644 --- a/doc/ci/testing/code_quality.md +++ b/doc/ci/testing/code_quality.md @@ -105,7 +105,7 @@ The project quality view displays an overview of the code quality findings. The Prerequisites: - GitLab CI/CD configuration (`.gitlab-ci.yml`) must include the `test` stage. -- If you're using shared runners, the Code Quality job must be configured for the +- If you're using instance runners, the Code Quality job must be configured for the [Docker-in-Docker workflow](../docker/using_docker_build.md#use-docker-in-docker). - If you're using private runners, you should use an [alternative configuration](#improve-code-quality-performance-with-private-runners) diff --git a/doc/development/fips_compliance.md b/doc/development/fips_compliance.md index 7acdb8486d4..807414b49d9 100644 --- a/doc/development/fips_compliance.md +++ b/doc/development/fips_compliance.md @@ -66,7 +66,6 @@ listed here that also do not work properly in FIPS mode: supports a reduced set of [analyzers](../user/application_security/sast/index.md#fips-enabled-images) when operating in FIPS-compliant mode. - Advanced search is currently not included in FIPS mode. It must not be enabled to be FIPS-compliant. -- [Gravatar or Libravatar-based profile images](../administration/libravatar.md) are not FIPS-compliant. - [Operational Container Scanning](../user/clusters/agent/vulnerabilities.md). Additionally, these package repositories are disabled in FIPS mode: diff --git a/doc/development/gitlab_flavored_markdown/specification_guide/index.md b/doc/development/gitlab_flavored_markdown/specification_guide/index.md index f8097d48739..3ee2adb0241 100644 --- a/doc/development/gitlab_flavored_markdown/specification_guide/index.md +++ b/doc/development/gitlab_flavored_markdown/specification_guide/index.md @@ -691,7 +691,7 @@ subgraph input E((GLFM static
renderer implementation)) --> B F((GLFM WYSIWYG
renderer implementation)) --> B end -subgraph output:
test results/output +subgraph "output:
test results/output" C --> G[spec_tests.py output] end ``` @@ -760,10 +760,10 @@ end subgraph script: A{run-snapshopt-tests.sh} -->|invokes| B end -subgraph output:
test results/output +subgraph "output:
test results/output" B --> H[rspec+jest output] end -subgraph input:
YAML +subgraph "input:
YAML" C[examples_index.yml] --> B D[markdown.yml] --> B E[html.yml] --> B diff --git a/doc/development/semver.md b/doc/development/semver.md index 4a591e46cdb..cd7aac5c5d7 100644 --- a/doc/development/semver.md +++ b/doc/development/semver.md @@ -56,6 +56,15 @@ Depending on the use case, you may want to disable the validation during the rol Please refer to [this MR](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142228) as a reference. +## Sorting + +The concern provides two scopes to sort by semantic versions: + +```ruby +scope :order_by_semantic_version_desc, -> { order(semver_major: :desc, semver_minor: :desc, semver_patch: :desc)} +scope :order_by_semantic_version_asc, -> { order(semver_major: :asc, semver_minor: :asc, semver_patch: :asc)} +``` + ## Filtering and Searching TBD diff --git a/doc/subscriptions/bronze_starter.md b/doc/subscriptions/bronze_starter.md index e1c5bbcadc2..d69bf6b2d52 100644 --- a/doc/subscriptions/bronze_starter.md +++ b/doc/subscriptions/bronze_starter.md @@ -94,7 +94,7 @@ the tiers are no longer mentioned in GitLab documentation: - [Mirror with Perforce Helix with Git Fusion](../user/project/repository/mirror/bidirectional.md#mirror-with-perforce-helix-with-git-fusion) - Runners: - Run pipelines in the parent project [for merge requests from a forked project](../ci/pipelines/merge_request_pipelines.md#run-pipelines-in-the-parent-project) - - [Shared runners compute quota](../ci/pipelines/cicd_minutes.md) + - [Instance runners compute quota](../ci/pipelines/cicd_minutes.md) - [Push rules](../user/project/repository/push_rules.md) - SAML for self-managed GitLab instance: - [Administrator groups](../integration/saml.md#administrator-groups) diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md index 9d475bc03fe..a624b7b9577 100644 --- a/doc/subscriptions/gitlab_com/index.md +++ b/doc/subscriptions/gitlab_com/index.md @@ -390,7 +390,7 @@ To add a secondary contact for your subscription: ## Compute Compute is the resource consumed when running [pipelines](../../ci/pipelines/index.md) -on GitLab shared runners. +on GitLab instance runners. Refer to [Compute usage](../../ci/pipelines/cicd_minutes.md) for more information. diff --git a/doc/topics/autodevops/requirements.md b/doc/topics/autodevops/requirements.md index 403fb864a4d..6a2f8dfff4d 100644 --- a/doc/topics/autodevops/requirements.md +++ b/doc/topics/autodevops/requirements.md @@ -138,7 +138,7 @@ To make full use of Auto DevOps with Kubernetes, you need: You can configure Docker-based runners to autoscale as well, using [Docker Machine](https://docs.gitlab.com/runner/executors/docker_machine.html). - Runners should be registered as [shared runners](../../ci/runners/runners_scope.md#shared-runners) + Runners should be registered as [instance runners](../../ci/runners/runners_scope.md#instance-runners) for the entire GitLab instance, or [project runners](../../ci/runners/runners_scope.md#project-runners) that are assigned to specific projects. diff --git a/doc/tutorials/automate_runner_creation/index.md b/doc/tutorials/automate_runner_creation/index.md index a23870f8153..e63ab7cdf1b 100644 --- a/doc/tutorials/automate_runner_creation/index.md +++ b/doc/tutorials/automate_runner_creation/index.md @@ -28,7 +28,7 @@ method that uses registration tokens. For more information, see ## Before you begin - GitLab Runner must be installed on your GitLab instance. -- To create shared runners, you must be an administrator. +- To create instance runners, you must be an administrator. - To create group runners, you must be an administrator or have the Owner role for the group. - To create project runners, you must be an administrator or have the Maintainer role for the project. @@ -177,7 +177,7 @@ runner installation and registration. After you create a runner and its configuration, you can use the same runner authentication token to register multiple runners with the same configuration. -For example, you can deploy multiple shared runners with the same executor type +For example, you can deploy multiple instance runners with the same executor type and job tags to the target compute host. Each runner registered with the same runner authentication token has a unique `system_id`, which GitLab Runner generates randomly and stores in your local file system. diff --git a/doc/update/deprecations.md b/doc/update/deprecations.md index 6ff2b1345f7..8f31a7bc175 100644 --- a/doc/update/deprecations.md +++ b/doc/update/deprecations.md @@ -317,6 +317,29 @@ Because Cloud Native Buildpacks do not support automatic testing, the Auto Test
+### Autogenerated Markdown anchor links with dash (`-`) characters + +
+- Announced in GitLab 16.9 +- Removal in GitLab 17.0 ([breaking change](https://docs.gitlab.com/ee/update/terminology.html#breaking-change)) +- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/440733). +
+ +GitLab automatically creates anchor links for all headings, so you can link to +a specific place in a Markdown document or wiki page. But in some edge cases, +the autogenerated anchor is created with fewer dash (`-`) characters than many users expect. +For example, with a heading with `## Step - 1`, most other Markdown tools and linters would expect `#step---1`. +But GitLab generates an anchor of `#step-1`, with consecutive dashes compressed down to one. + +In GitLab 17.0, we will align our autogenerated anchors to the industry standard by no longer stripping consecutive dashes. +If you have Markdown documents and link to headings that could have multiple dashes in 17.0, +you should update the heading to avoid this edge case. With the example above, you +can change `## Step - 1` to `## Step 1` to ensure in-page links continue to work. + +
+ +
+ ### Block usage of ref and sha together in `GET /projects/:id/ci/lint`
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md index 5d88eae7194..cba060d6ed8 100644 --- a/doc/user/application_security/container_scanning/index.md +++ b/doc/user/application_security/container_scanning/index.md @@ -83,7 +83,7 @@ To enable container scanning in your pipeline, you need the following: - [GitLab Runner](https://docs.gitlab.com/runner/) with the [`docker`](https://docs.gitlab.com/runner/executors/docker.html) or [`kubernetes`](https://docs.gitlab.com/runner/install/kubernetes.html) executor on Linux/amd64. - Docker `18.09.03` or later installed on the same computer as the runner. If you're using the - shared runners on GitLab.com, then this is already the case. + instance runners on GitLab.com, then this is already the case. - An image matching the [supported distributions](#supported-distributions). - [Build and push](../../packages/container_registry/build_and_push_images.md#use-gitlab-cicd) the Docker image to your project's container registry. diff --git a/doc/user/application_security/dast/browser/configuration/variables.md b/doc/user/application_security/dast/browser/configuration/variables.md index 98c0748aa8d..30230fc457f 100644 --- a/doc/user/application_security/dast/browser/configuration/variables.md +++ b/doc/user/application_security/dast/browser/configuration/variables.md @@ -46,7 +46,7 @@ For authentication CI/CD variables, see [Authentication](authentication.md). | `DAST_BROWSER_MAX_RESPONSE_SIZE_MB` | number | `15` | The maximum size of a HTTP response body. Responses with bodies larger than this are blocked by the browser. Defaults to 10 MB. | | `DAST_BROWSER_NAVIGATION_STABILITY_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `7s` | The maximum amount of time to wait for a browser to consider a page loaded and ready for analysis after a navigation completes. Defaults to `800ms`.| | `DAST_BROWSER_NAVIGATION_TIMEOUT` | [Duration string](https://pkg.go.dev/time#ParseDuration) | `15s` | The maximum amount of time to wait for a browser to navigate from one page to another. | -| `DAST_BROWSER_NUMBER_OF_BROWSERS` | number | `3` | The maximum number of concurrent browser instances to use. For shared runners on GitLab.com, we recommended a maximum of three. Private runners with more resources may benefit from a higher number, but are likely to produce little benefit after five to seven instances. | +| `DAST_BROWSER_NUMBER_OF_BROWSERS` | number | `3` | The maximum number of concurrent browser instances to use. For instance runners on GitLab.com, we recommended a maximum of three. Private runners with more resources may benefit from a higher number, but are likely to produce little benefit after five to seven instances. | | `DAST_BROWSER_PAGE_LOADING_SELECTOR` | selector | `css:#page-is-loading` | Selector that when is no longer visible on the page, indicates to the analyzer that the page has finished loading and the scan can continue. Cannot be used with `DAST_BROWSER_PAGE_READY_SELECTOR`. | | `DAST_BROWSER_PAGE_READY_SELECTOR` | selector | `css:#page-is-ready` | Selector that when detected as visible on the page, indicates to the analyzer that the page has finished loading and the scan can continue. Cannot be used with `DAST_BROWSER_PAGE_LOADING_SELECTOR`. | | `DAST_BROWSER_PASSIVE_CHECK_WORKERS` | int | `5` | Number of workers that passive scan in parallel. Recommend setting to the number of available CPUs. | diff --git a/doc/user/crm/index.md b/doc/user/crm/index.md index d552b540c89..557eebad1b0 100644 --- a/doc/user/crm/index.md +++ b/doc/user/crm/index.md @@ -34,9 +34,11 @@ For more information about what is planned for the future, see [issue 2256](http ## Enable customer relations management (CRM) -Customer relations management features must be enabled at the group level. If your +> - [Enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/108378) in GitLab 16.9. + +Customer relations management features are enabled at the group level. If your group also contains subgroups, and you want to use CRM features in the subgroup, -you must enable CRM features for the subgroup. +CRM features must also be enabled for the subgroup. To enable customer relations management in a group or subgroup: diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md index 1feaa15e105..e49ddd68c81 100644 --- a/doc/user/gitlab_com/index.md +++ b/doc/user/gitlab_com/index.md @@ -264,7 +264,7 @@ from those IPs and allow them. GitLab.com is fronted by Cloudflare. For incoming connections to GitLab.com, you might need to allow CIDR blocks of Cloudflare ([IPv4](https://www.cloudflare.com/ips-v4/) and [IPv6](https://www.cloudflare.com/ips-v6/)). For outgoing connections from CI/CD runners, we are not providing static IP addresses. -All GitLab.com shared runners are deployed into Google Cloud Platform (GCP) in `us-east1`. +All GitLab.com instance runners are deployed into Google Cloud Platform (GCP) in `us-east1`. Any IP-based firewall can be configured by looking up [IP address ranges or CIDR blocks for GCP](https://cloud.google.com/compute/docs/faq#find_ip_range). diff --git a/doc/user/group/access_and_permissions.md b/doc/user/group/access_and_permissions.md index 33fea38633d..a725e6d6406 100644 --- a/doc/user/group/access_and_permissions.md +++ b/doc/user/group/access_and_permissions.md @@ -114,7 +114,7 @@ Keep in mind that restricting group access by IP address has the following impli ### GitLab.com access restrictions -On GitLab.com shared runners are added to the [global allowlist](../../administration/settings/visibility_and_access_controls.md#configure-globally-allowed-ip-address-ranges), so that they are available regardless of IP restrictions. +On GitLab.com instance runners are added to the [global allowlist](../../administration/settings/visibility_and_access_controls.md#configure-globally-allowed-ip-address-ranges), so that they are available regardless of IP restrictions. Artifact and Registry downloading from runners is sourced from any Google or, in the case of MacOS runners, Amazon IP address in that region. The download is therefore not added to the global allowlist. diff --git a/doc/user/group/epics/index.md b/doc/user/group/epics/index.md index e779a112b83..ad0f62a9518 100644 --- a/doc/user/group/epics/index.md +++ b/doc/user/group/epics/index.md @@ -35,7 +35,7 @@ Use epics: The possible relationships between epics and issues are: - An epic is the parent of one or more issues. -- An epic is the parent of one or more child epics. For details see [Multi-level child epics](manage_epics.md#multi-level-child-epics). +- An epic is the parent of one or more [child epics](manage_epics.md#multi-level-child-epics). Ultimate only. ```mermaid graph TD diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md index 4c5438ee1ad..55d0465901e 100644 --- a/doc/user/packages/container_registry/index.md +++ b/doc/user/packages/container_registry/index.md @@ -34,7 +34,7 @@ You can search, sort, filter, and [delete](delete_container_registry_images.md#u your container images. You can share a filtered view by copying the URL from your browser. Only members of the project or group can access the container registry for a private project. -Container images downloaded from a private registry may be [available to other users in a shared runner](https://docs.gitlab.com/runner/security/index.html#usage-of-private-docker-images-with-if-not-present-pull-policy). +Container images downloaded from a private registry may be [available to other users in an instance runner](https://docs.gitlab.com/runner/security/index.html#usage-of-private-docker-images-with-if-not-present-pull-policy). If a project is public, the container registry is also public. diff --git a/doc/user/packages/yarn_repository/index.md b/doc/user/packages/yarn_repository/index.md index 6ef206c1a60..c40862a611f 100644 --- a/doc/user/packages/yarn_repository/index.md +++ b/doc/user/packages/yarn_repository/index.md @@ -29,7 +29,7 @@ achieve. For more information, review the [guidance on tokens](../../../user/pac - If your organization uses two-factor authentication (2FA), you must use a personal access token with the scope set to `api`. - If you publish a package via CI/CD pipelines, you can use a CI job token in - private runners or you can register a variable for shared runners. + private runners or you can register a variable for instance runners. ### Publish configuration @@ -72,9 +72,9 @@ Your package should now publish to the package registry. You can use pipeline variables when you use this method. -You can use **Shared Runners** *(Default)* or **Private Runners** (Advanced). +You can use **instance runners** *(Default)* or **Private Runners** (Advanced). -#### Shared runners +#### Instance runners To create an authentication token for your project or group: diff --git a/doc/user/project/changelogs.md b/doc/user/project/changelogs.md index 12681bd2594..655abff2d77 100644 --- a/doc/user/project/changelogs.md +++ b/doc/user/project/changelogs.md @@ -92,7 +92,7 @@ To generate the changelog: and append your desired options. Some options include: - `--config-file [string]`: The path to the changelog configuration file in your project's - Git repository. Defaults to `.gitlab/changelog_config.yml`. + Git repository. This file must exist in your project's Git repository. Defaults to `.gitlab/changelog_config.yml`. - Commit range: - `--from [string]`: The start of the range of commits (as a SHA) to use for generating the changelog. This commit itself isn't included in the changelog. @@ -110,8 +110,8 @@ for definitions and usage. ## Customize the changelog output -To customize the changelog output, edit the changelog configuration file. The default -location for this configuration is `.gitlab/changelog_config.yml`. The file supports +To customize the changelog output, edit the changelog configuration file, and commit these changes to your project's Git repository. +The default location for this configuration is `.gitlab/changelog_config.yml`. The file supports these variables: - `date_format`: The date format, in `strftime` format, used in the title of the newly added changelog data. diff --git a/doc/user/project/clusters/cluster_access.md b/doc/user/project/clusters/cluster_access.md index 40961357cb7..6187e1e2168 100644 --- a/doc/user/project/clusters/cluster_access.md +++ b/doc/user/project/clusters/cluster_access.md @@ -92,5 +92,5 @@ arbitrary images as they effectively have root access. If you don't want to use a runner in privileged mode, either: -- Use shared runners on GitLab.com. They don't have this security issue. +- Use instance runners on GitLab.com. They don't have this security issue. - Set up your own runners that use [`docker+machine`](https://docs.gitlab.com/runner/executors/docker_machine.html). diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md index 0082040c28d..066a5f7f97b 100644 --- a/doc/user/project/pages/introduction.md +++ b/doc/user/project/pages/introduction.md @@ -35,7 +35,7 @@ If you are using [GitLab Pages on GitLab.com](#gitlab-pages-on-gitlabcom) to hos - The domain name for GitLab Pages on GitLab.com is `gitlab.io`. - Custom domains and TLS support are enabled. -- Shared runners are enabled by default, provided for free and can be used to +- Instance runners are enabled by default, provided for free and can be used to build your website. If you want you can still bring your own runner. ## Example projects diff --git a/doc/user/project/repository/forking_workflow.md b/doc/user/project/repository/forking_workflow.md index 7eda7658976..8a57c226876 100644 --- a/doc/user/project/repository/forking_workflow.md +++ b/doc/user/project/repository/forking_workflow.md @@ -225,8 +225,8 @@ to share objects with another repository: ### Error: `An error occurred while forking the project. Please try again` -This error can be due to a mismatch in shared runner settings between the forked project -and the new namespace. See [Forks](../../../ci/runners/configure_runners.md#using-shared-runners-in-forked-projects) +This error can be due to a mismatch in instance runner settings between the forked project +and the new namespace. See [Forks](../../../ci/runners/configure_runners.md#using-instance-runners-in-forked-projects) in the Runner documentation for more information. ### Removing fork relationship fails diff --git a/doc/user/project/settings/import_export_troubleshooting.md b/doc/user/project/settings/import_export_troubleshooting.md index 3f2b9a23f2d..35cf86b3ea0 100644 --- a/doc/user/project/settings/import_export_troubleshooting.md +++ b/doc/user/project/settings/import_export_troubleshooting.md @@ -28,12 +28,12 @@ tail /var/log/gitlab/gitlab-rails/importer.log ## Project fails to import due to mismatch -If the [shared runners enablement](../../../ci/runners/runners_scope.md#enable-shared-runners-for-a-project) +If the [instance runners enablement](../../../ci/runners/runners_scope.md#enable-instance-runners-for-a-project) does not match between the exported project, and the project import, the project fails to import. Review [issue 276930](https://gitlab.com/gitlab-org/gitlab/-/issues/276930), and either: -- Ensure shared runners are enabled in both the source and destination projects. -- Disable shared runners on the parent group when you import the project. +- Ensure instance runners are enabled in both the source and destination projects. +- Disable instance runners on the parent group when you import the project. ## Users missing from imported project diff --git a/lib/bulk_imports/ndjson_pipeline.rb b/lib/bulk_imports/ndjson_pipeline.rb index 07118c3b55c..e817bfe8034 100644 --- a/lib/bulk_imports/ndjson_pipeline.rb +++ b/lib/bulk_imports/ndjson_pipeline.rb @@ -136,7 +136,8 @@ module BulkImports pipeline_class: tracker.pipeline_name, exception_class: 'RecordInvalid', exception_message: record.errors.full_messages.to_sentence, - correlation_id_value: Labkit::Correlation::CorrelationId.current_or_new_id + correlation_id_value: Labkit::Correlation::CorrelationId.current_or_new_id, + subrelation: record.class.to_s ) end end diff --git a/lib/gitlab/database/partitioning/list/convert_table.rb b/lib/gitlab/database/partitioning/list/convert_table.rb index 8819c916ce6..41df83e4d2f 100644 --- a/lib/gitlab/database/partitioning/list/convert_table.rb +++ b/lib/gitlab/database/partitioning/list/convert_table.rb @@ -200,7 +200,7 @@ module Gitlab end def attach_foreign_keys_to_parent - migration_context.foreign_keys(table_name).each do |fk| + Gitlab::Database::PostgresForeignKey.by_constrained_table_name(table_name).not_inherited.each do |fk| # At this point no other connection knows about the parent table. # Thus the only contended lock in the following transaction is on fk.to_table. # So a deadlock is impossible. @@ -209,14 +209,22 @@ module Gitlab # If we're rerunning this migration after a failure to acquire a lock, the foreign key might already exist # Don't try to recreate it in that case - if migration_context.foreign_keys(parent_table_name) - .any? { |p_fk| p_fk.options[:name] == fk.options[:name] } - next - end + next if Gitlab::Database::PostgresForeignKey + .by_constrained_table_name(parent_table_name) + .not_inherited + .any? { |p_fk| p_fk.name == fk.name } - migration_context.with_lock_retries(raise_on_exhaustion: true) do - migration_context.add_foreign_key(parent_table_name, fk.to_table, **fk.options) - end + migration_context.add_concurrent_foreign_key( + parent_table_name, + fk.referenced_table_name, + name: fk.name, + column: fk.constrained_columns, + target_column: fk.referenced_columns, + on_delete: fk.on_delete_action == "no_action" ? nil : fk.on_delete_action.to_sym, + on_update: fk.on_update_action == "no_action" ? nil : fk.on_update_action.to_sym, + validate: true, + allow_partitioned: true + ) end end diff --git a/lib/gitlab/import_export/project/import_export.yml b/lib/gitlab/import_export/project/import_export.yml index d34cab5ac92..f42cd37b00d 100644 --- a/lib/gitlab/import_export/project/import_export.yml +++ b/lib/gitlab/import_export/project/import_export.yml @@ -1233,6 +1233,7 @@ ee: - :commit_committer_check - :regexp_uses_re2 - :reject_non_dco_commits + - :organization unprotect_access_levels: - :access_level - :user_id diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 58c95b96840..cf4e5b3ae86 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -2728,6 +2728,9 @@ msgstr "" msgid "Achievements|Awarded %{timeAgo} by a private namespace" msgstr "" +msgid "Achievements|There are currently no achievements." +msgstr "" + msgid "Achievements|View your achievements on your %{link_start}profile%{link_end}." msgstr "" @@ -39193,7 +39196,7 @@ msgstr "" msgid "ProjectSettings|Storage name:" msgstr "" -msgid "ProjectSettings|Store custom configuration files." +msgid "ProjectSettings|Store configuration files for custom dashboards and visualizations." msgstr "" msgid "ProjectSettings|Submit changes to be merged upstream." @@ -39522,15 +39525,15 @@ msgstr "" msgid "ProjectsNew|Create new project" msgstr "" -msgid "ProjectsNew|Default hashing algorithm is SHA-1." -msgstr "" - msgid "ProjectsNew|Description format" msgstr "" msgid "ProjectsNew|Enable Static Application Security Testing (SAST)" msgstr "" +msgid "ProjectsNew|Experimental settings" +msgstr "" + msgid "ProjectsNew|Group name" msgstr "" @@ -39546,6 +39549,9 @@ msgstr "" msgid "ProjectsNew|Initialize repository with a README" msgstr "" +msgid "ProjectsNew|Might break existing functionality with other repositories or APIs. It's not possible to change SHA-256 repositories back to the default SHA-1 hashing algorithm." +msgstr "" + msgid "ProjectsNew|Migrate your data from an external source like GitHub, Bitbucket, or another instance of GitLab." msgstr "" @@ -39588,7 +39594,7 @@ msgstr "" msgid "ProjectsNew|Unable to suggest a path. Please refresh and try again." msgstr "" -msgid "ProjectsNew|Use SHA-256 as the repository hashing algorithm" +msgid "ProjectsNew|Use SHA-256 for repository hashing algorithm" msgstr "" msgid "ProjectsNew|Visibility Level" @@ -44370,6 +44376,9 @@ msgstr "" msgid "SecurityConfiguration|Vulnerability details and statistics in the merge request" msgstr "" +msgid "SecurityOrchestraation|(Formerly Scan result policy)" +msgstr "" + msgid "SecurityOrchestration| and " msgstr "" @@ -44891,6 +44900,12 @@ msgstr "" msgid "SecurityOrchestration|Summary" msgstr "" +msgid "SecurityOrchestration|The %{oldNameStart}Scan result policy%{oldNameEnd} is now called the %{newNameStart}Merge request approval policy%{newNameEnd} to better align with its purpose. For more details, see the release notes." +msgstr "" + +msgid "SecurityOrchestration|The Scan result policy is now called the Merge request approval policy to better align with its purpose. For more details, see the release notes." +msgstr "" + msgid "SecurityOrchestration|The following branches do not exist on this development project: %{branches}. Please review all protected branches to ensure the values are accurate before updating this policy." msgstr "" @@ -44951,6 +44966,9 @@ msgstr "" msgid "SecurityOrchestration|Update scan policies" msgstr "" +msgid "SecurityOrchestration|Updated policy name" +msgstr "" + msgid "SecurityOrchestration|Use a merge request approval policy to create rules that check for security vulnerabilities and license compliance before merging a merge request." msgstr "" diff --git a/spec/components/pajamas/accordion_item_component_spec.rb b/spec/components/pajamas/accordion_item_component_spec.rb new file mode 100644 index 00000000000..10aef4a44ad --- /dev/null +++ b/spec/components/pajamas/accordion_item_component_spec.rb @@ -0,0 +1,59 @@ +# frozen_string_literal: true + +require "spec_helper" + +RSpec.describe Pajamas::AccordionItemComponent, type: :component, feature_category: :shared do + let(:title) { "This is a title" } + let(:content) { "This is the content" } + let(:state) { :opened } + + before do + render_inline(described_class.new(title: title, state: state)) do |_c| + content + end + end + + describe "title param" do + it "is shown inside the accordion" do + expect(page).to have_button(title) + end + end + + describe "content" do + it "is shown inside the accordion" do + expect(page).to have_css ".accordion-item", text: content + end + end + + describe "state (opened) param" do + it "renders the show class" do + expect(page).to have_selector('.show') + end + + it "renders a chevron-down icon" do + expect(page).to have_selector('[data-testid="chevron-down-icon"]') + end + + it "renders a button with the correct aria-expanded value" do + expect(page).to have_selector('button[aria-expanded="true"]') + end + end + + describe "state (closed) param" do + before do + render_inline(described_class.new(title: title, state: :closed)) + end + + it "does not render the show class" do + expect(page).not_to have_selector('.show') + end + + it "renders a chevron-right icon" do + expect(page).to have_selector('[data-testid="chevron-right-icon"]') + end + + it "renders a button with the correct aria-expanded value" do + expect(page).to have_selector('button[aria-expanded="false"]') + end + end +end diff --git a/spec/components/previews/pajamas/accordion_component_preview.rb b/spec/components/previews/pajamas/accordion_component_preview.rb new file mode 100644 index 00000000000..5c722cdee69 --- /dev/null +++ b/spec/components/previews/pajamas/accordion_component_preview.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module Pajamas + class AccordionComponentPreview < ViewComponent::Preview + # @param title text + # @param body text + # @param state + def default(title: "Accordion title (open)", body: "Accordion body", state: :opened) + render(Pajamas::AccordionComponent.new( + title: title, + body: body, + state: state + )) + end + + def closed(title: "Accordion title (closed)", body: "Accordion body", state: :closed) + render(Pajamas::AccordionComponent.new( + title: title, + body: body, + state: state + )) + end + end +end diff --git a/spec/controllers/projects/autocomplete_sources_controller_spec.rb b/spec/controllers/projects/autocomplete_sources_controller_spec.rb index 1745dfe3af0..22736655795 100644 --- a/spec/controllers/projects/autocomplete_sources_controller_spec.rb +++ b/spec/controllers/projects/autocomplete_sources_controller_spec.rb @@ -296,11 +296,7 @@ RSpec.describe Projects::AutocompleteSourcesController do end context 'when feature flag is enabled' do - context 'when a group has contact relations enabled' do - before do - create(:crm_settings, group: group, enabled: true) - end - + context 'when a group has crm enabled' do context 'when a user can read contacts' do it 'lists contacts' do group.add_developer(user) @@ -321,7 +317,11 @@ RSpec.describe Projects::AutocompleteSourcesController do end end - context 'when a group has contact relations disabled' do + context 'when a group has crm disabled' do + before do + create(:crm_settings, group: group, enabled: false) + end + it 'renders 404' do group.add_developer(user) diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb index 9e479aa4558..2f671b08985 100644 --- a/spec/db/schema_spec.rb +++ b/spec/db/schema_spec.rb @@ -102,6 +102,7 @@ RSpec.describe 'Database schema', feature_category: :database do p_batched_git_ref_updates_deletions: %w[project_id partition_id], p_catalog_resource_sync_events: %w[catalog_resource_id project_id partition_id], p_ci_finished_build_ch_sync_events: %w[build_id], + p_ci_job_artifacts: %w[partition_id project_id job_id], p_ci_pipeline_variables: %w[partition_id], product_analytics_events_experimental: %w[event_id txn_id user_id], project_build_artifacts_size_refreshes: %w[last_job_artifact_id], diff --git a/spec/factories/groups.rb b/spec/factories/groups.rb index 2f55c3ab567..e92e4768b8b 100644 --- a/spec/factories/groups.rb +++ b/spec/factories/groups.rb @@ -113,9 +113,9 @@ FactoryBot.define do end end - trait :crm_enabled do + trait :crm_disabled do after(:create) do |group| - create(:crm_settings, group: group, enabled: true) + create(:crm_settings, group: group, enabled: false) end end diff --git a/spec/features/groups/crm/contacts/create_spec.rb b/spec/features/groups/crm/contacts/create_spec.rb index aa05ef82a8b..b0e10477018 100644 --- a/spec/features/groups/crm/contacts/create_spec.rb +++ b/spec/features/groups/crm/contacts/create_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe 'Create a CRM contact', :js, feature_category: :service_desk do let(:user) { create(:user) } - let(:group) { create(:group, :crm_enabled) } + let(:group) { create(:group) } let!(:crm_organization) { create(:crm_organization, group: group, name: 'GitLab') } before do diff --git a/spec/features/groups/group_page_with_external_authorization_service_spec.rb b/spec/features/groups/group_page_with_external_authorization_service_spec.rb index fe1a685899f..f69fec56d35 100644 --- a/spec/features/groups/group_page_with_external_authorization_service_spec.rb +++ b/spec/features/groups/group_page_with_external_authorization_service_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'The group page', :js, feature_category: :groups_and_projects do include ExternalAuthorizationServiceHelpers let(:user) { create(:user) } - let(:group) { create(:group) } + let(:group) { create(:group, :crm_disabled) } before do sign_in user diff --git a/spec/features/groups/navbar_spec.rb b/spec/features/groups/navbar_spec.rb index e9cdacf8255..b1d7559a6d9 100644 --- a/spec/features/groups/navbar_spec.rb +++ b/spec/features/groups/navbar_spec.rb @@ -17,6 +17,10 @@ RSpec.describe 'Group navbar', :with_license, :js, feature_category: :navigation insert_after_nav_item(_('Analyze'), new_nav_item: settings_for_maintainer_nav_item) if Gitlab.ee? insert_infrastructure_registry_nav(_('Kubernetes')) + if group.crm_enabled? && group.parent.nil? + insert_customer_relations_nav(Gitlab.ee? ? _('Iterations') : _('Milestones')) + end + stub_config(dependency_proxy: { enabled: false }) stub_config(registry: { enabled: false }) stub_group_wikis(false) @@ -42,24 +46,18 @@ RSpec.describe 'Group navbar', :with_license, :js, feature_category: :navigation it_behaves_like 'verified navigation bar' end - context 'when customer_relations feature is enabled' do - let(:group) { create(:group, :crm_enabled) } + context 'when crm feature is disabled' do + let(:group) { create(:group, :crm_disabled) } before do - if Gitlab.ee? - insert_customer_relations_nav(_('Iterations')) - else - insert_customer_relations_nav(_('Milestones')) - end - visit group_path(group) end it_behaves_like 'verified navigation bar' end - context 'when customer_relations feature is enabled but subgroup' do - let(:group) { create(:group, :crm_enabled, parent: create(:group)) } + context 'when crm feature is enabled but subgroup' do + let(:group) { create(:group, parent: create(:group)) } before do visit group_path(group) diff --git a/spec/features/issues/gfm_autocomplete_spec.rb b/spec/features/issues/gfm_autocomplete_spec.rb index 58c84d26fea..409153a7725 100644 --- a/spec/features/issues/gfm_autocomplete_spec.rb +++ b/spec/features/issues/gfm_autocomplete_spec.rb @@ -8,7 +8,7 @@ RSpec.describe 'GFM autocomplete', :js, feature_category: :team_planning do let_it_be(:user) { create(:user, name: '💃speciąl someone💃', username: 'someone.special') } let_it_be(:user2) { create(:user, name: 'Marge Simpson', username: 'msimpson') } - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project, group: group) } let_it_be(:issue) { create(:issue, project: project, assignees: [user]) } let_it_be(:label) { create(:label, project: project, title: 'special+') } diff --git a/spec/features/issues/issue_sidebar_spec.rb b/spec/features/issues/issue_sidebar_spec.rb index 08d0d54bcd2..ff1119af21f 100644 --- a/spec/features/issues/issue_sidebar_spec.rb +++ b/spec/features/issues/issue_sidebar_spec.rb @@ -48,7 +48,7 @@ RSpec.describe 'Issue Sidebar', feature_category: :team_planning do open_assignees_dropdown page.within '.dropdown-menu-user' do - find('[data-testid="user-search-input"]').set(user2.name) + find_by_testid('user-search-input').set(user2.name) wait_for_requests @@ -68,7 +68,7 @@ RSpec.describe 'Issue Sidebar', feature_category: :team_planning do it 'keeps your filtered term after filtering and dismissing the dropdown' do open_assignees_dropdown - find('[data-testid="user-search-input"]').set(user2.name) + find_by_testid('user-search-input').set(user2.name) wait_for_requests page.within '.dropdown-menu-user' do @@ -84,7 +84,7 @@ RSpec.describe 'Issue Sidebar', feature_category: :team_planning do expect(page.all('[data-testid="unselected-participant"]').length).to eq(1) end - expect(find('[data-testid="user-search-input"]').value).to eq(user2.name) + expect(find_by_testid('user-search-input').value).to eq(user2.name) end end end diff --git a/spec/features/issues/issue_state_spec.rb b/spec/features/issues/issue_state_spec.rb index 125329764c6..b85d40a798d 100644 --- a/spec/features/issues/issue_state_spec.rb +++ b/spec/features/issues/issue_state_spec.rb @@ -16,14 +16,14 @@ RSpec.describe 'issue state', :js, feature_category: :team_planning do it 'can close an issue' do expect(page).to have_selector('[data-testid="issue-state-badge"]') - expect(find('[data-testid="issue-state-badge"]')).to have_content 'Open' + expect(find_by_testid('issue-state-badge')).to have_content 'Open' within selector do click_button 'Close issue' wait_for_requests end - expect(find('[data-testid="issue-state-badge"]')).to have_content 'Closed' + expect(find_by_testid('issue-state-badge')).to have_content 'Closed' end end @@ -31,14 +31,14 @@ RSpec.describe 'issue state', :js, feature_category: :team_planning do it 'can reopen an issue' do expect(page).to have_selector('[data-testid="issue-state-badge"]') - expect(find('[data-testid="issue-state-badge"]')).to have_content 'Closed' + expect(find_by_testid('issue-state-badge')).to have_content 'Closed' within selector do click_button 'Reopen issue' wait_for_requests end - expect(find('[data-testid="issue-state-badge"]')).to have_content 'Open' + expect(find_by_testid('issue-state-badge')).to have_content 'Open' end end diff --git a/spec/features/issues/user_creates_issue_spec.rb b/spec/features/issues/user_creates_issue_spec.rb index a407e7fd112..01a14aaca75 100644 --- a/spec/features/issues/user_creates_issue_spec.rb +++ b/spec/features/issues/user_creates_issue_spec.rb @@ -101,7 +101,7 @@ RSpec.describe "User creates issue", feature_category: :team_planning do wait_for_all_requests - page.within '[data-testid="sidebar-labels"]' do + within_testid('sidebar-labels') do click_button label_titles.first click_button _('Close') diff --git a/spec/features/issues/user_edits_issue_spec.rb b/spec/features/issues/user_edits_issue_spec.rb index e9bf1ef542b..b3ac374ae63 100644 --- a/spec/features/issues/user_edits_issue_spec.rb +++ b/spec/features/issues/user_edits_issue_spec.rb @@ -117,7 +117,7 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin markdown_field_focused_selector = 'textarea:focus' click_edit_issue_description - issuable_form = find('[data-testid="issuable-form"]') + issuable_form = find_by_testid('issuable-form') expect(issuable_form).to have_selector(markdown_field_focused_selector) @@ -220,8 +220,8 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin click_button('Edit') wait_for_requests - find('[data-testid="unassign"]').click - find('[data-testid="title"]').click + find_by_testid('unassign').click + find_by_testid('title').click wait_for_requests expect(page).to have_content 'None - assign yourself' @@ -243,7 +243,7 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin end page.within('.assignee') do - find('[data-testid="title"]').click + find_by_testid('title').click wait_for_requests expect(page).to have_content user.name @@ -262,7 +262,7 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin wait_for_requests click_button user.name - find('[data-testid="title"]').click + find_by_testid('title').click wait_for_requests expect(page).to have_content "None" @@ -314,7 +314,7 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin wait_for_requests click_button milestone.title - page.within '[data-testid="select-milestone"]' do + within_testid('select-milestone') do expect(page).to have_content milestone.title end @@ -322,7 +322,7 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin wait_for_requests click_button 'No milestone' - page.within '[data-testid="select-milestone"]' do + within_testid('select-milestone') do expect(page).to have_content 'None' end end @@ -376,7 +376,7 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin it 'adds due date to issue' do date = Date.today.at_beginning_of_month + 2.days - page.within '[data-testid="sidebar-due-date"]' do + within_testid('sidebar-due-date') do click_button 'Edit' page.within '.pika-single' do click_button date.day @@ -384,14 +384,14 @@ RSpec.describe "Issues > User edits issue", :js, feature_category: :team_plannin wait_for_requests - expect(find('[data-testid="sidebar-date-value"]').text).to have_content date.strftime('%b %-d, %Y') + expect(find_by_testid('sidebar-date-value').text).to have_content date.strftime('%b %-d, %Y') end end it 'removes due date from issue' do date = Date.today.at_beginning_of_month + 2.days - page.within '[data-testid="sidebar-due-date"]' do + within_testid('sidebar-due-date') do click_button 'Edit' page.within '.pika-single' do diff --git a/spec/features/issues/user_resets_their_incoming_email_token_spec.rb b/spec/features/issues/user_resets_their_incoming_email_token_spec.rb index 55c66eb8a39..df6443a32b4 100644 --- a/spec/features/issues/user_resets_their_incoming_email_token_spec.rb +++ b/spec/features/issues/user_resets_their_incoming_email_token_spec.rb @@ -20,7 +20,7 @@ RSpec.describe 'Issues > User resets their incoming email token', feature_catego page.within '#issuable-email-modal' do previous_token = page.find('input[type="text"]').value - find('[data-testid="reset_email_token_link"]').click + find_by_testid('reset_email_token_link').click wait_for_requests diff --git a/spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb b/spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb index 91b18454af5..1d66c543b77 100644 --- a/spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb +++ b/spec/features/issues/user_sees_sidebar_updates_in_realtime_spec.rb @@ -8,8 +8,8 @@ RSpec.describe 'Issues > Real-time sidebar', :js, :with_license, feature_categor let_it_be(:user) { create(:user) } let_it_be(:label) { create(:label, project: project, name: 'Development') } - let(:labels_widget) { find('[data-testid="sidebar-labels"]') } - let(:labels_value) { find('[data-testid="value-wrapper"]') } + let(:labels_widget) { find_by_testid('sidebar-labels') } + let(:labels_value) { find_by_testid('value-wrapper') } before_all do project.add_developer(user) diff --git a/spec/features/issues/user_toggles_subscription_spec.rb b/spec/features/issues/user_toggles_subscription_spec.rb index a1ea40c511f..6c611608510 100644 --- a/spec/features/issues/user_toggles_subscription_spec.rb +++ b/spec/features/issues/user_toggles_subscription_spec.rb @@ -32,17 +32,19 @@ RSpec.describe "User toggles subscription", :js, feature_category: :team_plannin it 'unsubscribes from issue' do find('.detail-page-header-actions .gl-new-dropdown-toggle').click - subscription_button = find('[data-testid="notification-toggle"] [data-testid="toggle-wrapper"]') + within_testid('notification-toggle') do + subscription_button = find_by_testid('toggle-wrapper') - # Check we're subscribed. - expect(subscription_button).to have_css("button.is-checked") + # Check we're subscribed. + expect(subscription_button).to have_css("button.is-checked") - # Toggle subscription. - subscription_button.find('button').click - wait_for_requests + # Toggle subscription. + subscription_button.find('button').click + wait_for_requests - # Check we're unsubscribed. - expect(subscription_button).to have_css("button:not(.is-checked)") + # Check we're unsubscribed. + expect(subscription_button).to have_css("button:not(.is-checked)") + end end end @@ -57,17 +59,19 @@ RSpec.describe "User toggles subscription", :js, feature_category: :team_plannin it 'subscribes to issue' do find('.detail-page-header-actions .gl-new-dropdown-toggle').click - subscription_button = find('[data-testid="notification-toggle"] [data-testid="toggle-wrapper"]') + within_testid('notification-toggle') do + subscription_button = find_by_testid('toggle-wrapper') - # Check we're not subscribed. - expect(subscription_button).to have_css("button:not(.is-checked)") + # Check we're not subscribed. + expect(subscription_button).to have_css("button:not(.is-checked)") - # Toggle subscription. - subscription_button.find('button').click - wait_for_requests + # Toggle subscription. + subscription_button.find('button').click + wait_for_requests - # Check we're subscribed. - expect(subscription_button).to have_css("button.is-checked") + # Check we're subscribed. + expect(subscription_button).to have_css("button.is-checked") + end end end @@ -80,7 +84,7 @@ RSpec.describe "User toggles subscription", :js, feature_category: :team_plannin end it 'toggles subscription' do - subscription_button = find('[data-testid="subscribe-button"]') + subscription_button = find_by_testid('subscribe-button') expect(page).to have_selector("button[title='Notifications off']") subscription_button.click diff --git a/spec/features/labels_hierarchy_spec.rb b/spec/features/labels_hierarchy_spec.rb index c6c7342325b..c5bf230e988 100644 --- a/spec/features/labels_hierarchy_spec.rb +++ b/spec/features/labels_hierarchy_spec.rb @@ -58,7 +58,7 @@ RSpec.describe 'Labels Hierarchy', :js, feature_category: :team_planning do expect(card).to have_selector('a', text: labeled_issue.title) end else - within '[data-testid="filtered-search-input"]' do + within_testid('filtered-search-input') do click_filtered_search_bar click_on 'Label' click_on '= is' @@ -109,7 +109,7 @@ RSpec.describe 'Labels Hierarchy', :js, feature_category: :team_planning do expect(card).to have_selector('a', text: labeled_issue_2.title) end else - within '[data-testid="filtered-search-input"]' do + within_testid('filtered-search-input') do click_filtered_search_bar click_on 'Label' click_on '= is' @@ -170,7 +170,7 @@ RSpec.describe 'Labels Hierarchy', :js, feature_category: :team_planning do wait_for_all_requests - page.within '[data-testid="sidebar-labels"]' do + within_testid('sidebar-labels') do click_button grandparent_group_label.title click_button parent_group_label.title click_button project_label_1.title diff --git a/spec/features/merge_request/user_accepts_merge_request_spec.rb b/spec/features/merge_request/user_accepts_merge_request_spec.rb index e3989a8a192..6e0ad749dbb 100644 --- a/spec/features/merge_request/user_accepts_merge_request_spec.rb +++ b/spec/features/merge_request/user_accepts_merge_request_spec.rb @@ -109,7 +109,7 @@ RSpec.describe 'User accepts a merge request', :js, :sidekiq_might_not_need_inli end it 'accepts a merge request' do - find('[data-testid="widget_edit_commit_message"]').click + find_by_testid('widget_edit_commit_message').click fill_in('merge-message-edit', with: 'wow such merge') click_merge_button diff --git a/spec/features/merge_request/user_assigns_themselves_spec.rb b/spec/features/merge_request/user_assigns_themselves_spec.rb index ed4ea91f704..b1d87ee4904 100644 --- a/spec/features/merge_request/user_assigns_themselves_spec.rb +++ b/spec/features/merge_request/user_assigns_themselves_spec.rb @@ -25,7 +25,7 @@ RSpec.describe 'Merge request > User assigns themselves', feature_category: :cod wait_for_requests expect do - page.within('[data-testid="assignee-block-container"]') do + within_testid('assignee-block-container') do click_button 'assign yourself' end @@ -40,7 +40,7 @@ RSpec.describe 'Merge request > User assigns themselves', feature_category: :cod end it 'does not display if related issues are already assigned' do - page.within('[data-testid="assignee-block-container"]') do + within_testid('assignee-block-container') do expect(page).not_to have_content 'Assign yourself' end end @@ -54,7 +54,7 @@ RSpec.describe 'Merge request > User assigns themselves', feature_category: :cod end it 'does not show assignment link' do - page.within('[data-testid="assignee-block-container"]') do + within_testid('assignee-block-container') do expect(page).not_to have_content 'Assign yourself' end end diff --git a/spec/features/merge_request/user_comments_on_diff_spec.rb b/spec/features/merge_request/user_comments_on_diff_spec.rb index 9135f5c7b98..eb14bd39253 100644 --- a/spec/features/merge_request/user_comments_on_diff_spec.rb +++ b/spec/features/merge_request/user_comments_on_diff_spec.rb @@ -146,7 +146,7 @@ RSpec.describe 'User comments on a diff', :js, feature_category: :code_review_wo click_button "Insert suggestion" end - within '[data-testid="content-editor"]' do + within_testid('content-editor') do expect(page).to have_content('Suggested change From line') end end diff --git a/spec/features/merge_request/user_comments_on_whitespace_hidden_diff_spec.rb b/spec/features/merge_request/user_comments_on_whitespace_hidden_diff_spec.rb index c13fe8d1e45..233e6dd0f3e 100644 --- a/spec/features/merge_request/user_comments_on_whitespace_hidden_diff_spec.rb +++ b/spec/features/merge_request/user_comments_on_whitespace_hidden_diff_spec.rb @@ -23,7 +23,7 @@ RSpec.describe 'User comments on a diff with whitespace changes', :js, feature_c context 'when hiding whitespace changes' do before do find('.js-show-diff-settings').click - find('[data-testid="show-whitespace"]').click + find_by_testid('show-whitespace').click wait_for_requests end diff --git a/spec/features/merge_request/user_creates_mr_spec.rb b/spec/features/merge_request/user_creates_mr_spec.rb index 5f6e465d011..8c90a94b228 100644 --- a/spec/features/merge_request/user_creates_mr_spec.rb +++ b/spec/features/merge_request/user_creates_mr_spec.rb @@ -14,20 +14,20 @@ RSpec.describe 'Merge request > User creates MR', feature_category: :code_review include ListboxHelpers it 'creates new merge request', :js do - find('[data-testid="assignee-ids-dropdown-toggle"]').click + find_by_testid('assignee-ids-dropdown-toggle').click page.within '.dropdown-menu-user' do click_link user2.name end expect(find('input[name="merge_request[assignee_ids][]"]', visible: false).value).to match(user2.id.to_s) - page.within '[data-testid="assignee-ids-dropdown-toggle"]' do + within_testid('assignee-ids-dropdown-toggle') do expect(page).to have_content user2.name end click_link 'Assign to me' expect(find('input[name="merge_request[assignee_ids][]"]', visible: false).value).to match(user.id.to_s) - page.within '[data-testid="assignee-ids-dropdown-toggle"]' do + within_testid('assignee-ids-dropdown-toggle') do expect(page).to have_content user.name end @@ -38,12 +38,12 @@ RSpec.describe 'Merge request > User creates MR', feature_category: :code_review click_button _('Select label') wait_for_all_requests - page.within '[data-testid="sidebar-labels"]' do + within_testid('sidebar-labels') do click_button label.title click_button label2.title click_button _('Close') wait_for_requests - page.within('[data-testid="embedded-labels-list"]') do + within_testid('embedded-labels-list') do expect(page).to have_content(label.title) expect(page).to have_content(label2.title) end diff --git a/spec/features/projects/user_creates_project_spec.rb b/spec/features/projects/user_creates_project_spec.rb index 96156f14cfc..b715733ca20 100644 --- a/spec/features/projects/user_creates_project_spec.rb +++ b/spec/features/projects/user_creates_project_spec.rb @@ -58,12 +58,13 @@ RSpec.describe 'User creates a project', :js, feature_category: :groups_and_proj end context 'when creating a project with SHA256 repository' do - let(:sha256_field) { 'Use SHA-256 as the repository hashing algorithm' } + let(:sha256_field) { 'Use SHA-256 for repository hashing algorithm' } it 'creates a new project' do visit(new_project_path) click_link 'Create blank project' + click_button 'Experimental settings' fill_in(:project_name, with: 'With initial commits') expect(page).to have_checked_field 'Initialize repository with a README' diff --git a/spec/finders/crm/contacts_finder_spec.rb b/spec/finders/crm/contacts_finder_spec.rb index d0339ce2b18..c54cd39534f 100644 --- a/spec/finders/crm/contacts_finder_spec.rb +++ b/spec/finders/crm/contacts_finder_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Crm::ContactsFinder do subject { described_class.new(user, group: group).execute } context 'when customer relations feature is enabled for the group' do - let_it_be(:root_group) { create(:group, :crm_enabled) } + let_it_be(:root_group) { create(:group) } let_it_be(:group) { create(:group, parent: root_group) } let_it_be(:contact_1) { create(:contact, group: root_group) } @@ -44,8 +44,8 @@ RSpec.describe Crm::ContactsFinder do end end - context 'when customer relations feature is disabled for the group' do - let_it_be(:group) { create(:group) } + context 'when crm feature is disabled for the group' do + let_it_be(:group) { create(:group, :crm_disabled) } let_it_be(:contact) { create(:contact, group: group) } before do @@ -58,7 +58,7 @@ RSpec.describe Crm::ContactsFinder do end context 'with search informations' do - let_it_be(:search_test_group) { create(:group, :crm_enabled) } + let_it_be(:search_test_group) { create(:group) } let_it_be(:search_test_a) do create( @@ -189,7 +189,7 @@ RSpec.describe Crm::ContactsFinder do end describe '.counts_by_state' do - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let_it_be(:active_contacts) { create_list(:contact, 3, group: group, state: :active) } let_it_be(:inactive_contacts) { create_list(:contact, 2, group: group, state: :inactive) } diff --git a/spec/finders/crm/organizations_finder_spec.rb b/spec/finders/crm/organizations_finder_spec.rb index bc174f927a7..fd65cd22cb5 100644 --- a/spec/finders/crm/organizations_finder_spec.rb +++ b/spec/finders/crm/organizations_finder_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Crm::OrganizationsFinder do subject { described_class.new(user, group: group).execute } context 'when customer relations feature is enabled for the group' do - let_it_be(:root_group) { create(:group, :crm_enabled) } + let_it_be(:root_group) { create(:group) } let_it_be(:group) { create(:group, parent: root_group) } let_it_be(:crm_organization_1) { create(:crm_organization, group: root_group) } @@ -45,7 +45,7 @@ RSpec.describe Crm::OrganizationsFinder do end context 'when customer relations feature is disabled for the group' do - let_it_be(:group) { create(:group) } + let_it_be(:group) { create(:group, :crm_disabled) } let_it_be(:crm_organization) { create(:crm_organization, group: group) } before do @@ -58,7 +58,7 @@ RSpec.describe Crm::OrganizationsFinder do end context 'with search informations' do - let_it_be(:search_test_group) { create(:group, :crm_enabled) } + let_it_be(:search_test_group) { create(:group) } let_it_be(:search_test_a) do create( @@ -130,7 +130,7 @@ RSpec.describe Crm::OrganizationsFinder do end context 'when sorting' do - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let_it_be(:sort_test_a) do create( @@ -185,7 +185,7 @@ RSpec.describe Crm::OrganizationsFinder do end describe '.counts_by_state' do - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let_it_be(:active_crm_organizations) { create_list(:crm_organization, 3, group: group, state: :active) } let_it_be(:inactive_crm_organizations) { create_list(:crm_organization, 2, group: group, state: :inactive) } diff --git a/spec/frontend/accordion/index_spec.js b/spec/frontend/accordion/index_spec.js new file mode 100644 index 00000000000..10ce1cdd00e --- /dev/null +++ b/spec/frontend/accordion/index_spec.js @@ -0,0 +1,52 @@ +import initAccordion from '~/accordion'; +import { setHTMLFixture, resetHTMLFixture } from 'helpers/fixtures'; + +describe('Init Accordion component', () => { + beforeEach(() => { + setHTMLFixture( + '
', + ); + initAccordion(document.querySelector('.js-accordion')); + }); + + afterEach(() => resetHTMLFixture()); + + const findAccordionTrigger = () => document.querySelector('button'); + const findAccordionItem = () => document.querySelector('.accordion-item'); + const findSvgIconLink = () => document.querySelector('use').getAttribute('xlink:href'); + + describe('expanded', () => { + beforeEach(() => findAccordionTrigger().click()); + + it('adds a `show` class to the accordion item', () => { + expect(findAccordionItem().classList.contains('show')).toBe(true); + }); + + it('renders a chevron-down icon', () => { + expect(findSvgIconLink()).toContain('#chevron-down'); + }); + + it('renders a button with the correct aria-expanded value', () => { + expect(findAccordionTrigger().getAttribute('aria-expanded')).toBe('true'); + }); + }); + + describe('collapsed', () => { + beforeEach(() => { + findAccordionTrigger().click(); // expands the accordion + findAccordionTrigger().click(); // collapses the accordion + }); + + it('removes `show` class from the accordion item', () => { + expect(findAccordionItem().classList.contains('show')).toBe(false); + }); + + it('renders a chevron-right icon', () => { + expect(findSvgIconLink()).toContain('#chevron-right'); + }); + + it('renders a button with the correct aria-expanded value', () => { + expect(findAccordionTrigger().getAttribute('aria-expanded')).toBe('false'); + }); + }); +}); diff --git a/spec/frontend/achievements/achievements_app_spec.js b/spec/frontend/achievements/achievements_app_spec.js new file mode 100644 index 00000000000..46fc085af45 --- /dev/null +++ b/spec/frontend/achievements/achievements_app_spec.js @@ -0,0 +1,94 @@ +import { GlEmptyState, GlKeysetPagination, GlLoadingIcon, GlTableLite } from '@gitlab/ui'; +import Vue from 'vue'; +import VueApollo from 'vue-apollo'; +import getGroupAchievementsResponse from 'test_fixtures/graphql/get_group_achievements_response.json'; +import getGroupAchievementsEmptyResponse from 'test_fixtures/graphql/get_group_achievements_empty_response.json'; +import getGroupAchievementsPaginatedResponse from 'test_fixtures/graphql/get_group_achievements_paginated_response.json'; +import { shallowMountExtended } from 'helpers/vue_test_utils_helper'; +import createMockApollo from 'helpers/mock_apollo_helper'; +import waitForPromises from 'helpers/wait_for_promises'; +import AchievementsApp from '~/achievements/components/achievements_app.vue'; +import getGroupAchievementsQuery from '~/achievements/components/graphql/get_group_achievements.query.graphql'; + +Vue.use(VueApollo); + +describe('Achievements app', () => { + let wrapper; + let fakeApollo; + let queryHandler; + + const findEmptyState = () => wrapper.findComponent(GlEmptyState); + const findLoadingIcon = () => wrapper.findComponent(GlLoadingIcon); + const findPagingControls = () => wrapper.findComponent(GlKeysetPagination); + const findTable = () => wrapper.findComponent(GlTableLite); + + const mountComponent = ({ queryResponse = getGroupAchievementsResponse } = {}) => { + queryHandler = jest.fn().mockResolvedValue(queryResponse); + fakeApollo = createMockApollo([[getGroupAchievementsQuery, queryHandler]]); + wrapper = shallowMountExtended(AchievementsApp, { + provide: { + groupFullPath: 'flightjs', + }, + apolloProvider: fakeApollo, + }); + return waitForPromises(); + }; + + it('should render loading state', () => { + mountComponent(); + + expect(findLoadingIcon().exists()).toBe(true); + }); + + describe('on successful load', () => { + it('should render table with expected props', async () => { + await mountComponent(); + + const { items } = findTable().vm.$attrs; + + expect(findTable().exists()).toBe(true); + expect(items).toContainEqual(expect.objectContaining({ name: 'Hero' })); + expect(items).toContainEqual(expect.objectContaining({ name: 'Star' })); + expect(items).toContainEqual(expect.objectContaining({ name: 'Legend' })); + }); + + describe('with no achievements', () => { + it('should render the empty state', async () => { + await mountComponent({ queryResponse: getGroupAchievementsEmptyResponse }); + + expect(findEmptyState().exists()).toBe(true); + }); + }); + + describe('with multiple pages', () => { + it('should render paging controls', async () => { + await mountComponent({ queryResponse: getGroupAchievementsPaginatedResponse }); + + expect(findPagingControls().exists()).toBe(true); + }); + + describe('when the next page is selected', () => { + it('should pass the end cursor', async () => { + await mountComponent({ queryResponse: getGroupAchievementsPaginatedResponse }); + findPagingControls().vm.$emit('next', 'foo'); + await waitForPromises(); + + expect(queryHandler).toHaveBeenCalledWith({ + after: null, + before: null, + first: 20, + groupFullPath: 'flightjs', + last: null, + }); + expect(queryHandler).toHaveBeenCalledWith({ + after: 'foo', + before: null, + first: 20, + groupFullPath: 'flightjs', + last: null, + }); + }); + }); + }); + }); +}); diff --git a/spec/frontend/fixtures/achievements.rb b/spec/frontend/fixtures/achievements.rb new file mode 100644 index 00000000000..7fcdd8fa843 --- /dev/null +++ b/spec/frontend/fixtures/achievements.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Achievements (JavaScript fixtures)', feature_category: :user_profile do + include JavaScriptFixturesHelpers + include ApiHelpers + + describe GraphQL::Query, type: :request do + include GraphqlHelpers + + let_it_be(:group) { create(:group, :public) } + + let(:query_path) { 'achievements/components/graphql/get_group_achievements.query.graphql' } + let(:query) { get_graphql_query_as_string(query_path) } + + it "graphql/get_group_achievements_empty_response.json" do + post_graphql(query, current_user: nil, variables: { group_full_path: group.full_path }) + + expect_graphql_errors_to_be_empty + end + + context 'with achievements' do + before_all do + create(:achievement, namespace: group, name: "Hero") + create(:achievement, namespace: group, name: "Star") + create(:achievement, namespace: group, name: "Legend") + end + + it "graphql/get_group_achievements_response.json" do + post_graphql(query, current_user: nil, variables: { group_full_path: group.full_path }) + + expect_graphql_errors_to_be_empty + end + + it "graphql/get_group_achievements_paginated_response.json" do + post_graphql(query, current_user: nil, variables: { group_full_path: group.full_path, first: 2 }) + + expect_graphql_errors_to_be_empty + end + end + end +end diff --git a/spec/frontend/releases/__snapshots__/util_spec.js.snap b/spec/frontend/releases/__snapshots__/util_spec.js.snap index 983db8846c6..e517f9569ef 100644 --- a/spec/frontend/releases/__snapshots__/util_spec.js.snap +++ b/spec/frontend/releases/__snapshots__/util_spec.js.snap @@ -43,7 +43,7 @@ Object { }, "author": Object { "__typename": "UserCore", - "avatarUrl": "https://www.gravatar.com/avatar/eb329fbfeccd9e6d45ff159da8736876?s=80&d=identicon", + "avatarUrl": "https://www.gravatar.com/avatar/47420c558894b028457615db5156a52e6b791b829a6ca611656bb2560f9dbfc3?s=80&d=identicon", "id": Any, "username": "user1", "webUrl": "http://localhost/user1", @@ -149,7 +149,7 @@ Object { }, "author": Object { "__typename": "UserCore", - "avatarUrl": "https://www.gravatar.com/avatar/eb329fbfeccd9e6d45ff159da8736876?s=80&d=identicon", + "avatarUrl": "https://www.gravatar.com/avatar/47420c558894b028457615db5156a52e6b791b829a6ca611656bb2560f9dbfc3?s=80&d=identicon", "id": Any, "username": "user1", "webUrl": "http://localhost/user1", @@ -386,7 +386,7 @@ Object { }, "author": Object { "__typename": "UserCore", - "avatarUrl": "https://www.gravatar.com/avatar/eb329fbfeccd9e6d45ff159da8736876?s=80&d=identicon", + "avatarUrl": "https://www.gravatar.com/avatar/47420c558894b028457615db5156a52e6b791b829a6ca611656bb2560f9dbfc3?s=80&d=identicon", "id": Any, "username": "user1", "webUrl": "http://localhost/user1", diff --git a/spec/graphql/mutations/customer_relations/contacts/create_spec.rb b/spec/graphql/mutations/customer_relations/contacts/create_spec.rb index 3ee898c2079..2cca77b8983 100644 --- a/spec/graphql/mutations/customer_relations/contacts/create_spec.rb +++ b/spec/graphql/mutations/customer_relations/contacts/create_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Mutations::CustomerRelations::Contacts::Create do let_it_be(:user) { create(:user) } - let(:group) { create(:group, :crm_enabled) } + let(:group) { create(:group) } let(:not_found_or_does_not_belong) { 'The specified organization was not found or does not belong to this group' } let(:valid_params) do attributes_for(:contact, @@ -41,7 +41,7 @@ RSpec.describe Mutations::CustomerRelations::Contacts::Create do end context 'when crm_enabled is false' do - let(:group) { create(:group) } + let(:group) { create(:group, :crm_disabled) } it 'raises an error' do expect { resolve_mutation }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) diff --git a/spec/graphql/mutations/customer_relations/contacts/update_spec.rb b/spec/graphql/mutations/customer_relations/contacts/update_spec.rb index 421bb4f1b06..2ea13dbeb3d 100644 --- a/spec/graphql/mutations/customer_relations/contacts/update_spec.rb +++ b/spec/graphql/mutations/customer_relations/contacts/update_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe Mutations::CustomerRelations::Contacts::Update do let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let(:first_name) { 'Lionel' } let(:last_name) { 'Smith' } diff --git a/spec/graphql/mutations/customer_relations/organizations/create_spec.rb b/spec/graphql/mutations/customer_relations/organizations/create_spec.rb index cf1ff2d5653..f9aef726499 100644 --- a/spec/graphql/mutations/customer_relations/organizations/create_spec.rb +++ b/spec/graphql/mutations/customer_relations/organizations/create_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe Mutations::CustomerRelations::Organizations::Create do let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let(:valid_params) do attributes_for(:crm_organization, diff --git a/spec/graphql/mutations/customer_relations/organizations/update_spec.rb b/spec/graphql/mutations/customer_relations/organizations/update_spec.rb index 2fad320b497..c62d6859241 100644 --- a/spec/graphql/mutations/customer_relations/organizations/update_spec.rb +++ b/spec/graphql/mutations/customer_relations/organizations/update_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe Mutations::CustomerRelations::Organizations::Update do let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let(:name) { 'GitLab' } let(:default_rate) { 1000.to_f } diff --git a/spec/graphql/resolvers/crm/contact_state_counts_resolver_spec.rb b/spec/graphql/resolvers/crm/contact_state_counts_resolver_spec.rb index 0128ec792b3..607855ef41c 100644 --- a/spec/graphql/resolvers/crm/contact_state_counts_resolver_spec.rb +++ b/spec/graphql/resolvers/crm/contact_state_counts_resolver_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Resolvers::Crm::ContactStateCountsResolver do include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } before_all do create(:contact, group: group, email: "x@test.com") diff --git a/spec/graphql/resolvers/crm/contacts_resolver_spec.rb b/spec/graphql/resolvers/crm/contacts_resolver_spec.rb index 1a53f42633f..f7ca034842b 100644 --- a/spec/graphql/resolvers/crm/contacts_resolver_spec.rb +++ b/spec/graphql/resolvers/crm/contacts_resolver_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Resolvers::Crm::ContactsResolver do include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let_it_be(:contact_a) do create( diff --git a/spec/graphql/resolvers/crm/organization_state_counts_resolver_spec.rb b/spec/graphql/resolvers/crm/organization_state_counts_resolver_spec.rb index f6c2040b7d0..eb704a538d0 100644 --- a/spec/graphql/resolvers/crm/organization_state_counts_resolver_spec.rb +++ b/spec/graphql/resolvers/crm/organization_state_counts_resolver_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Resolvers::Crm::OrganizationStateCountsResolver do include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } before_all do create(:crm_organization, group: group, name: "ABC Corp") diff --git a/spec/graphql/resolvers/crm/organizations_resolver_spec.rb b/spec/graphql/resolvers/crm/organizations_resolver_spec.rb index edc1986799a..f3685014b61 100644 --- a/spec/graphql/resolvers/crm/organizations_resolver_spec.rb +++ b/spec/graphql/resolvers/crm/organizations_resolver_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Resolvers::Crm::OrganizationsResolver do include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let_it_be(:crm_organization_a) do create( diff --git a/spec/helpers/avatars_helper_spec.rb b/spec/helpers/avatars_helper_spec.rb index aab63ea0f70..88310086cc5 100644 --- a/spec/helpers/avatars_helper_spec.rb +++ b/spec/helpers/avatars_helper_spec.rb @@ -225,7 +225,7 @@ RSpec.describe AvatarsHelper, feature_category: :source_code_management do stub_config_setting(https: false) expect(helper.gravatar_icon(user_email)) - .to match('https://www.gravatar.com/avatar/b58c6f14d292556214bd64909bcdb118') + .to match('https://www.gravatar.com/avatar/0925f997eb0d742678f66d2da134d15d842d57722af5f7605c4785cb5358831b') end it 'uses HTTPs when configured' do @@ -239,7 +239,7 @@ RSpec.describe AvatarsHelper, feature_category: :source_code_management do stub_gravatar_setting(plain_url: 'http://example.local/?s=%{size}&hash=%{hash}') expect(gravatar_icon(user_email, 20)) - .to eq('http://example.local/?s=40&hash=b58c6f14d292556214bd64909bcdb118') + .to eq('http://example.local/?s=40&hash=0925f997eb0d742678f66d2da134d15d842d57722af5f7605c4785cb5358831b') end it 'accepts a custom size argument' do @@ -261,12 +261,6 @@ RSpec.describe AvatarsHelper, feature_category: :source_code_management do expect(normal).to eq upcase end end - - context 'with FIPS enabled', :fips_mode do - it 'returns a generic avatar' do - expect(helper.gravatar_icon(user_email)).to match_asset_path(described_class::DEFAULT_AVATAR_PATH) - end - end end end diff --git a/spec/lib/api/entities/bulk_imports/entity_failure_spec.rb b/spec/lib/api/entities/bulk_imports/entity_failure_spec.rb index 20563bfb685..ee96bc1cae6 100644 --- a/spec/lib/api/entities/bulk_imports/entity_failure_spec.rb +++ b/spec/lib/api/entities/bulk_imports/entity_failure_spec.rb @@ -39,4 +39,18 @@ RSpec.describe API::Entities::BulkImports::EntityFailure, feature_category: :imp expect(subject[:exception_message]).to eq(filtered_message.truncate(255)) end end + + describe 'relation' do + it 'returns relation' do + expect(subject[:relation]).to eq('test') + end + + context 'when subrelation is present' do + it 'includes subrelation' do + failure.update!(subrelation: 'subrelation') + + expect(subject[:relation]).to eq('test, subrelation') + end + end + end end diff --git a/spec/lib/bulk_imports/ndjson_pipeline_spec.rb b/spec/lib/bulk_imports/ndjson_pipeline_spec.rb index 5611879868d..55a9292e48d 100644 --- a/spec/lib/bulk_imports/ndjson_pipeline_spec.rb +++ b/spec/lib/bulk_imports/ndjson_pipeline_spec.rb @@ -203,6 +203,7 @@ RSpec.describe BulkImports::NdjsonPipeline, feature_category: :importers do failure = entity.failures.first expect(failure.pipeline_class).to eq(tracker.pipeline_name) + expect(failure.subrelation).to eq('LabelPriority') expect(failure.exception_class).to eq('RecordInvalid') expect(failure.exception_message).to eq("Project can't be blank, Priority can't be blank, and Priority is not a number") end diff --git a/spec/lib/gitlab/database/partitioning/list/convert_table_spec.rb b/spec/lib/gitlab/database/partitioning/list/convert_table_spec.rb index 0b3528d5691..a0158b039e3 100644 --- a/spec/lib/gitlab/database/partitioning/list/convert_table_spec.rb +++ b/spec/lib/gitlab/database/partitioning/list/convert_table_spec.rb @@ -285,9 +285,11 @@ RSpec.describe Gitlab::Database::Partitioning::List::ConvertTable, feature_categ where(:case_name, :fault) do [ ["creating parent table", lazy { fail_sql_matching(/CREATE/i) }], - ["adding the first foreign key", lazy { fail_adding_fk(parent_table_name, referenced_table_name) }], + ["adding the first foreign key", lazy do + fail_adding_concurrent_fk(parent_table_name, referenced_table_name) + end], ["adding the second foreign key", lazy do - fail_adding_fk(parent_table_name, other_referenced_table_name) + fail_adding_concurrent_fk(parent_table_name, other_referenced_table_name) end], ["attaching table", lazy { fail_sql_matching(/ATTACH/i) }] ] @@ -338,8 +340,7 @@ RSpec.describe Gitlab::Database::Partitioning::List::ConvertTable, feature_categ it 'sets up partitioning analysis for parent table' do expect(migration_context).to receive(:execute).with(/CREATE TABLE/).ordered.and_call_original - expect(migration_context).to receive(:execute).with(/ALTER TABLE/).ordered.and_call_original - expect(migration_context).to receive(:disable_statement_timeout).ordered.and_call_original + expect(migration_context).to receive(:execute).exactly(5).with(/ALTER TABLE/).ordered.and_call_original expect(migration_context).to receive(:execute).with(/ANALYZE VERBOSE/).ordered.and_call_original partition diff --git a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb index 9d484198cc0..806c01a993e 100644 --- a/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb +++ b/spec/lib/gitlab/email/handler/service_desk_handler_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Gitlab::Email::Handler::ServiceDeskHandler, feature_category: :se let(:message_id) { 'CADkmRc+rNGAGGbV2iE5p918UVy4UyJqVcXRO2=otppgzduJSg@mail.gmail.com' } let(:issue_email_participants_count) { 1 } - let_it_be(:group) { create(:group, :private, :crm_enabled, name: "email") } + let_it_be(:group) { create(:group, :private, name: "email") } let(:expected_subject) { "The message subject! @all" } let(:expected_description) do diff --git a/spec/lib/gitlab/import_export/all_models.yml b/spec/lib/gitlab/import_export/all_models.yml index ca6d9bde835..0cd0cc77923 100644 --- a/spec/lib/gitlab/import_export/all_models.yml +++ b/spec/lib/gitlab/import_export/all_models.yml @@ -1031,6 +1031,7 @@ issuable_sla: - issue push_rule: - group + - organization bulk_import_export: - group service_desk_setting: diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 73b945d4274..5ceac6cad98 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -1032,6 +1032,7 @@ PushRule: - commit_committer_check - regexp_uses_re2 - reject_non_dco_commits + - organization_id MergeRequest::CleanupSchedule: - id - scheduled_at diff --git a/spec/models/bulk_imports/failure_spec.rb b/spec/models/bulk_imports/failure_spec.rb index bbb5ad52fe1..7f583296fda 100644 --- a/spec/models/bulk_imports/failure_spec.rb +++ b/spec/models/bulk_imports/failure_spec.rb @@ -43,6 +43,25 @@ RSpec.describe BulkImports::Failure, type: :model, feature_category: :importers expect(failure.relation).to eq('test_relation') end end + + context 'when subrelation is nil' do + it 'returns relation' do + failure = described_class.new(pipeline_class: 'BulkImports::Common::Pipelines::WikiPipeline') + + expect(failure.relation).to eq('wiki') + end + end + + context 'when subrelation is present' do + it 'returns relation and subrelation' do + failure = described_class.new( + subrelation: 'subrelation', + pipeline_class: 'BulkImports::Common::Pipelines::WikiPipeline' + ) + + expect(failure.relation).to eq('wiki, subrelation') + end + end end describe '#exception_message=' do @@ -74,4 +93,12 @@ RSpec.describe BulkImports::Failure, type: :model, feature_category: :importers expect(failure.source_url.size).to eq(255) end end + + describe '#subrelation=' do + it 'truncates subrelation to 255 characters' do + failure = described_class.new + failure.subrelation = 'A' * 1000 + expect(failure.subrelation.size).to eq(255) + end + end end diff --git a/spec/models/ci/build_runner_session_spec.rb b/spec/models/ci/build_runner_session_spec.rb index dac7edbe6cc..198eb936497 100644 --- a/spec/models/ci/build_runner_session_spec.rb +++ b/spec/models/ci/build_runner_session_spec.rb @@ -183,11 +183,11 @@ RSpec.describe Ci::BuildRunnerSession, model: true, feature_category: :continuou let(:build_runner_session) { create(:ci_build_runner_session, build: new_build) } before do - stub_current_partition_id + stub_current_partition_id(ci_testing_partition_id_for_check_constraints) end it 'assigns the same partition id as the one that build has' do - expect(build_runner_session.partition_id).to eq(ci_testing_partition_id) + expect(build_runner_session.partition_id).to eq(ci_testing_partition_id_for_check_constraints) end end end diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index 8741d347c36..67d163a3404 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -5601,14 +5601,14 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def let(:ci_build) { create(:ci_build, pipeline: new_pipeline) } before do - stub_current_partition_id + stub_current_partition_id(ci_testing_partition_id_for_check_constraints) end it 'includes partition_id in the token prefix' do prefix = ci_build.token.match(/^glcbt-([\h]+)_/) partition_prefix = prefix[1].to_i(16) - expect(partition_prefix).to eq(ci_testing_partition_id) + expect(partition_prefix).to eq(ci_testing_partition_id_for_check_constraints) end end diff --git a/spec/models/ci/build_trace_metadata_spec.rb b/spec/models/ci/build_trace_metadata_spec.rb index 866d94b4cbe..667f519ecf5 100644 --- a/spec/models/ci/build_trace_metadata_spec.rb +++ b/spec/models/ci/build_trace_metadata_spec.rb @@ -169,11 +169,11 @@ RSpec.describe Ci::BuildTraceMetadata, feature_category: :continuous_integration let(:metadata) { create(:ci_build_trace_metadata, build: new_build) } before do - stub_current_partition_id + stub_current_partition_id(ci_testing_partition_id_for_check_constraints) end it 'assigns the same partition id as the one that build has' do - expect(metadata.partition_id).to eq(ci_testing_partition_id) + expect(metadata.partition_id).to eq(ci_testing_partition_id_for_check_constraints) end end end diff --git a/spec/models/ci/job_variable_spec.rb b/spec/models/ci/job_variable_spec.rb index a56e6b6be43..8b1191a3930 100644 --- a/spec/models/ci/job_variable_spec.rb +++ b/spec/models/ci/job_variable_spec.rb @@ -49,15 +49,15 @@ RSpec.describe Ci::JobVariable, feature_category: :continuous_integration do let(:job_variable_2) { build(:ci_job_variable, job: ci_build) } before do - stub_current_partition_id + stub_current_partition_id(ci_testing_partition_id_for_check_constraints) end it 'creates job variables successfully', :aggregate_failures do described_class.bulk_insert!([job_variable, job_variable_2]) expect(described_class.count).to eq(2) - expect(described_class.first.partition_id).to eq(ci_testing_partition_id) - expect(described_class.last.partition_id).to eq(ci_testing_partition_id) + expect(described_class.first.partition_id).to eq(ci_testing_partition_id_for_check_constraints) + expect(described_class.last.partition_id).to eq(ci_testing_partition_id_for_check_constraints) end end end diff --git a/spec/models/ci/pending_build_spec.rb b/spec/models/ci/pending_build_spec.rb index 331522070df..076aad34a94 100644 --- a/spec/models/ci/pending_build_spec.rb +++ b/spec/models/ci/pending_build_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Ci::PendingBuild do +RSpec.describe Ci::PendingBuild, feature_category: :continuous_integration do let_it_be(:project) { create(:project) } let_it_be(:pipeline) { create(:ci_pipeline, project: project) } @@ -200,21 +200,20 @@ RSpec.describe Ci::PendingBuild do include Ci::PartitioningHelpers before do - stub_current_partition_id + stub_current_partition_id(ci_testing_partition_id_for_check_constraints) end let(:new_pipeline ) { create(:ci_pipeline, project: pipeline.project) } let(:new_build) { create(:ci_build, pipeline: new_pipeline) } it 'assigns the same partition id as the one that build has', :aggregate_failures do - expect(new_build.partition_id).to eq ci_testing_partition_id - expect(new_build.partition_id).not_to eq pipeline.partition_id + expect(new_build.partition_id).to eq ci_testing_partition_id_for_check_constraints described_class.upsert_from_build!(build) described_class.upsert_from_build!(new_build) expect(build.reload.queuing_entry.partition_id).to eq pipeline.partition_id - expect(new_build.reload.queuing_entry.partition_id).to eq ci_testing_partition_id + expect(new_build.reload.queuing_entry.partition_id).to eq ci_testing_partition_id_for_check_constraints end end diff --git a/spec/models/ci/resource_group_spec.rb b/spec/models/ci/resource_group_spec.rb index 9e98cc884de..e2aaeb2a18e 100644 --- a/spec/models/ci/resource_group_spec.rb +++ b/spec/models/ci/resource_group_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe Ci::ResourceGroup do +RSpec.describe Ci::ResourceGroup, feature_category: :continuous_delivery do let_it_be(:group) { create(:group) } it_behaves_like 'cleanup by a loose foreign key' do @@ -37,7 +37,7 @@ RSpec.describe Ci::ResourceGroup do include Ci::PartitioningHelpers before do - stub_current_partition_id + stub_current_partition_id(ci_testing_partition_id_for_check_constraints) end subject { resource_group.assign_resource_to(build) } @@ -78,7 +78,7 @@ RSpec.describe Ci::ResourceGroup do include Ci::PartitioningHelpers before do - stub_current_partition_id + stub_current_partition_id(ci_testing_partition_id_for_check_constraints) end subject { resource_group.release_resource_from(build) } diff --git a/spec/models/ci/running_build_spec.rb b/spec/models/ci/running_build_spec.rb index 7f254bd235c..0a81eaf9ac0 100644 --- a/spec/models/ci/running_build_spec.rb +++ b/spec/models/ci/running_build_spec.rb @@ -54,21 +54,20 @@ RSpec.describe Ci::RunningBuild, feature_category: :continuous_integration do include Ci::PartitioningHelpers before do - stub_current_partition_id + stub_current_partition_id(ci_testing_partition_id_for_check_constraints) end let(:new_pipeline ) { create(:ci_pipeline, project: pipeline.project) } let(:new_build) { create(:ci_build, :running, pipeline: new_pipeline, runner: runner) } it 'assigns the same partition id as the one that build has', :aggregate_failures do - expect(new_build.partition_id).to eq ci_testing_partition_id - expect(new_build.partition_id).not_to eq pipeline.partition_id + expect(new_build.partition_id).to eq ci_testing_partition_id_for_check_constraints described_class.upsert_shared_runner_build!(build) described_class.upsert_shared_runner_build!(new_build) expect(build.reload.runtime_metadata.partition_id).to eq pipeline.partition_id - expect(new_build.reload.runtime_metadata.partition_id).to eq ci_testing_partition_id + expect(new_build.reload.runtime_metadata.partition_id).to eq ci_testing_partition_id_for_check_constraints end end diff --git a/spec/models/ci/sources/pipeline_spec.rb b/spec/models/ci/sources/pipeline_spec.rb index 036708ed61e..6bc848fadb8 100644 --- a/spec/models/ci/sources/pipeline_spec.rb +++ b/spec/models/ci/sources/pipeline_spec.rb @@ -44,12 +44,12 @@ RSpec.describe Ci::Sources::Pipeline, feature_category: :continuous_integration let(:source_pipeline) { create(:ci_sources_pipeline, pipeline: new_pipeline) } before do - stub_current_partition_id + stub_current_partition_id(ci_testing_partition_id_for_check_constraints) end it 'assigns partition_id and source_partition_id from pipeline and source_job', :aggregate_failures do - expect(source_pipeline.partition_id).to eq(ci_testing_partition_id) - expect(source_pipeline.source_partition_id).to eq(ci_testing_partition_id) + expect(source_pipeline.partition_id).to eq(ci_testing_partition_id_for_check_constraints) + expect(source_pipeline.source_partition_id).to eq(ci_testing_partition_id_for_check_constraints) end end end diff --git a/spec/models/concerns/semantic_versionable_spec.rb b/spec/models/concerns/semantic_versionable_spec.rb index 500b4564fbe..dc476d603ac 100644 --- a/spec/models/concerns/semantic_versionable_spec.rb +++ b/spec/models/concerns/semantic_versionable_spec.rb @@ -5,19 +5,23 @@ require 'spec_helper' RSpec.describe SemanticVersionable, feature_category: :mlops do using RSpec::Parameterized::TableSyntax + before_all do + ActiveRecord::Schema.define do |_t| + create_table :_test_semantic_versions, force: true do |t| + t.integer :semver_major + t.integer :semver_minor + t.integer :semver_patch + t.string :semver_prerelease + end + end + end + let(:model_class) do Class.new(ActiveRecord::Base) do include SemanticVersionable semver_method :semver - # we need a table for the dummy class to operate - self.table_name = 'ml_model_versions' - - def self.name - 'Ml::ModelVersion' - end - - attr_accessor :major, :minor, :patch, :prerelease + self.table_name = '_test_semantic_versions' end end @@ -94,4 +98,22 @@ RSpec.describe SemanticVersionable, feature_category: :mlops do expect(model_instance.valid?).to be true end end + + describe 'scopes' do + let(:first_release) { model_class.create!(semver: '1.0.1') } + let(:second_release) { model_class.create!(semver: '3.0.1') } + let(:patch) { model_class.create!(semver: '2.0.1') } + + describe '.order_by_semantic_version_asc' do + it 'orders the versions by semantic order ascending' do + expect(model_class.order_by_semantic_version_asc).to eq([first_release, patch, second_release]) + end + end + + describe '.order_by_semantic_version_desc' do + it 'orders the versions by semantic order descending' do + expect(model_class.order_by_semantic_version_desc).to eq([second_release, patch, first_release]) + end + end + end end diff --git a/spec/models/customer_relations/contact_state_counts_spec.rb b/spec/models/customer_relations/contact_state_counts_spec.rb index a19f6f08489..de9da7cf88d 100644 --- a/spec/models/customer_relations/contact_state_counts_spec.rb +++ b/spec/models/customer_relations/contact_state_counts_spec.rb @@ -4,7 +4,7 @@ require 'spec_helper' RSpec.describe CustomerRelations::ContactStateCounts do let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let(:counter) { described_class.new(user, group, params) } let(:params) { {} } diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index ce2c9ced47f..69723533943 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -3260,8 +3260,8 @@ RSpec.describe Group, feature_category: :groups_and_projects do end describe '#crm_enabled?' do - it 'returns false where no crm_settings exist' do - expect(group.crm_enabled?).to be_falsey + it 'returns true where no crm_settings exist' do + expect(group.crm_enabled?).to be_truthy end it 'returns false where crm_settings.state is disabled' do @@ -3277,7 +3277,7 @@ RSpec.describe Group, feature_category: :groups_and_projects do end it 'returns true where crm_settings.state is enabled for subgroup' do - subgroup = create(:group, :crm_enabled, parent: group) + subgroup = create(:group, parent: group) expect(subgroup.crm_enabled?).to be_truthy end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index cae5291fb56..1a7f2e6614b 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -5402,57 +5402,32 @@ RSpec.describe Project, factory_default: :keep, feature_category: :groups_and_pr describe '#has_ci_config_file?' do subject(:has_ci_config_file) { project.has_ci_config_file? } - # Extract these from `shared_examples` when the FF ci_refactor_has_ci_config_file is removed. - shared_examples '#has_ci_config_file?' do - context 'when the repository does not exist' do - let_it_be(:project) { create(:project) } + context 'when the repository does not exist' do + let_it_be(:project) { create(:project) } - it { is_expected.to be_falsey } - end - - context 'when the repository has a .gitlab-ci.yml file' do - let_it_be(:project) { create(:project, :small_repo, files: { '.gitlab-ci.yml' => 'test' }) } - - it { is_expected.to be_truthy } - end - - context 'when the repository does not have a .gitlab-ci.yml file' do - let_it_be(:project) { create(:project, :small_repo, files: { 'README.md' => 'hello' }) } - - it { is_expected.to be_falsey } - end + it { is_expected.to be_falsey } end - context 'when the FF ci_refactor_has_ci_config_file is enabled' do - it_behaves_like '#has_ci_config_file?' + context 'when the repository has a .gitlab-ci.yml file' do + let_it_be(:project) { create(:project, :small_repo, files: { '.gitlab-ci.yml' => 'test' }) } - context 'when the repository has a custom CI config file' do - let_it_be(:project) { create(:project, :small_repo, files: { 'my_ci_file.yml' => 'test' }) } - - before do - project.ci_config_path = 'my_ci_file.yml' - end - - it { is_expected.to be_truthy } - end + it { is_expected.to be_truthy } end - context 'when the FF ci_refactor_has_ci_config_file is disabled' do + context 'when the repository does not have a .gitlab-ci.yml file' do + let_it_be(:project) { create(:project, :small_repo, files: { 'README.md' => 'hello' }) } + + it { is_expected.to be_falsey } + end + + context 'when the repository has a custom CI config file' do + let_it_be(:project) { create(:project, :small_repo, files: { 'my_ci_file.yml' => 'test' }) } + before do - stub_feature_flags(ci_refactor_has_ci_config_file: false) + project.ci_config_path = 'my_ci_file.yml' end - it_behaves_like '#has_ci_config_file?' - - context 'when the repository has a custom CI config file' do - let_it_be(:project) { create(:project, :small_repo, files: { 'my_ci_file.yml' => 'test' }) } - - before do - project.ci_config_path = 'my_ci_file.yml' - end - - it { is_expected.to be_falsey } - end + it { is_expected.to be_truthy } end end diff --git a/spec/models/repository_spec.rb b/spec/models/repository_spec.rb index e5374f92846..b6cb2464605 100644 --- a/spec/models/repository_spec.rb +++ b/spec/models/repository_spec.rb @@ -4072,20 +4072,6 @@ RSpec.describe Repository, feature_category: :source_code_management do it { is_expected.to eq(::Gitlab::Git::SHA256_BLANK_SHA) } end - - context 'when feature flag is disabled' do - before do - stub_feature_flags(determine_blank_ref_based_on_gitaly_object_format: false) - end - - it { is_expected.to eq(::Gitlab::Git::SHA1_BLANK_SHA) } - - context 'for a SHA256 repository' do - let_it_be(:project) { create(:project, :empty_repo, object_format: Repository::FORMAT_SHA256) } - - it { is_expected.to eq(::Gitlab::Git::SHA1_BLANK_SHA) } - end - end end context 'for missing repository' do @@ -4094,14 +4080,6 @@ RSpec.describe Repository, feature_category: :source_code_management do end it { is_expected.to eq(::Gitlab::Git::SHA1_BLANK_SHA) } - - context 'when feature flag is disabled' do - before do - stub_feature_flags(determine_blank_ref_based_on_gitaly_object_format: false) - end - - it { is_expected.to eq(::Gitlab::Git::SHA1_BLANK_SHA) } - end end end diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb index 4632fcca12a..f9712b9735d 100644 --- a/spec/policies/group_policy_spec.rb +++ b/spec/policies/group_policy_spec.rb @@ -8,7 +8,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do using RSpec::Parameterized::TableSyntax context 'public group with no user' do - let(:group) { create(:group, :public, :crm_enabled) } + let(:group) { create(:group, :public) } let(:current_user) { nil } specify do @@ -23,7 +23,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do end context 'public group with user who is not a member' do - let(:group) { create(:group, :public, :crm_enabled) } + let(:group) { create(:group, :public) } let(:current_user) { create(:user) } specify do @@ -38,7 +38,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do end context 'private group that has been invited to a public project and with no user' do - let(:project) { create(:project, :public, group: create(:group, :crm_enabled)) } + let(:project) { create(:project, :public, group: create(:group)) } let(:current_user) { nil } before do @@ -53,7 +53,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do end context 'private group that has been invited to a public project and with a foreign user' do - let(:project) { create(:project, :public, group: create(:group, :crm_enabled)) } + let(:project) { create(:project, :public, group: create(:group)) } let(:current_user) { create(:user) } before do @@ -78,7 +78,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do it { expect_allowed(*(public_permissions - [:read_counts])) } context 'in subgroups' do - let(:subgroup) { create(:group, :private, :crm_enabled, parent: group) } + let(:subgroup) { create(:group, :private, parent: group) } let(:project) { create(:project, namespace: subgroup) } it { expect_allowed(*(public_permissions - [:read_counts])) } @@ -274,7 +274,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do describe 'private nested group use the highest access level from the group and inherited permissions' do let_it_be(:nested_group) do - create(:group, :private, :owner_subgroup_creation_only, :crm_enabled, parent: group) + create(:group, :private, :owner_subgroup_creation_only, parent: group) end before_all do @@ -378,7 +378,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do let(:current_user) { owner } context 'when the group share_with_group_lock is enabled' do - let(:group) { create(:group, :crm_enabled, share_with_group_lock: true, parent: parent) } + let(:group) { create(:group, share_with_group_lock: true, parent: parent) } before do group.add_owner(owner) @@ -386,10 +386,10 @@ RSpec.describe GroupPolicy, feature_category: :system_access do context 'when the parent group share_with_group_lock is enabled' do context 'when the group has a grandparent' do - let(:parent) { create(:group, :crm_enabled, share_with_group_lock: true, parent: grandparent) } + let(:parent) { create(:group, share_with_group_lock: true, parent: grandparent) } context 'when the grandparent share_with_group_lock is enabled' do - let(:grandparent) { create(:group, :crm_enabled, share_with_group_lock: true) } + let(:grandparent) { create(:group, share_with_group_lock: true) } context 'when the current_user owns the parent' do before do @@ -415,7 +415,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do end context 'when the grandparent share_with_group_lock is disabled' do - let(:grandparent) { create(:group, :crm_enabled) } + let(:grandparent) { create(:group) } context 'when the current_user owns the parent' do before do @@ -432,7 +432,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do end context 'when the group does not have a grandparent' do - let(:parent) { create(:group, :crm_enabled, share_with_group_lock: true) } + let(:parent) { create(:group, share_with_group_lock: true) } context 'when the current_user owns the parent' do before do @@ -449,7 +449,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do end context 'when the parent group share_with_group_lock is disabled' do - let(:parent) { create(:group, :crm_enabled) } + let(:parent) { create(:group) } it { expect_allowed(:change_share_with_group_lock) } end @@ -905,14 +905,14 @@ RSpec.describe GroupPolicy, feature_category: :system_access do end it_behaves_like 'clusterable policies' do - let(:clusterable) { create(:group, :crm_enabled) } + let(:clusterable) { create(:group) } let(:cluster) do create(:cluster, :provided_by_gcp, :group, groups: [clusterable]) end end describe 'update_max_artifacts_size' do - let(:group) { create(:group, :public, :crm_enabled) } + let(:group) { create(:group, :public) } context 'when no user' do let(:current_user) { nil } @@ -942,7 +942,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do end describe 'design activity' do - let_it_be(:group) { create(:group, :public, :crm_enabled) } + let_it_be(:group) { create(:group, :public) } let(:current_user) { nil } @@ -1256,7 +1256,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do it_behaves_like 'Self-managed Core resource access tokens' context 'support bot' do - let_it_be_with_refind(:group) { create(:group, :private, :crm_enabled) } + let_it_be_with_refind(:group) { create(:group, :private) } let_it_be(:current_user) { Users::Internal.support_bot } before do @@ -1266,7 +1266,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do it { expect_disallowed(:read_label) } context 'when group hierarchy has a project with service desk enabled' do - let_it_be(:subgroup) { create(:group, :private, :crm_enabled, parent: group) } + let_it_be(:subgroup) { create(:group, :private, parent: group) } let_it_be(:project) { create(:project, group: subgroup, service_desk_enabled: true) } it { expect_allowed(:read_label) } @@ -1635,7 +1635,7 @@ RSpec.describe GroupPolicy, feature_category: :system_access do let(:current_user) { owner } before do - group.crm_settings.update!(enabled: false) + create(:crm_settings, group: group, enabled: false) end it { is_expected.to be_disallowed(:read_crm_contact) } diff --git a/spec/policies/issue_policy_spec.rb b/spec/policies/issue_policy_spec.rb index 94b05e50ef6..6bcc42df418 100644 --- a/spec/policies/issue_policy_spec.rb +++ b/spec/policies/issue_policy_spec.rb @@ -489,7 +489,7 @@ RSpec.describe IssuePolicy, feature_category: :team_planning do describe 'crm permissions' do let(:user) { create(:user) } - let(:subgroup) { create(:group, :crm_enabled, parent: create(:group, :crm_enabled)) } + let(:subgroup) { create(:group, parent: create(:group)) } let(:project) { create(:project, group: subgroup) } let(:issue) { create(:issue, project: project) } let(:policies) { described_class.new(user, issue) } @@ -522,7 +522,7 @@ RSpec.describe IssuePolicy, feature_category: :team_planning do end context 'when crm disabled on subgroup' do - let(:subgroup) { create(:group, parent: create(:group, :crm_enabled)) } + let(:subgroup) { create(:group, :crm_disabled, parent: create(:group)) } it 'is disallowed' do subgroup.parent.add_reporter(user) diff --git a/spec/requests/api/commit_statuses_spec.rb b/spec/requests/api/commit_statuses_spec.rb index 9247d9366b2..c49e544c175 100644 --- a/spec/requests/api/commit_statuses_spec.rb +++ b/spec/requests/api/commit_statuses_spec.rb @@ -543,11 +543,12 @@ RSpec.describe API::CommitStatuses, :clean_gitlab_redis_cache, feature_category: end context 'with partitions', :ci_partitionable do - let(:current_partition_id) { ci_testing_partition_id } + include Ci::PartitioningHelpers + + let(:current_partition_id) { ci_testing_partition_id_for_check_constraints } before do - allow(Ci::Pipeline) - .to receive(:current_partition_value) { current_partition_id } + stub_current_partition_id(ci_testing_partition_id_for_check_constraints) end it 'creates records in the current partition' do diff --git a/spec/requests/api/graphql/crm/contacts_spec.rb b/spec/requests/api/graphql/crm/contacts_spec.rb index 3ae19de63ed..b6785491388 100644 --- a/spec/requests/api/graphql/crm/contacts_spec.rb +++ b/spec/requests/api/graphql/crm/contacts_spec.rb @@ -6,7 +6,7 @@ RSpec.describe 'getting CRM contacts', feature_category: :service_desk do include GraphqlHelpers let_it_be(:current_user) { create(:user) } - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let_it_be(:contact_a) do create( diff --git a/spec/requests/api/graphql/mutations/branch_rules/destroy_spec.rb b/spec/requests/api/graphql/mutations/branch_rules/destroy_spec.rb new file mode 100644 index 00000000000..d6093601f68 --- /dev/null +++ b/spec/requests/api/graphql/mutations/branch_rules/destroy_spec.rb @@ -0,0 +1,60 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe 'Deleting a BranchRule', feature_category: :source_code_management do + include GraphqlHelpers + + let_it_be(:current_user) { create(:user) } + let_it_be(:protected_branch) { create(:protected_branch) } + let_it_be(:project) { protected_branch.project } + + let(:branch_rule) { Projects::BranchRule.new(project, protected_branch) } + let(:global_id) { branch_rule.to_global_id.to_s } + let(:mutation) { graphql_mutation(:branch_rule_delete, { id: global_id }) } + let(:mutation_response) { graphql_mutation_response(:branch_rule_delete) } + + subject(:mutation_request) { post_graphql_mutation(mutation, current_user: current_user) } + + context 'when the user does not have permission' do + it_behaves_like 'a mutation that returns top-level errors', + errors: [Gitlab::Graphql::Authorize::AuthorizeResource::RESOURCE_ACCESS_ERROR] + + it 'does not destroy the BranchRule' do + expect { mutation_request }.not_to change { ProtectedBranch.count } + end + end + + context 'when the user has permission' do + before_all do + project.add_maintainer(current_user) + end + + it 'destroys the BranchRule' do + expect { mutation_request }.to change { ProtectedBranch.count }.by(-1) + end + + it 'returns an empty BranchRule' do + mutation_request + + expect(mutation_response).to have_key('branchRule') + expect(mutation_response['branchRule']).to be_nil + end + + context 'when an invalid global id is given' do + let(:global_id) { project.to_gid.to_s } + let(:error_message) { %("#{global_id}" does not represent an instance of Projects::BranchRule) } + let(:global_id_error) { a_hash_including('message' => a_string_including(error_message)) } + + it 'returns an error' do + mutation_request + + expect(graphql_errors).to include(global_id_error) + end + + it 'does not destroy the BranchRule' do + expect { mutation_request }.not_to change { ProtectedBranch.count } + end + end + end +end diff --git a/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb b/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb index cdab267162e..05e0c997557 100644 --- a/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb +++ b/spec/requests/api/graphql/mutations/issues/set_crm_contacts_spec.rb @@ -6,8 +6,8 @@ RSpec.describe 'Setting issues crm contacts', feature_category: :service_desk do include GraphqlHelpers let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group, :crm_enabled) } - let_it_be(:subgroup) { create(:group, :crm_enabled, parent: group) } + let_it_be(:group) { create(:group) } + let_it_be(:subgroup) { create(:group, parent: group) } let_it_be(:project) { create(:project, group: subgroup) } let_it_be(:contacts) { create_list(:contact, 4, group: group) } @@ -129,7 +129,7 @@ RSpec.describe 'Setting issues crm contacts', feature_category: :service_desk do end context 'when the contact belongs to a different group' do - let(:group2) { create(:group, :crm_enabled) } + let(:group2) { create(:group) } let(:contact) { create(:contact, group: group2) } let(:contact_ids) { [global_id_of(contact)] } @@ -171,8 +171,10 @@ RSpec.describe 'Setting issues crm contacts', feature_category: :service_desk do end context 'when crm_enabled is false' do - let(:issue) { create(:issue) } - let(:initial_contacts) { [] } + let_it_be(:group2) { create(:group, :crm_disabled) } + let_it_be(:project2) { create(:project, group: group2) } + let_it_be(:issue) { create(:issue, project: project2) } + let_it_be(:initial_contacts) { [] } it 'raises expected error' do issue.project.add_reporter(user) diff --git a/spec/requests/groups/crm/contacts_controller_spec.rb b/spec/requests/groups/crm/contacts_controller_spec.rb index 4916ce60108..48e9bfe6ef0 100644 --- a/spec/requests/groups/crm/contacts_controller_spec.rb +++ b/spec/requests/groups/crm/contacts_controller_spec.rb @@ -24,7 +24,7 @@ RSpec.describe Groups::Crm::ContactsController, feature_category: :team_planning shared_examples 'ok response with index template if authorized' do context 'private group' do - let(:group) { create(:group, :private, :crm_enabled) } + let(:group) { create(:group, :private) } context 'with authorized user' do before do @@ -37,13 +37,13 @@ RSpec.describe Groups::Crm::ContactsController, feature_category: :team_planning end context 'when crm_enabled is false' do - let(:group) { create(:group, :private) } + let(:group) { create(:group, :private, :crm_disabled) } it_behaves_like 'response with 404 status' end context 'when subgroup' do - let(:group) { create(:group, :private, :crm_enabled, parent: create(:group)) } + let(:group) { create(:group, :private, parent: create(:group)) } it_behaves_like 'response with 404 status' end @@ -68,7 +68,7 @@ RSpec.describe Groups::Crm::ContactsController, feature_category: :team_planning end context 'public group' do - let(:group) { create(:group, :public, :crm_enabled) } + let(:group) { create(:group, :public) } context 'with anonymous user' do it_behaves_like 'response with 404 status' diff --git a/spec/requests/groups/crm/organizations_controller_spec.rb b/spec/requests/groups/crm/organizations_controller_spec.rb index 3e7e9a8e878..c180365ae55 100644 --- a/spec/requests/groups/crm/organizations_controller_spec.rb +++ b/spec/requests/groups/crm/organizations_controller_spec.rb @@ -24,7 +24,7 @@ RSpec.describe Groups::Crm::OrganizationsController, feature_category: :team_pla shared_examples 'ok response with index template if authorized' do context 'private group' do - let(:group) { create(:group, :private, :crm_enabled) } + let(:group) { create(:group, :private) } context 'with authorized user' do before do @@ -37,13 +37,13 @@ RSpec.describe Groups::Crm::OrganizationsController, feature_category: :team_pla end context 'when crm_enabled is false' do - let(:group) { create(:group, :private) } + let(:group) { create(:group, :private, :crm_disabled) } it_behaves_like 'response with 404 status' end context 'when subgroup' do - let(:group) { create(:group, :private, :crm_enabled, parent: create(:group)) } + let(:group) { create(:group, :private, parent: create(:group)) } it_behaves_like 'response with 404 status' end @@ -68,7 +68,7 @@ RSpec.describe Groups::Crm::OrganizationsController, feature_category: :team_pla end context 'public group' do - let(:group) { create(:group, :public, :crm_enabled) } + let(:group) { create(:group, :public) } context 'with anonymous user' do it_behaves_like 'response with 404 status' diff --git a/spec/requests/users_controller_spec.rb b/spec/requests/users_controller_spec.rb index 0dbe9cdec71..899d17879ef 100644 --- a/spec/requests/users_controller_spec.rb +++ b/spec/requests/users_controller_spec.rb @@ -589,8 +589,6 @@ RSpec.describe UsersController, feature_category: :user_management do aimed_for_deletion_project.add_developer(private_user) create(:push_event, project: project, author: author) create(:push_event, project: aimed_for_deletion_project, author: author) - - subject end shared_examples_for 'renders contributed projects' do @@ -604,6 +602,10 @@ RSpec.describe UsersController, feature_category: :user_management do context "with format: #{format}" do let(:format) { format } + before do + subject + end + context 'with public profile' do let(:author) { public_user } @@ -632,6 +634,30 @@ RSpec.describe UsersController, feature_category: :user_management do end end end + + describe 'pagination' do + let(:author) { public_user } + let(:format) { :json } + let(:per_page_limit) { 2 } + + before do + allow(Kaminari.config).to receive(:default_per_page).and_return(per_page_limit) + + create_list(:project, per_page_limit + 1, :public, :small_repo).each do |small_project| + small_project.add_developer(author) + create(:push_event, project: small_project, author: author) + end + + subject + end + + it_behaves_like 'renders contributed projects' + + it 'paginates without count' do + expect(assigns(:contributed_projects).size).to eq(per_page_limit) + expect(assigns(:contributed_projects)).to be_a(Kaminari::PaginatableWithoutCount) + end + end end describe 'GET #starred' do diff --git a/spec/serializers/issue_sidebar_basic_entity_spec.rb b/spec/serializers/issue_sidebar_basic_entity_spec.rb index ef80bcd5eb1..a7e7730516a 100644 --- a/spec/serializers/issue_sidebar_basic_entity_spec.rb +++ b/spec/serializers/issue_sidebar_basic_entity_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe IssueSidebarBasicEntity do - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project, :repository, group: group) } let_it_be(:user) { create(:user, developer_projects: [project]) } let_it_be_with_reload(:issue) { create(:issue, project: project, assignees: [user]) } @@ -99,7 +99,7 @@ RSpec.describe IssueSidebarBasicEntity do end context 'with crm enabled' do - let(:subgroup) { create(:group, :crm_enabled, parent: group) } + let(:subgroup) { create(:group, parent: group) } it 'is true' do allow(CustomerRelations::Contact).to receive(:exists_for_group?).with(group).and_return(true) @@ -109,7 +109,7 @@ RSpec.describe IssueSidebarBasicEntity do end context 'with crm disabled' do - let(:subgroup) { create(:group, parent: group) } + let(:subgroup) { create(:group, :crm_disabled, parent: group) } it 'is false' do allow(CustomerRelations::Contact).to receive(:exists_for_group?).with(group).and_return(true) diff --git a/spec/services/ci/create_commit_status_service_spec.rb b/spec/services/ci/create_commit_status_service_spec.rb index ec200e24c8f..3c7346e3e2e 100644 --- a/spec/services/ci/create_commit_status_service_spec.rb +++ b/spec/services/ci/create_commit_status_service_spec.rb @@ -404,12 +404,13 @@ RSpec.describe Ci::CreateCommitStatusService, :clean_gitlab_redis_cache, feature end context 'with partitions', :ci_partitionable do - let(:current_partition_id) { ci_testing_partition_id } + include Ci::PartitioningHelpers + + let(:current_partition_id) { ci_testing_partition_id_for_check_constraints } let(:params) { { state: 'running' } } before do - allow(Ci::Pipeline) - .to receive(:current_partition_value) { current_partition_id } + stub_current_partition_id(ci_testing_partition_id_for_check_constraints) end it 'creates records in the current partition' do diff --git a/spec/services/customer_relations/contacts/create_service_spec.rb b/spec/services/customer_relations/contacts/create_service_spec.rb index 91aa51385e7..ac973f4a14b 100644 --- a/spec/services/customer_relations/contacts/create_service_spec.rb +++ b/spec/services/customer_relations/contacts/create_service_spec.rb @@ -12,7 +12,7 @@ RSpec.describe CustomerRelations::Contacts::CreateService, feature_category: :se subject(:response) { described_class.new(group: group, current_user: user, params: params).execute } context 'when user does not have permission' do - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } before_all do group.add_reporter(user) @@ -25,7 +25,7 @@ RSpec.describe CustomerRelations::Contacts::CreateService, feature_category: :se end context 'when user has permission' do - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } before_all do group.add_developer(user) diff --git a/spec/services/customer_relations/contacts/update_service_spec.rb b/spec/services/customer_relations/contacts/update_service_spec.rb index 105b5bad5f7..3dc1ddc5ab6 100644 --- a/spec/services/customer_relations/contacts/update_service_spec.rb +++ b/spec/services/customer_relations/contacts/update_service_spec.rb @@ -11,7 +11,7 @@ RSpec.describe CustomerRelations::Contacts::UpdateService, feature_category: :se describe '#execute' do context 'when the user has no permission' do - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let(:params) { { first_name: 'Gary' } } @@ -24,7 +24,7 @@ RSpec.describe CustomerRelations::Contacts::UpdateService, feature_category: :se end context 'when user has permission' do - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } before_all do group.add_developer(user) diff --git a/spec/services/customer_relations/organizations/create_service_spec.rb b/spec/services/customer_relations/organizations/create_service_spec.rb index 8748fe44763..0c313f7f925 100644 --- a/spec/services/customer_relations/organizations/create_service_spec.rb +++ b/spec/services/customer_relations/organizations/create_service_spec.rb @@ -6,7 +6,7 @@ RSpec.describe CustomerRelations::Organizations::CreateService, feature_category describe '#execute' do let_it_be(:user) { create(:user) } - let(:group) { create(:group, :crm_enabled) } + let(:group) { create(:group) } let(:params) { attributes_for(:crm_organization, group: group) } subject(:response) { described_class.new(group: group, current_user: user, params: params).execute } diff --git a/spec/services/customer_relations/organizations/update_service_spec.rb b/spec/services/customer_relations/organizations/update_service_spec.rb index f11b99b101e..0d8c6613400 100644 --- a/spec/services/customer_relations/organizations/update_service_spec.rb +++ b/spec/services/customer_relations/organizations/update_service_spec.rb @@ -11,7 +11,7 @@ RSpec.describe CustomerRelations::Organizations::UpdateService, feature_category describe '#execute' do context 'when the user has no permission' do - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let(:params) { { name: 'GitLab' } } @@ -24,7 +24,7 @@ RSpec.describe CustomerRelations::Organizations::UpdateService, feature_category end context 'when user has permission' do - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } before_all do group.add_developer(user) diff --git a/spec/services/gravatar_service_spec.rb b/spec/services/gravatar_service_spec.rb index 6ccb362cc5c..7fad688d355 100644 --- a/spec/services/gravatar_service_spec.rb +++ b/spec/services/gravatar_service_spec.rb @@ -13,7 +13,7 @@ RSpec.describe GravatarService, feature_category: :user_profile do it 'replaces the placeholders' do avatar_url = described_class.new.execute('user@example.com', 100, 2, username: 'user') - expect(avatar_url).to include("hash=#{Digest::MD5.hexdigest('user@example.com')}") + expect(avatar_url).to include("hash=#{Digest::SHA256.hexdigest('user@example.com')}") expect(avatar_url).to include("size=200") expect(avatar_url).to include("email=user%40example.com") expect(avatar_url).to include("username=user") diff --git a/spec/services/groups/transfer_service_spec.rb b/spec/services/groups/transfer_service_spec.rb index ce67c4c51fe..8a866b632bd 100644 --- a/spec/services/groups/transfer_service_spec.rb +++ b/spec/services/groups/transfer_service_spec.rb @@ -17,7 +17,7 @@ RSpec.describe Groups::TransferService, :sidekiq_inline, feature_category: :grou end let_it_be(:user) { create(:user) } - let_it_be(:new_parent_group) { create(:group, :public, :crm_enabled) } + let_it_be(:new_parent_group) { create(:group, :public) } let!(:group_member) { create(:group_member, :owner, group: group, user: user) } let(:transfer_service) { described_class.new(group, user) } diff --git a/spec/services/groups/update_service_spec.rb b/spec/services/groups/update_service_spec.rb index 0d160911eab..7ac3382672d 100644 --- a/spec/services/groups/update_service_spec.rb +++ b/spec/services/groups/update_service_spec.rb @@ -150,29 +150,29 @@ RSpec.describe Groups::UpdateService, feature_category: :groups_and_projects do context 'crm_enabled param' do context 'when no existing crm_settings' do - it 'when param not present, leave crm disabled' do + it 'when param not present, leave crm enabled' do params = {} described_class.new(public_group, user, params).execute updated_group = public_group.reload - expect(updated_group.crm_enabled?).to be_falsey - end - - it 'when param set true, enables crm' do - params = { crm_enabled: true } - - described_class.new(public_group, user, params).execute - updated_group = public_group.reload - expect(updated_group.crm_enabled?).to be_truthy end + + it 'when param set false, disables crm' do + params = { crm_enabled: false } + + described_class.new(public_group, user, params).execute + updated_group = public_group.reload + + expect(updated_group.crm_enabled?).to be_falsy + end end context 'with existing crm_settings' do it 'when param set true, enables crm' do params = { crm_enabled: true } - create(:crm_settings, group: public_group) + create(:crm_settings, group: public_group, enabled: false) described_class.new(public_group, user, params).execute @@ -192,7 +192,7 @@ RSpec.describe Groups::UpdateService, feature_category: :groups_and_projects do it 'when param not present, crm remains disabled' do params = {} - create(:crm_settings, group: public_group) + create(:crm_settings, group: public_group, enabled: false) described_class.new(public_group, user, params).execute diff --git a/spec/services/issues/create_service_spec.rb b/spec/services/issues/create_service_spec.rb index 7cd2cd8f564..2e662567952 100644 --- a/spec/services/issues/create_service_spec.rb +++ b/spec/services/issues/create_service_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe Issues::CreateService, feature_category: :team_planning do include AfterNextHelpers - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let_it_be_with_reload(:project) { create(:project, :public, group: group) } let_it_be(:user) { create(:user) } diff --git a/spec/services/issues/set_crm_contacts_service_spec.rb b/spec/services/issues/set_crm_contacts_service_spec.rb index 7d709bbd9c8..5ff16dbeda1 100644 --- a/spec/services/issues/set_crm_contacts_service_spec.rb +++ b/spec/services/issues/set_crm_contacts_service_spec.rb @@ -4,8 +4,8 @@ require 'spec_helper' RSpec.describe Issues::SetCrmContactsService, feature_category: :team_planning do let_it_be(:user) { create(:user) } - let_it_be(:group) { create(:group, :crm_enabled) } - let_it_be(:project) { create(:project, group: create(:group, :crm_enabled, parent: group)) } + let_it_be(:group) { create(:group) } + let_it_be(:project) { create(:project, group: create(:group, parent: group)) } let_it_be(:contacts) { create_list(:contact, 4, group: group) } let_it_be(:issue, reload: true) { create(:issue, project: project) } let_it_be(:issue_contact_1) do @@ -60,7 +60,7 @@ RSpec.describe Issues::SetCrmContactsService, feature_category: :team_planning d context 'but the crm setting is disabled' do let(:params) { { replace_ids: [contacts[1].id, contacts[2].id] } } - let(:subgroup_with_crm_disabled) { create(:group, parent: group) } + let(:subgroup_with_crm_disabled) { create(:group, :crm_disabled, parent: group) } let(:project_with_crm_disabled) { create(:project, group: subgroup_with_crm_disabled) } let(:issue_with_crm_disabled) { create(:issue, project: project_with_crm_disabled) } diff --git a/spec/services/issues/update_service_spec.rb b/spec/services/issues/update_service_spec.rb index e8bcdc2c44b..f6cbacaf760 100644 --- a/spec/services/issues/update_service_spec.rb +++ b/spec/services/issues/update_service_spec.rb @@ -7,7 +7,7 @@ RSpec.describe Issues::UpdateService, :mailer, feature_category: :team_planning let_it_be(:user2) { create(:user) } let_it_be(:user3) { create(:user) } let_it_be(:guest) { create(:user) } - let_it_be(:group) { create(:group, :public, :crm_enabled) } + let_it_be(:group) { create(:group, :public) } let_it_be(:project, reload: true) { create(:project, :repository, group: group) } let_it_be(:label) { create(:label, title: 'a', project: project) } let_it_be(:label2) { create(:label, title: 'b', project: project) } diff --git a/spec/services/projects/autocomplete_service_spec.rb b/spec/services/projects/autocomplete_service_spec.rb index 4bfbb1e3dd2..0ec6362761e 100644 --- a/spec/services/projects/autocomplete_service_spec.rb +++ b/spec/services/projects/autocomplete_service_spec.rb @@ -3,7 +3,7 @@ require 'spec_helper' RSpec.describe Projects::AutocompleteService, feature_category: :groups_and_projects do - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project, :public, group: group) } let_it_be(:owner) { create(:user) } let_it_be(:issue) { create(:issue, project: project, title: 'Issue 1') } diff --git a/spec/services/quick_actions/interpret_service_spec.rb b/spec/services/quick_actions/interpret_service_spec.rb index 2f1443cc297..4ea3467e33c 100644 --- a/spec/services/quick_actions/interpret_service_spec.rb +++ b/spec/services/quick_actions/interpret_service_spec.rb @@ -5,7 +5,7 @@ require 'spec_helper' RSpec.describe QuickActions::InterpretService, feature_category: :team_planning do include AfterNextHelpers - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let_it_be(:public_project) { create(:project, :public, group: group) } let_it_be(:repository_project) { create(:project, :repository) } let_it_be(:project) { public_project } diff --git a/spec/support/helpers/database/duplicate_indexes.yml b/spec/support/helpers/database/duplicate_indexes.yml index 6162c1f0791..55531f46c70 100644 --- a/spec/support/helpers/database/duplicate_indexes.yml +++ b/spec/support/helpers/database/duplicate_indexes.yml @@ -99,6 +99,13 @@ ml_models: p_ci_runner_machine_builds: index_p_ci_runner_machine_builds_on_runner_machine_id: - index_ci_runner_machine_builds_on_runner_machine_id +p_ci_job_artifacts: + p_ci_job_artifacts_project_id_file_type_id_idx: + - p_ci_job_artifacts_project_id_idx + p_ci_job_artifacts_project_id_created_at_id_idx: + - p_ci_job_artifacts_project_id_idx + p_ci_job_artifacts_project_id_id_idx1: + - p_ci_job_artifacts_project_id_idx pages_domains: index_pages_domains_on_project_id_and_enabled_until: - index_pages_domains_on_project_id diff --git a/spec/support/helpers/database/inject_failure_helpers.rb b/spec/support/helpers/database/inject_failure_helpers.rb index df98f45e69f..25b4d2a6f87 100644 --- a/spec/support/helpers/database/inject_failure_helpers.rb +++ b/spec/support/helpers/database/inject_failure_helpers.rb @@ -30,6 +30,14 @@ module Database end end + def fail_adding_concurrent_fk(from_table, to_table) + proc do + allow(migration_context).to receive(:add_concurrent_foreign_key).and_call_original + expect(migration_context).to receive(:add_concurrent_foreign_key).with(from_table, to_table, any_args) + .and_wrap_original(&fail_first_time) + end + end + def fail_removing_fk(from_table, to_table) proc do allow(migration_context.connection).to receive(:remove_foreign_key).and_call_original diff --git a/spec/support/shared_contexts/navbar_structure_context.rb b/spec/support/shared_contexts/navbar_structure_context.rb index 9188fa08335..1f958734bad 100644 --- a/spec/support/shared_contexts/navbar_structure_context.rb +++ b/spec/support/shared_contexts/navbar_structure_context.rb @@ -149,6 +149,16 @@ RSpec.shared_context 'group navbar structure' do [_("Issues"), _("Issue board"), _("Milestones"), (_('Iterations') if Gitlab.ee?)] end + let(:customer_relations_nav_item) do + { + nav_item: _('Customer relations'), + nav_sub_items: [ + _('Contacts'), + _('Organizations') + ] + } + end + let(:structure) do [ { diff --git a/spec/support/shared_contexts/policies/group_policy_shared_context.rb b/spec/support/shared_contexts/policies/group_policy_shared_context.rb index 094a78aa45f..509bc413b8d 100644 --- a/spec/support/shared_contexts/policies/group_policy_shared_context.rb +++ b/spec/support/shared_contexts/policies/group_policy_shared_context.rb @@ -8,7 +8,7 @@ RSpec.shared_context 'GroupPolicy context' do let_it_be(:owner) { create(:user) } let_it_be(:admin) { create(:admin) } let_it_be(:non_group_member) { create(:user) } - let_it_be(:group, refind: true) { create(:group, :private, :owner_subgroup_creation_only, :crm_enabled) } + let_it_be(:group, refind: true) { create(:group, :private, :owner_subgroup_creation_only) } let(:public_permissions) do %i[ diff --git a/spec/views/shared/issuable/_sidebar.html.haml_spec.rb b/spec/views/shared/issuable/_sidebar.html.haml_spec.rb index 31f79c25073..a8307cc536e 100644 --- a/spec/views/shared/issuable/_sidebar.html.haml_spec.rb +++ b/spec/views/shared/issuable/_sidebar.html.haml_spec.rb @@ -11,7 +11,7 @@ RSpec.describe 'shared/issuable/_sidebar.html.haml' do end context 'project in a group' do - let_it_be(:group) { create(:group, :crm_enabled) } + let_it_be(:group) { create(:group) } let_it_be(:project) { create(:project, group: group) } let_it_be(:issue) { create(:issue, project: project) } let_it_be(:incident) { create(:incident, project: project) }