Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitlab/ci/global.gitlab-ci.yml2
-rw-r--r--.gitlab/ci/rails.gitlab-ci.yml14
-rw-r--r--.gitlab/ci/review-apps/main.gitlab-ci.yml1
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.checksum2
-rw-r--r--Gemfile.lock6
-rw-r--r--app/assets/javascripts/issues/create_merge_request_dropdown.js36
-rw-r--r--app/assets/javascripts/super_sidebar/components/flyout_menu.vue8
-rw-r--r--app/assets/javascripts/super_sidebar/components/nav_item.vue5
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue11
-rw-r--r--app/assets/javascripts/vue_shared/components/groups_list/groups_list.stories.js19
-rw-r--r--app/assets/javascripts/vue_shared/components/groups_list/groups_list.vue29
-rw-r--r--app/assets/javascripts/vue_shared/components/groups_list/groups_list_item.vue168
-rw-r--r--config/feature_flags/development/group_saml_jit_errors.yml8
-rw-r--r--config/feature_flags/development/telesign_callback.yml8
-rw-r--r--doc/administration/troubleshooting/postgresql.md6
-rw-r--r--doc/development/pipelines/internals.md9
-rw-r--r--doc/install/requirements.md1
-rw-r--r--doc/update/index.md309
-rw-r--r--doc/update/upgrading_from_source.md4
-rwxr-xr-xscripts/review_apps/review-apps.sh4
-rw-r--r--scripts/utils.sh35
-rw-r--r--spec/features/issues/user_creates_branch_and_merge_request_spec.rb19
-rw-r--r--spec/frontend/issues/create_merge_request_dropdown_spec.js25
-rw-r--r--spec/frontend/vue_merge_request_widget/mock_data.js2
-rw-r--r--spec/frontend/vue_shared/components/groups_list/groups_list_item_spec.js182
-rw-r--r--spec/frontend/vue_shared/components/groups_list/groups_list_spec.js34
-rw-r--r--spec/frontend/vue_shared/components/groups_list/mock_data.js35
-rw-r--r--spec/lib/gitlab/tracking/standard_context_spec.rb48
29 files changed, 627 insertions, 405 deletions
diff --git a/.gitlab/ci/global.gitlab-ci.yml b/.gitlab/ci/global.gitlab-ci.yml
index ca8d81737b8..b4a3232fcf7 100644
--- a/.gitlab/ci/global.gitlab-ci.yml
+++ b/.gitlab/ci/global.gitlab-ci.yml
@@ -509,4 +509,4 @@
url="${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/repository/files/scripts%2Futils.sh/raw?ref=${CI_COMMIT_SHA}"
curl -f --header "Private-Token: ${PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE}" "${url}" --create-dirs --output scripts/utils.sh
- source scripts/utils.sh
- - download_files ${FILES_TO_DOWNLOAD}
+ - run_timed_command "download_files ${FILES_TO_DOWNLOAD}"
diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml
index 2844669a89d..5b654627465 100644
--- a/.gitlab/ci/rails.gitlab-ci.yml
+++ b/.gitlab/ci/rails.gitlab-ci.yml
@@ -447,6 +447,7 @@ rspec:artifact-collector ee:
rspec:coverage:
extends:
- .coverage-base
+ - .fast-no-clone-job
- .rails:rules:rspec-coverage
stage: post-test
needs:
@@ -477,7 +478,20 @@ rspec:coverage:
# Memory jobs
- job: memory-on-boot
optional: true
+ variables:
+ FILES_TO_DOWNLOAD: >
+ config/bundler_setup.rb
+ Gemfile
+ Gemfile.lock
+ scripts/merge-simplecov
+ spec/simplecov_env_core.rb
+ spec/simplecov_env.rb
+ before_script:
+ - !reference [".fast-no-clone-job", before_script]
+ - run_timed_command "download_local_gems"
+ - !reference [".coverage-base", before_script]
script:
+ - chmod u+x scripts/merge-simplecov # Not the right permissions when downloading the script via the API.
- run_timed_command "bundle exec scripts/merge-simplecov"
coverage: '/LOC \((\d+\.\d+%)\) covered.$/'
artifacts:
diff --git a/.gitlab/ci/review-apps/main.gitlab-ci.yml b/.gitlab/ci/review-apps/main.gitlab-ci.yml
index f97aa445310..e94455c2893 100644
--- a/.gitlab/ci/review-apps/main.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/main.gitlab-ci.yml
@@ -69,6 +69,7 @@ review-build-cng:
GITLAB_REPO_URL: ${CI_PROJECT_URL}
GITLAB_IMAGE_REPOSITORY: "registry.gitlab.com/gitlab-org/build/cng-mirror"
GITLAB_IMAGE_SUFFIX: "ee"
+ GITLAB_REVIEW_APP_BASE_CONFIG_FILE: "scripts/review_apps/base-config.yaml"
GITLAB_HELM_CHART_REF: "75b1486a9aec212d0f49ef1251526d8e51004bbc" # 7.0.1: https://gitlab.com/gitlab-org/charts/gitlab/-/commit/75b1486a9aec212d0f49ef1251526d8e51004bbc
environment:
name: review/${CI_COMMIT_REF_SLUG}${SCHEDULE_TYPE} # No separator for SCHEDULE_TYPE so it's compatible as before and looks nice without it
diff --git a/Gemfile b/Gemfile
index c9f8f09e7f3..59145e353f6 100644
--- a/Gemfile
+++ b/Gemfile
@@ -120,7 +120,7 @@ gem 'gitlab_omniauth-ldap', '~> 2.2.0', require: 'omniauth-ldap'
gem 'net-ldap', '~> 0.17.1'
# API
-gem 'grape', '~> 1.7.0'
+gem 'grape', '~> 1.7.1'
gem 'grape-entity', '~> 0.10.0'
gem 'rack-cors', '~> 1.1.1', require: 'rack/cors'
gem 'grape-swagger', '~> 1.6.1', group: [:development, :test]
diff --git a/Gemfile.checksum b/Gemfile.checksum
index 9ca019df145..d785b0e030f 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -254,7 +254,7 @@
{"name":"googleapis-common-protos-types","version":"1.5.0","platform":"ruby","checksum":"5769cf7376abc86ef7f5897a4aaca1d5c5a3c49ddabeddd2c251fcf8155f858b"},
{"name":"googleauth","version":"1.3.0","platform":"ruby","checksum":"51dd7362353cf1e90a2d01e1fb94321ae3926c776d4dc4a79db65230217ffcc2"},
{"name":"gpgme","version":"2.0.22","platform":"ruby","checksum":"7c6904952afdd0bf2c7c3ed6de98a5143f86c6b7390dbcd9d7012bddfa3ec862"},
-{"name":"grape","version":"1.7.0","platform":"ruby","checksum":"88331a9627d7e61525f82b012450b345cec81f6152c91026d3909826baf66f51"},
+{"name":"grape","version":"1.7.1","platform":"ruby","checksum":"6b679d8918ee3dc19b0da95a5069dc95a71a15cf5788f5f787bb2ededf58cbb6"},
{"name":"grape-entity","version":"0.10.0","platform":"ruby","checksum":"9aed1e7cbbc96d9e73f72e5f32c776d4ba8a5baf54c3acda2682008dba2b2cfe"},
{"name":"grape-path-helpers","version":"1.7.1","platform":"ruby","checksum":"2e27271a20d4073e3a3b2b955425c7f803e198be3ba8f6e59e3d59643c5381e2"},
{"name":"grape-swagger","version":"1.6.1","platform":"ruby","checksum":"0fd2d38476524b66e8d06de71e6c481d34286d895b12161f5df4427d66d5c69f"},
diff --git a/Gemfile.lock b/Gemfile.lock
index a321f3be7fc..a9e0754dc7b 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -768,12 +768,12 @@ GEM
signet (>= 0.16, < 2.a)
gpgme (2.0.22)
mini_portile2 (~> 2.7)
- grape (1.7.0)
+ grape (1.7.1)
activesupport
builder
dry-types (>= 1.1)
mustermann-grape (~> 1.0.0)
- rack (>= 1.3.0)
+ rack (>= 1.3.0, < 3)
rack-accept
grape-entity (0.10.0)
activesupport (>= 3.0.0)
@@ -1841,7 +1841,7 @@ DEPENDENCIES
google-cloud-storage (~> 1.44.0)
google-protobuf (~> 3.23, >= 3.23.4)
gpgme (~> 2.0.22)
- grape (~> 1.7.0)
+ grape (~> 1.7.1)
grape-entity (~> 0.10.0)
grape-path-helpers (~> 1.7.1)
grape-swagger (~> 1.6.1)
diff --git a/app/assets/javascripts/issues/create_merge_request_dropdown.js b/app/assets/javascripts/issues/create_merge_request_dropdown.js
index de0334b4ffe..98888f9f9b2 100644
--- a/app/assets/javascripts/issues/create_merge_request_dropdown.js
+++ b/app/assets/javascripts/issues/create_merge_request_dropdown.js
@@ -137,8 +137,6 @@ export default class CreateMergeRequestDropdown {
this.refInput.addEventListener('keyup', this.onChangeInput.bind(this));
// Detect when user clicks inside the input to apply the suggested ref
this.refInput.addEventListener('click', this.onChangeInput.bind(this));
- // Detect when user clicks outside the input to apply the suggested ref
- this.refInput.addEventListener('blur', this.onChangeInput.bind(this));
// Detect when user presses tab to apply the suggested ref
this.refInput.addEventListener('keydown', CreateMergeRequestDropdown.processTab.bind(this));
}
@@ -178,8 +176,16 @@ export default class CreateMergeRequestDropdown {
createBranch(navigateToBranch = true) {
this.isCreatingBranch = true;
+ const endpoint = createEndpoint(
+ this.projectPath,
+ mergeUrlParams(
+ { ref: this.refInput.value, branch_name: this.branchInput.value },
+ this.createBranchPath,
+ ),
+ );
+
return axios
- .post(createEndpoint(this.projectPath, this.createBranchPath), {
+ .post(endpoint, {
confidential_issue_project_id: canCreateConfidentialMergeRequest() ? this.projectId : null,
})
.then(({ data }) => {
@@ -407,9 +413,6 @@ export default class CreateMergeRequestDropdown {
// If the input is empty, use the original value generated by the backend.
if (!value) {
- this.createBranchPath = this.wrapperEl.dataset.createBranchPath;
- this.createMrPath = this.wrapperEl.dataset.createMrPath;
-
if (target === INPUT_TARGET_BRANCH) {
this.branchIsValid = true;
} else {
@@ -539,7 +542,6 @@ export default class CreateMergeRequestDropdown {
updateBranchName(suggestedBranchName) {
this.branchInput.value = suggestedBranchName;
this.updateInputState(INPUT_TARGET_BRANCH, suggestedBranchName, '');
- this.updateCreatePaths(INPUT_TARGET_BRANCH, suggestedBranchName);
}
updateInputState(target, ref, result) {
@@ -561,7 +563,6 @@ export default class CreateMergeRequestDropdown {
if (ref === result) {
this.refIsValid = true;
this.showAvailableMessage(INPUT_TARGET_REF);
- this.updateCreatePaths(INPUT_TARGET_REF, ref);
} else {
this.refIsValid = false;
this.refInput.dataset.value = ref;
@@ -585,7 +586,6 @@ export default class CreateMergeRequestDropdown {
// Or user typed input contains invalid chars,
// that means a new branch cannot be created as it already exists.
this.showAvailableMessage(INPUT_TARGET_BRANCH, VALIDATION_TYPE_BRANCH_UNAVAILABLE);
- this.updateCreatePaths(INPUT_TARGET_BRANCH, ref);
} else if (isInvalidString) {
this.branchIsValid = false;
this.showNotAvailableMessage(INPUT_TARGET_BRANCH, VALIDATION_TYPE_INVALID_CHARS);
@@ -594,22 +594,4 @@ export default class CreateMergeRequestDropdown {
this.showNotAvailableMessage(INPUT_TARGET_BRANCH);
}
}
-
- // target - 'branch' or 'ref'
- // ref - string - the new value to use as branch or ref
- updateCreatePaths(target, ref) {
- const pathReplacement = `$1${encodeURIComponent(ref)}`;
-
- this.createBranchPath = this.createBranchPath.replace(
- this.regexps[target].createBranchPath,
- pathReplacement,
- );
- this.createMrPath = this.createMrPath.replace(
- this.regexps[target].createMrPath,
- pathReplacement,
- );
-
- this.wrapperEl.dataset.createBranchPath = this.createBranchPath;
- this.wrapperEl.dataset.createMrPath = this.createMrPath;
- }
}
diff --git a/app/assets/javascripts/super_sidebar/components/flyout_menu.vue b/app/assets/javascripts/super_sidebar/components/flyout_menu.vue
index 285fa8ee90b..fa7960da2f4 100644
--- a/app/assets/javascripts/super_sidebar/components/flyout_menu.vue
+++ b/app/assets/javascripts/super_sidebar/components/flyout_menu.vue
@@ -1,5 +1,5 @@
<script>
-import { computePosition, autoUpdate, flip, shift } from '@floating-ui/dom';
+import { computePosition, autoUpdate, offset, flip, shift } from '@floating-ui/dom';
import NavItem from './nav_item.vue';
export default {
@@ -22,7 +22,7 @@ export default {
function updatePosition() {
return computePosition(target, flyout, {
- middleware: [flip(), shift()],
+ middleware: [offset({ alignmentAxis: -12 }), flip(), shift()],
placement: 'right-start',
strategy: 'fixed',
}).then(({ x, y }) => {
@@ -44,13 +44,13 @@ export default {
<template>
<div
:id="`${targetId}-flyout`"
- class="gl-fixed gl-pl-3 gl-z-index-9999 gl-max-h-full gl-overflow-y-auto"
+ class="gl-fixed gl-p-4 gl-mx-n1 gl-z-index-9999 gl-max-h-full gl-overflow-y-auto"
@mouseover="$emit('mouseover')"
@mouseleave="$emit('mouseleave')"
>
<ul
v-if="items.length > 0"
- class="gl-min-w-20 gl-max-w-34 gl-border-1 gl-rounded-base gl-border-solid gl-border-gray-100 gl-shadow gl-bg-white gl-p-2 gl-pb-1 gl-list-style-none"
+ class="gl-min-w-20 gl-max-w-34 gl-border-1 gl-rounded-base gl-border-solid gl-border-gray-100 gl-shadow-md gl-bg-white gl-p-2 gl-pb-1 gl-list-style-none"
>
<nav-item
v-for="item of items"
diff --git a/app/assets/javascripts/super_sidebar/components/nav_item.vue b/app/assets/javascripts/super_sidebar/components/nav_item.vue
index 842893af931..79d476ee74b 100644
--- a/app/assets/javascripts/super_sidebar/components/nav_item.vue
+++ b/app/assets/javascripts/super_sidebar/components/nav_item.vue
@@ -109,7 +109,8 @@ export default {
return {
'gl-px-2 gl-mx-2 gl-line-height-normal': this.isSubitem,
'gl-px-3': !this.isSubitem,
- 'gl-pl-5!': this.isFlyout,
+ 'gl-pl-5! gl-rounded-small': this.isFlyout,
+ 'gl-rounded-base': !this.isFlyout,
[this.item.link_classes]: this.item.link_classes,
...this.linkClasses,
};
@@ -127,7 +128,7 @@ export default {
:is="navItemLinkComponent"
#default="{ isActive }"
v-bind="linkProps"
- class="nav-item-link gl-rounded-base gl-relative gl-display-flex gl-align-items-center gl-min-h-7 gl-gap-3 gl-mb-1 gl-py-2 gl-text-black-normal! gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-text-decoration-none! gl-focus--focus"
+ class="nav-item-link gl-relative gl-display-flex gl-align-items-center gl-min-h-7 gl-gap-3 gl-mb-1 gl-py-2 gl-text-black-normal! gl-hover-bg-t-gray-a-08 gl-focus-bg-t-gray-a-08 gl-text-decoration-none! gl-focus--focus"
:class="computedLinkClasses"
data-qa-selector="nav_item_link"
data-testid="nav-item-link"
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue
index 258fa4edcda..9bb39ba22e0 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/app.vue
@@ -5,8 +5,9 @@ export default {
import(
'~/vue_merge_request_widget/extensions/security_reports/mr_widget_security_reports.vue'
),
-
MrTerraformWidget: () => import('~/vue_merge_request_widget/extensions/terraform/index.vue'),
+ MrCodeQualityWidget: () =>
+ import('~/vue_merge_request_widget/extensions/code_quality/index.vue'),
},
props: {
@@ -21,8 +22,14 @@ export default {
return this.mr.terraformReportsPath && 'MrTerraformWidget';
},
+ codeQualityWidget() {
+ return this.mr.codequalityReportsPath ? 'MrCodeQualityWidget' : undefined;
+ },
+
widgets() {
- return [this.terraformPlansWidget, 'MrSecurityWidget'].filter((w) => w);
+ return [this.codeQualityWidget, this.terraformPlansWidget, 'MrSecurityWidget'].filter(
+ (w) => w,
+ );
},
},
};
diff --git a/app/assets/javascripts/vue_shared/components/groups_list/groups_list.stories.js b/app/assets/javascripts/vue_shared/components/groups_list/groups_list.stories.js
new file mode 100644
index 00000000000..235523054c3
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/groups_list/groups_list.stories.js
@@ -0,0 +1,19 @@
+import { groups } from 'jest/vue_shared/components/groups_list/mock_data';
+import GroupsList from './groups_list.vue';
+
+export default {
+ component: GroupsList,
+ title: 'vue_shared/groups_list',
+};
+
+const Template = (args, { argTypes }) => ({
+ components: { GroupsList },
+ props: Object.keys(argTypes),
+ template: '<groups-list v-bind="$props" />',
+});
+
+export const Default = Template.bind({});
+Default.args = {
+ groups,
+ showGroupIcon: true,
+};
diff --git a/app/assets/javascripts/vue_shared/components/groups_list/groups_list.vue b/app/assets/javascripts/vue_shared/components/groups_list/groups_list.vue
new file mode 100644
index 00000000000..7da45169fee
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/groups_list/groups_list.vue
@@ -0,0 +1,29 @@
+<script>
+import GroupsListItem from './groups_list_item.vue';
+
+export default {
+ components: { GroupsListItem },
+ props: {
+ groups: {
+ type: Array,
+ required: true,
+ },
+ showGroupIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+};
+</script>
+
+<template>
+ <ul class="gl-p-0 gl-list-style-none">
+ <groups-list-item
+ v-for="group in groups"
+ :key="group.id"
+ :group="group"
+ :show-group-icon="showGroupIcon"
+ />
+ </ul>
+</template>
diff --git a/app/assets/javascripts/vue_shared/components/groups_list/groups_list_item.vue b/app/assets/javascripts/vue_shared/components/groups_list/groups_list_item.vue
new file mode 100644
index 00000000000..8a301cd0dd0
--- /dev/null
+++ b/app/assets/javascripts/vue_shared/components/groups_list/groups_list_item.vue
@@ -0,0 +1,168 @@
+<script>
+import { GlAvatarLabeled, GlIcon, GlTooltipDirective, GlTruncateText } from '@gitlab/ui';
+
+import { VISIBILITY_TYPE_ICON, GROUP_VISIBILITY_TYPE } from '~/visibility_level/constants';
+import { ACCESS_LEVEL_LABELS } from '~/access_level/constants';
+import UserAccessRoleBadge from '~/vue_shared/components/user_access_role_badge.vue';
+import { __ } from '~/locale';
+import { numberToMetricPrefix } from '~/lib/utils/number_utils';
+import SafeHtml from '~/vue_shared/directives/safe_html';
+
+export default {
+ i18n: {
+ subgroups: __('Subgroups'),
+ projects: __('Projects'),
+ directMembers: __('Direct members'),
+ showMore: __('Show more'),
+ showLess: __('Show less'),
+ },
+ avatarSize: { default: 32, md: 48 },
+ safeHtmlConfig: {
+ ADD_TAGS: ['gl-emoji'],
+ },
+ components: {
+ GlAvatarLabeled,
+ GlIcon,
+ UserAccessRoleBadge,
+ GlTruncateText,
+ },
+ directives: {
+ GlTooltip: GlTooltipDirective,
+ SafeHtml,
+ },
+ props: {
+ group: {
+ type: Object,
+ required: true,
+ },
+ showGroupIcon: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
+ },
+ computed: {
+ visibility() {
+ return this.group.visibility;
+ },
+ visibilityIcon() {
+ return VISIBILITY_TYPE_ICON[this.visibility];
+ },
+ visibilityTooltip() {
+ return GROUP_VISIBILITY_TYPE[this.visibility];
+ },
+ accessLevel() {
+ return this.group.accessLevel?.integerValue;
+ },
+ accessLevelLabel() {
+ return ACCESS_LEVEL_LABELS[this.accessLevel];
+ },
+ shouldShowAccessLevel() {
+ return this.accessLevel !== undefined;
+ },
+ groupIconName() {
+ return this.group.parent ? 'subgroup' : 'group';
+ },
+ statsPadding() {
+ return this.showGroupIcon ? 'gl-pl-11' : 'gl-pl-8';
+ },
+ descendantGroupsCount() {
+ return numberToMetricPrefix(this.group.descendantGroupsCount);
+ },
+ projectsCount() {
+ return numberToMetricPrefix(this.group.projectsCount);
+ },
+ groupMembersCount() {
+ return numberToMetricPrefix(this.group.groupMembersCount);
+ },
+ },
+};
+</script>
+
+<template>
+ <li class="groups-list-item gl-py-5 gl-md-display-flex gl-align-items-center gl-border-b">
+ <div class="gl-display-flex gl-flex-grow-1">
+ <gl-icon
+ v-if="showGroupIcon"
+ class="gl-mr-3 gl-mt-3 gl-md-mt-5 gl-flex-shrink-0 gl-text-secondary"
+ :name="groupIconName"
+ />
+ <gl-avatar-labeled
+ :entity-id="group.id"
+ :entity-name="group.fullName"
+ :label="group.fullName"
+ :label-link="group.webUrl"
+ shape="rect"
+ :size="$options.avatarSize"
+ >
+ <template #meta>
+ <div class="gl-px-2">
+ <div class="gl-mx-n2 gl-display-flex gl-align-items-center gl-flex-wrap">
+ <div class="gl-px-2">
+ <gl-icon
+ v-if="visibility"
+ v-gl-tooltip="visibilityTooltip"
+ :name="visibilityIcon"
+ class="gl-text-secondary"
+ />
+ </div>
+ <div class="gl-px-2">
+ <user-access-role-badge v-if="shouldShowAccessLevel">{{
+ accessLevelLabel
+ }}</user-access-role-badge>
+ </div>
+ </div>
+ </div>
+ </template>
+ <gl-truncate-text
+ v-if="group.descriptionHtml"
+ :lines="2"
+ :mobile-lines="2"
+ :show-more-text="$options.i18n.showMore"
+ :show-less-text="$options.i18n.showLess"
+ class="gl-mt-2"
+ >
+ <div
+ v-safe-html:[$options.safeHtmlConfig]="group.descriptionHtml"
+ class="gl-font-sm md"
+ data-testid="group-description"
+ ></div>
+ </gl-truncate-text>
+ </gl-avatar-labeled>
+ </div>
+ <div
+ class="gl-md-display-flex gl-flex-direction-column gl-align-items-flex-end gl-flex-shrink-0 gl-mt-3 gl-md-pl-0 gl-md-mt-0 gl-md-ml-3"
+ :class="statsPadding"
+ >
+ <div class="gl-display-flex gl-align-items-center gl-gap-x-3">
+ <div
+ v-gl-tooltip="$options.i18n.subgroups"
+ :aria-label="$options.i18n.subgroups"
+ class="gl-text-secondary"
+ data-testid="subgroups-count"
+ >
+ <gl-icon name="subgroup" />
+ <span>{{ descendantGroupsCount }}</span>
+ </div>
+ <div
+ v-gl-tooltip="$options.i18n.projects"
+ :aria-label="$options.i18n.projects"
+ class="gl-text-secondary"
+ data-testid="projects-count"
+ >
+ <gl-icon name="project" />
+ <span>{{ projectsCount }}</span>
+ </div>
+ <div
+ v-gl-tooltip="$options.i18n.directMembers"
+ :aria-label="$options.i18n.directMembers"
+ class="gl-text-secondary"
+ data-testid="members-count"
+ >
+ <gl-icon name="users" />
+ <span>{{ groupMembersCount }}</span>
+ </div>
+ </div>
+ </div>
+ </li>
+</template>
diff --git a/config/feature_flags/development/group_saml_jit_errors.yml b/config/feature_flags/development/group_saml_jit_errors.yml
deleted file mode 100644
index 6d093e7c492..00000000000
--- a/config/feature_flags/development/group_saml_jit_errors.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: group_saml_jit_errors
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/127654
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/419836
-milestone: '16.3'
-type: development
-group: group::authentication and authorization
-default_enabled: false
diff --git a/config/feature_flags/development/telesign_callback.yml b/config/feature_flags/development/telesign_callback.yml
deleted file mode 100644
index 33bdb24a727..00000000000
--- a/config/feature_flags/development/telesign_callback.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: telesign_callback
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/125983
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/417703
-milestone: '16.3'
-type: development
-group: group::anti-abuse
-default_enabled: false
diff --git a/doc/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md
index 42d4d9c6d8c..53bde005232 100644
--- a/doc/administration/troubleshooting/postgresql.md
+++ b/doc/administration/troubleshooting/postgresql.md
@@ -212,10 +212,8 @@ To resolve the error, run `VACUUM` manually:
### GitLab database requirements
-The [database requirements](../../install/requirements.md#database) for GitLab include:
-
-- Support for MySQL was removed in [GitLab 12.1](../../update/index.md#1210).
-- Review and install the [required extension list](../../install/postgresql_extensions.md).
+See [database requirements](../../install/requirements.md#database) and review and install the
+[required extension list](../../install/postgresql_extensions.md).
### Serialization errors in the `production/sidekiq` log
diff --git a/doc/development/pipelines/internals.md b/doc/development/pipelines/internals.md
index 97424e02437..904ac11511d 100644
--- a/doc/development/pipelines/internals.md
+++ b/doc/development/pipelines/internals.md
@@ -368,6 +368,8 @@ my-job:
- This pattern does not work if a script relies on `git` to access the repository, because we don't have the repository without cloning or fetching.
- The job using this pattern needs to have `curl` available.
+- If you need to run `bundle install` in the job (even using `BUNDLE_ONLY`), you need to download the gems that are stored in the `gitlab-org/gitlab` project.
+ - You can use the `download_local_gems` shell command for that purpose.
#### Where is this pattern used?
@@ -387,5 +389,12 @@ my-job:
- `scripts/review_apps/review-apps.sh`
- `scripts/review_apps/seed-dast-test-data.sh`
- `VERSION`
+ - `rspec:coverage` for:
+ - `config/bundler_setup.rb`
+ - `Gemfile.lock`
+ - `Gemfile`
+ - `scripts/merge-simplecov`
+ - `spec/simplecov_env_core.rb`
+ - `spec/simplecov_env.rb`
Additionally, `scripts/utils.sh` is always downloaded from the API when this pattern is used (this file contains the code for `.fast-no-clone-job`).
diff --git a/doc/install/requirements.md b/doc/install/requirements.md
index 5e13628e815..b60d3fd8359 100644
--- a/doc/install/requirements.md
+++ b/doc/install/requirements.md
@@ -68,7 +68,6 @@ process, such as PostgreSQL, which can have disastrous consequences.
PostgreSQL is the only supported database, which is bundled with the Omnibus GitLab package.
You can also use an [external PostgreSQL database](https://docs.gitlab.com/omnibus/settings/database.html#using-a-non-packaged-postgresql-database-management-server).
-Support for MySQL was removed in [GitLab 12.1](../update/index.md#1210).
### PostgreSQL Requirements
diff --git a/doc/update/index.md b/doc/update/index.md
index 723b5199e98..e29c6d1b989 100644
--- a/doc/update/index.md
+++ b/doc/update/index.md
@@ -176,30 +176,21 @@ A *major* upgrade requires the following steps:
Upgrading across multiple GitLab versions in one go is *only possible by accepting downtime*.
If you don't want any downtime, read how to [upgrade with zero downtime](zero_downtime.md).
-For a dynamic view of examples of supported upgrade paths, try the [Upgrade Path tool](https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/) maintained by the [GitLab Support team](https://about.gitlab.com/handbook/support/#about-the-support-team). To share feedback and help improve the tool, create an issue or MR in the [upgrade-path project](https://gitlab.com/gitlab-com/support/toolbox/upgrade-path).
+For a dynamic view of examples of supported upgrade paths, try the [Upgrade Path tool](https://gitlab-com.gitlab.io/support/toolbox/upgrade-path/)
+maintained by the [GitLab Support team](https://about.gitlab.com/handbook/support/#about-the-support-team). To share
+feedback and help improve the tool, create an issue or MR in the [upgrade-path project](https://gitlab.com/gitlab-com/support/toolbox/upgrade-path).
-Required upgrade stops are versions of GitLab that you must upgrade to before upgrading to later versions. Required upgrade stops allow required background
-migrations to finish.
+When upgrading:
-During GitLab 16.x, we are scheduling two or three required upgrade stops. We will give at least two milestones of notice when we
-schedule a required upgrade stop.
+1. Find where your version sits in the upgrade path:
-The first planned required upgrade stop is scheduled for GitLab 16.3. If nothing is introduced requiring an upgrade stop, GitLab 16.3 will be treated as a
-regular upgrade.
+ - GitLab 14: [`14.0.12`](#1400) > [`14.3.6`](#1430) > [`14.9.5`](#1490) > [`14.10.5`](#14100).
+ - GitLab 15: [`15.0.5`](#1500) > [`15.1.6`](#1510) (for GitLab instances with multiple web nodes) > [`15.4.6`](#1540) > [`15.11.x`](#15110).
+ - GitLab 16: [latest `16.Y.Z`](https://gitlab.com/gitlab-org/gitlab/-/releases).
-Find where your version sits in the upgrade path below, and upgrade GitLab
-accordingly, while also consulting the
-[version-specific upgrade instructions](#version-specific-upgrading-instructions):
-
-- GitLab 8: `8.11.Z` > `8.12.0` > `8.17.7`
-- GitLab 9: `9.0.13` > `9.5.10`
-- GitLab 10: `10.0.7` > `10.8.7`
-- GitLab 11: `11.0.6` > [`11.11.8`](#1200)
-- GitLab 12: `12.0.12` > [`12.1.17`](#1210) > [`12.10.14`](#12100)
-- GitLab 13: `13.0.14` > [`13.1.11`](#1310) > [`13.8.8`](#1388) > [`13.12.15`](#13120)
-- GitLab 14: [`14.0.12`](#1400) > [`14.3.6`](#1430) > [`14.9.5`](#1490) > [`14.10.5`](#14100)
-- GitLab 15: [`15.0.5`](#1500) > [`15.1.6`](#1510) (for GitLab instances with multiple web nodes) > [`15.4.6`](#1540) > [`15.11.x`](#15110)
-- GitLab 16: [latest `16.Y.Z`](https://gitlab.com/gitlab-org/gitlab/-/releases)
+1. Check for [required upgrade stops](#required-upgrade-stops).
+1. Consult the [version-specific upgrade instructions](#version-specific-upgrading-instructions).
+1. Upgrade GitLab accordingly.
NOTE:
When not explicitly specified, upgrade GitLab to the latest available patch
@@ -209,6 +200,25 @@ be fixes for issues relating to the upgrade process.
Specifically around a [major version](#upgrading-to-a-new-major-version),
crucial database schema and migration patches may be included in the latest patch releases.
+### Required upgrade stops
+
+Required upgrade stops are versions of GitLab that you must upgrade to before upgrading to later versions. Required
+upgrade stops allow required background migrations to finish.
+
+During GitLab 16.x, we are scheduling two or three required upgrade stops. We will give at least two milestones of
+notice when we schedule a required upgrade stop.
+
+The first planned required upgrade stop is scheduled for GitLab 16.3. If nothing is introduced requiring an upgrade stop,
+GitLab 16.3 will be treated as a regular upgrade.
+
+### Earlier GitLab versions
+
+For information on upgrading to earlier GitLab versions, see the [documentation archives](https://archives.docs.gitlab.com).
+The versions of the documentation in the archives contain version-specific information for even earlier versions of GitLab.
+
+For example, the [documentation for GitLab 15.11](https://archives.docs.gitlab.com/15.11/ee/update/#upgrade-paths)
+contains information on versions back to GitLab 12.
+
## Upgrading between editions
GitLab comes in two flavors: [Community Edition](https://about.gitlab.com/features/#community) which is MIT licensed,
@@ -1393,8 +1403,6 @@ Other issues:
**GitLab 13.2 or older** directly to 14.0, this is [unsupported](#upgrading-to-a-new-major-version).
You should instead follow a [supported upgrade path](#upgrade-paths).
- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
-- See [Custom Rack Attack initializers](#custom-rack-attack-initializers) if you persist your own custom Rack Attack
- initializers during upgrades.
#### Upgrading to later 14.Y releases
@@ -1406,263 +1414,6 @@ Other issues:
1. [Batched background migrations must finish](background_migrations.md#batched-background-migrations)
before you upgrade to a later version [and may take longer than usual](#1400).
-### 13.12.0
-
-- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
-
-- Check the GitLab database [has no references to legacy storage](../administration/raketasks/storage.md#on-legacy-storage).
- The GitLab 14.0 pre-install check causes the package update to fail if unmigrated data exists:
-
- ```plaintext
- Checking for unmigrated data on legacy storage
-
- Legacy storage is no longer supported. Please migrate your data to hashed storage.
- ```
-
-### 13.11.0
-
-- Git 2.31.x and later is required. We recommend you use the
- [Git version provided by Gitaly](../install/installation.md#git).
-
-- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
-
-- GitLab 13.11 includes a faulty background migration ([`RescheduleArtifactExpiryBackfillAgain`](https://gitlab.com/gitlab-org/gitlab/-/blob/ccc70031b843ff8cff1185988c2e472a521c2701/db/post_migrate/20210413132500_reschedule_artifact_expiry_backfill_again.rb))
- that incorrectly sets the `expire_at` column in the `ci_job_artifacts` database table.
- Incorrect `expire_at` values can potentially cause data loss.
-
- To prevent this risk of data loss, you must remove the content of the `RescheduleArtifactExpiryBackfillAgain`
- migration, which makes it a no-op migration. You can repeat the changes from the
- [commit that makes the migration no-op in 14.9 and later](https://gitlab.com/gitlab-org/gitlab/-/blob/42c3dfc5a1c8181767bbb5c76e7c5fa6fefbbc2b/db/post_migrate/20210413132500_reschedule_artifact_expiry_backfill_again.rb).
- For more information, see [how to disable a data migration](../development/database/deleting_migrations.md#how-to-disable-a-data-migration).
-
-### 13.10.0
-
-See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
-
-### 13.9.0
-
-- We've detected an issue [with a column rename](https://gitlab.com/gitlab-org/gitlab/-/issues/324160)
- that prevents upgrades to GitLab 13.9.0, 13.9.1, 13.9.2, and 13.9.3 when following the zero-downtime steps. It is necessary
- to perform the following additional steps for the zero-downtime upgrade:
-
- 1. Before running the final `sudo gitlab-rake db:migrate` command on the deploy node,
- execute the following queries using the PostgreSQL console (or `sudo gitlab-psql`)
- to drop the problematic triggers:
-
- ```sql
- drop trigger trigger_e40a6f1858e6 on application_settings;
- drop trigger trigger_0d588df444c8 on application_settings;
- drop trigger trigger_1572cbc9a15f on application_settings;
- drop trigger trigger_22a39c5c25f3 on application_settings;
- ```
-
- 1. Run the final migrations:
-
- ```shell
- sudo gitlab-rake db:migrate
- ```
-
- If you have already run the final `sudo gitlab-rake db:migrate` command on the deploy node and have
- encountered the [column rename issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324160), you
- see the following error:
-
- ```shell
- -- remove_column(:application_settings, :asset_proxy_whitelist)
- rake aborted!
- StandardError: An error has occurred, all later migrations canceled:
- PG::DependentObjectsStillExist: ERROR: cannot drop column asset_proxy_whitelist of table application_settings because other objects depend on it
- DETAIL: trigger trigger_0d588df444c8 on table application_settings depends on column asset_proxy_whitelist of table application_settings
- ```
-
- To work around this bug, follow the previous steps to complete the upgrade.
- More details are available [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/324160).
-
-- See [Maintenance mode issue in GitLab 13.9 to 14.4](#maintenance-mode-issue-in-gitlab-139-to-144).
-
-- For GitLab Enterprise Edition customers, we noticed an issue when [subscription expiration is upcoming, and you create new subgroups and projects](https://gitlab.com/gitlab-org/gitlab/-/issues/322546). If you fall under that category and get 500 errors, you can work around this issue:
-
- 1. SSH into you GitLab server, and open a Rails console:
-
- ```shell
- sudo gitlab-rails console
- ```
-
- 1. Disable the following features:
-
- ```ruby
- Feature.disable(:subscribable_subscription_banner)
- Feature.disable(:subscribable_license_banner)
- ```
-
- 1. Restart Puma or Unicorn:
-
- ```shell
- #For installations using Puma
- sudo gitlab-ctl restart puma
-
- #For installations using Unicorn
- sudo gitlab-ctl restart unicorn
- ```
-
-### 13.8.8
-
-GitLab 13.8 includes a background migration to address [an issue with duplicate service records](https://gitlab.com/gitlab-org/gitlab/-/issues/290008). If duplicate services are present, this background migration must complete before a unique index is applied to the services table, which was [introduced in GitLab 13.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/52563). Upgrades from GitLab 13.8 and earlier to later versions must include an intermediate upgrade to GitLab 13.8.8 and [must wait until the background migrations complete](background_migrations.md) before proceeding.
-
-If duplicate services are still present, an upgrade to 13.9.x or later results in a failed upgrade with the following error:
-
-```console
-PG::UniqueViolation: ERROR: could not create unique index "index_services_on_project_id_and_type_unique"
-DETAIL: Key (project_id, type)=(NNN, ServiceName) is duplicated.
-```
-
-### 13.6.0
-
-Ruby 2.7.2 is required. GitLab does not start with Ruby 2.6.6 or older versions.
-
-The required Git version is Git v2.29 or later.
-
-GitLab 13.6 includes a
-[background migration `BackfillJiraTrackerDeploymentType2`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46368)
-that may remain stuck permanently in a **pending** state despite completion of work
-due to a bug.
-
-To clean up this stuck job, run the following in the [GitLab Rails Console](../administration/operations/rails_console.md):
-
-```ruby
-Gitlab::Database::BackgroundMigrationJob.pending.where(class_name: "BackfillJiraTrackerDeploymentType2").find_each do |job|
- puts Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded("BackfillJiraTrackerDeploymentType2", job.arguments)
-end
-```
-
-### 13.4.0
-
-GitLab 13.4.0 includes a background migration to [move all remaining repositories in legacy storage to hashed storage](../administration/raketasks/storage.md#migrate-to-hashed-storage). There are [known issues with this migration](https://gitlab.com/gitlab-org/gitlab/-/issues/259605) which are fixed in GitLab 13.5.4 and later. If possible, skip 13.4.0 and upgrade to 13.5.4 or later instead. The migration can take quite a while to run, depending on how many repositories must be moved. Be sure to check that all background migrations have completed before upgrading further.
-
-### 13.3.0
-
-The recommended Git version is Git v2.28. The minimum required version of Git
-v2.24 remains the same.
-
-### 13.2.0
-
-GitLab installations that have multiple web nodes must be
-[upgraded to 13.1](#1310) before upgrading to 13.2 (and later) due to a
-breaking change in Rails that can result in authorization issues.
-
-GitLab 13.2.0 [remediates](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35492) an [email verification bypass](https://about.gitlab.com/releases/2020/05/27/security-release-13-0-1-released/).
-After upgrading, if some of your users are unexpectedly encountering 404 or 422 errors when signing in,
-or "blocked" messages when using the command line,
-their accounts may have been un-confirmed.
-In that case, ask them to check their email for a re-confirmation link.
-For more information, see our discussion of [Email confirmation issues](../user/upgrade_email_bypass.md).
-
-GitLab 13.2.0 relies on the `btree_gist` extension for PostgreSQL. For installations with an externally managed PostgreSQL setup, make sure to
-[install the extension manually](https://www.postgresql.org/docs/11/sql-createextension.html) before upgrading GitLab if the database user for GitLab
-is not a superuser. This is not necessary for installations using a GitLab managed PostgreSQL database.
-
-### 13.1.0
-
-In 13.1.0, you must upgrade to either:
-
-- At least Git v2.24 (previously, the minimum required version was Git v2.22).
-- The recommended Git v2.26.
-
-Failure to do so results in internal errors in the Gitaly service in some RPCs due
-to the use of the new `--end-of-options` Git flag.
-
-Additionally, in GitLab 13.1.0, the version of
-[Rails was upgraded from 6.0.3 to 6.0.3.1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33454).
-The Rails upgrade included a change to CSRF token generation which is
-not backwards-compatible - GitLab servers with the new Rails version
-generate CSRF tokens that are not recognizable by GitLab servers
-with the older Rails version - which could cause non-GET requests to
-fail for [multi-node GitLab installations](zero_downtime.md#multi-node--ha-deployment).
-
-So, if you are using multiple Rails servers and specifically upgrading from 13.0,
-all servers must first be upgraded to 13.1.Z before upgrading to 13.2.0 or later:
-
-1. Ensure all GitLab web nodes are running GitLab 13.1.Z.
-1. Enable the `global_csrf_token` feature flag to enable new
- method of CSRF token generation:
-
- ```ruby
- Feature.enable(:global_csrf_token)
- ```
-
-1. Only then, continue to upgrade to later versions of GitLab.
-
-#### Custom Rack Attack initializers
-
-From GitLab 13.1, custom Rack Attack initializers (`config/initializers/rack_attack.rb`) are replaced with initializers
-supplied with GitLab during upgrades. You should use these GitLab-supplied initializers.
-
-If you persist your own Rack Attack initializers between upgrades, you might
-[get `500` errors](https://gitlab.com/gitlab-org/gitlab/-/issues/334681) when [upgrading to GitLab 14.0 and later](#1400).
-
-For **self-compiled (source) installations**, the Rack Attack initializer on GitLab
-was renamed from [`config/initializers/rack_attack_new.rb` to `config/initializers/rack_attack.rb`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/33072).
-The rename was part of [deprecating Rack Attack throttles on Omnibus GitLab](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/4750).
-
-If `rack_attack.rb` has been created on your installation, consider creating a backup before updating:
-
-```shell
-cd /home/git/gitlab
-cp config/initializers/rack_attack.rb config/initializers/rack_attack_backup.rb
-```
-
-### 12.10.0
-
-- The final patch release (12.10.14)
- [has a regression affecting maven package uploads](https://about.gitlab.com/releases/2020/07/06/critical-security-release-gitlab-13-1-3-released/#maven-package-upload-broken-in-121014).
- If you use this feature and must stay on 12.10 while preparing to upgrade to 13.0:
-
- - Upgrade to 12.10.13 instead.
- - Upgrade to 13.0.14 as soon as possible.
-
-- [GitLab 13.0 requires PostgreSQL 11](https://about.gitlab.com/releases/2020/05/22/gitlab-13-0-released/#postgresql-11-is-now-the-minimum-required-version-to-install-gitlab).
-
- - 12.10 is the final release that shipped with PostgreSQL 9.6, 10, and 11.
- - You should make sure that your database is PostgreSQL 11 on GitLab 12.10 before upgrading to 13.0. This upgrade requires downtime.
-
-### 12.2.0
-
-In 12.2.0, we enabled Rails' authenticated cookie encryption. Old sessions are
-automatically upgraded.
-
-However, session cookie downgrades are not supported. So after upgrading to 12.2.0,
-any downgrades would result to all sessions being invalidated and users are logged out.
-
-### 12.1.0
-
-- If you are planning to upgrade from `12.0.Z` to `12.10.Z`, it is necessary to
- perform an intermediary upgrade to `12.1.Z` before upgrading to `12.10.Z` to
- avoid issues like [#215141](https://gitlab.com/gitlab-org/gitlab/-/issues/215141).
-
-- Support for MySQL was removed in GitLab 12.1. Existing users using GitLab with
- MySQL/MariaDB should
- [migrate to PostgreSQL](https://gitlab.com/gitlab-org/gitlab/-/blob/v15.6.0-ee/doc/update/mysql_to_postgresql.md)
- before upgrading.
-
-### 12.0.0
-
-In 12.0.0 we made various database related changes. These changes require that
-users first upgrade to the latest 11.11 patch release. After upgraded to 11.11.Z,
-users can upgrade to 12.0.Z. Failure to do so may result in database migrations
-not being applied, which could lead to application errors.
-
-It is also required that you upgrade to 12.0.Z before moving to a later version
-of 12.Y.
-
-Example 1: you are currently using GitLab 11.11.8, which is the latest patch
-release for 11.11.Z. You can upgrade as usual to 12.0.Z.
-
-Example 2: you are currently using a version of GitLab 10.Y. To upgrade, first
-upgrade to the last 10.Y release (10.8.7) then the last 11.Y release (11.11.8).
-After upgraded to 11.11.8 you can safely upgrade to 12.0.Z.
-
-See our [documentation on upgrade paths](../policy/maintenance.md#upgrade-recommendations)
-for more information.
-
### User profile data loss bug in 15.9.x
There is a database migration bug in 15.9.0, 15.9.1, and 15.9.2 that can cause data loss from the user profile fields `linkedin`, `twitter`, `skype`, `website_url`, `location`, and `organization`.
diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md
index d9641e18e8e..21f509ebd33 100644
--- a/doc/update/upgrading_from_source.md
+++ b/doc/update/upgrading_from_source.md
@@ -327,10 +327,6 @@ cd /home/git/gitlab
sudo -u git -H bundle exec rake "gitlab:workhorse:install[/home/git/gitlab-workhorse]" RAILS_ENV=production
```
-NOTE:
-If you get any errors concerning Rack attack, see the [13.1](index.md#custom-rack-attack-initializers)
-specific changes.
-
### 13. Update Gitaly
If Gitaly is located on its own server, or you use Gitaly Cluster, see [Gitaly or Gitaly Cluster](zero_downtime.md#gitaly-or-gitaly-cluster)
diff --git a/scripts/review_apps/review-apps.sh b/scripts/review_apps/review-apps.sh
index af6c2ec5383..365894e6118 100755
--- a/scripts/review_apps/review-apps.sh
+++ b/scripts/review_apps/review-apps.sh
@@ -243,7 +243,7 @@ function download_chart() {
function base_config_changed() {
if [ -z "${CI_MERGE_REQUEST_IID}" ]; then return; fi
- curl "${CI_API_V4_URL}/projects/${CI_MERGE_REQUEST_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/changes" | jq '.changes | any(.old_path == "scripts/review_apps/base-config.yaml")'
+ curl "${CI_API_V4_URL}/projects/${CI_MERGE_REQUEST_PROJECT_ID}/merge_requests/${CI_MERGE_REQUEST_IID}/changes" | jq --arg path "${GITLAB_REVIEW_APP_BASE_CONFIG_FILE}" '.changes | any(.old_path == $path)'
}
function parse_gitaly_image_tag() {
@@ -263,7 +263,7 @@ function deploy() {
local base_config_file_ref="${CI_DEFAULT_BRANCH}"
if [[ "$(base_config_changed)" == "true" ]]; then base_config_file_ref="${CI_COMMIT_SHA}"; fi
- local base_config_file="${GITLAB_REPO_URL}/raw/${base_config_file_ref}/scripts/review_apps/base-config.yaml"
+ local base_config_file="${GITLAB_REPO_URL}/raw/${base_config_file_ref}/${GITLAB_REVIEW_APP_BASE_CONFIG_FILE}"
echoinfo "Deploying ${release} to ${CI_ENVIRONMENT_URL} ..." true
diff --git a/scripts/utils.sh b/scripts/utils.sh
index 4ed56b2de1a..e19622d07c6 100644
--- a/scripts/utils.sh
+++ b/scripts/utils.sh
@@ -416,3 +416,38 @@ function url_encode() {
-e 's/}/%7d/g' \
-e 's/~/%7e/g'
}
+
+# Download the local gems in `gems` and `vendor/gems` folders from the API.
+#
+# This is useful if you need to run bundle install while not doing a git clone of the gitlab-org/gitlab repo.
+function download_local_gems() {
+ for folder_path in vendor/gems gems; do
+ local output="${folder_path}.tar.gz"
+
+ # From https://docs.gitlab.com/ee/api/repositories.html#get-file-archive:
+ #
+ # This endpoint can be accessed without authentication if the repository is publicly accessible.
+ # For GitLab.com users, this endpoint has a rate limit threshold of 5 requests per minute.
+ #
+ # We don't want to set a token for public repo (e.g. gitlab-org/gitlab), as 5 requests/minute can
+ # potentially be reached with many pipelines running in parallel.
+ local private_token_header=""
+ if [[ "${CI_PROJECT_VISIBILITY}" != "public" ]]; then
+ private_token_header="Private-Token: ${PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE}"
+ fi
+
+ echo "Downloading ${folder_path}"
+
+ url=${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/repository/archive
+ curl -f \
+ --get \
+ --header "${private_token_header}" \
+ --output "${output}" \
+ --data-urlencode "sha=${CI_COMMIT_SHA}" \
+ --data-urlencode "path=${folder_path}" \
+ "${url}"
+
+ tar -zxf "${output}" --strip-component 1
+ rm "${output}"
+ done
+}
diff --git a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
index ecb899a7ca2..0c50b7b2475 100644
--- a/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
+++ b/spec/features/issues/user_creates_branch_and_merge_request_spec.rb
@@ -112,6 +112,18 @@ RSpec.describe 'User creates branch and merge request on issue page', :js, featu
expect(page).to have_selector('.ref-selector', text: branch_name)
expect(page).to have_current_path project_tree_path(project, branch_name), ignore_query: true
end
+
+ context 'when source branch is non-default' do
+ let(:source_branch) { 'feature' }
+
+ it 'creates a branch' do
+ select_dropdown_option('create-branch', branch_name, source_branch)
+ wait_for_requests
+
+ expect(page).to have_selector('.ref-selector', text: branch_name)
+ expect(page).to have_current_path project_tree_path(project, branch_name), ignore_query: true
+ end
+ end
end
context 'when branch name is invalid' do
@@ -231,12 +243,13 @@ RSpec.describe 'User creates branch and merge request on issue page', :js, featu
private
- def select_dropdown_option(option, branch_name = nil)
+ def select_dropdown_option(option, branch_name = nil, source_branch = nil)
find('.create-mr-dropdown-wrap .dropdown-toggle').click
find("li[data-value='#{option}']").click
- if branch_name
- find('.js-branch-name').set(branch_name)
+ if branch_name || source_branch
+ find('.js-branch-name').set(branch_name) if branch_name
+ find('.js-ref').set(source_branch) if source_branch
# Javascript debounces AJAX calls.
# So we have to wait until AJAX requests are started.
diff --git a/spec/frontend/issues/create_merge_request_dropdown_spec.js b/spec/frontend/issues/create_merge_request_dropdown_spec.js
index 21ae844e2dd..54dc07688df 100644
--- a/spec/frontend/issues/create_merge_request_dropdown_spec.js
+++ b/spec/frontend/issues/create_merge_request_dropdown_spec.js
@@ -51,31 +51,6 @@ describe('CreateMergeRequestDropdown', () => {
});
});
- describe('updateCreatePaths', () => {
- it('escapes branch names correctly', () => {
- dropdown.createBranchPath = `${TEST_HOST}/branches?branch_name=some-branch&issue=42`;
- dropdown.createMrPath = `${TEST_HOST}/create_merge_request?merge_request%5Bsource_branch%5D=test&merge_request%5Btarget_branch%5D=master&merge_request%5Bissue_iid%5D=42`;
-
- dropdown.updateCreatePaths('branch', 'contains#hash');
-
- expect(dropdown.createBranchPath).toBe(
- `${TEST_HOST}/branches?branch_name=contains%23hash&issue=42`,
- );
-
- expect(dropdown.createMrPath).toBe(
- `${TEST_HOST}/create_merge_request?merge_request%5Bsource_branch%5D=contains%23hash&merge_request%5Btarget_branch%5D=master&merge_request%5Bissue_iid%5D=42`,
- );
-
- expect(dropdown.wrapperEl.dataset.createBranchPath).toBe(
- `${TEST_HOST}/branches?branch_name=contains%23hash&issue=42`,
- );
-
- expect(dropdown.wrapperEl.dataset.createMrPath).toBe(
- `${TEST_HOST}/create_merge_request?merge_request%5Bsource_branch%5D=contains%23hash&merge_request%5Btarget_branch%5D=master&merge_request%5Bissue_iid%5D=42`,
- );
- });
- });
-
describe('enable', () => {
beforeEach(() => {
dropdown.createMergeRequestButton.classList.add('disabled');
diff --git a/spec/frontend/vue_merge_request_widget/mock_data.js b/spec/frontend/vue_merge_request_widget/mock_data.js
index 9da687c0ff8..5b3f533f34e 100644
--- a/spec/frontend/vue_merge_request_widget/mock_data.js
+++ b/spec/frontend/vue_merge_request_widget/mock_data.js
@@ -332,7 +332,7 @@ export default {
base_path: 'blob_path',
head_path: 'blob_path',
},
- codequality_reports_path: 'codequality_reports.json',
+ codequality_reports_path: '',
codequality_help_path: 'code_quality.html',
target_branch_path: '/root/acets-app/branches/main',
source_branch_path: '/root/acets-app/branches/daaaa',
diff --git a/spec/frontend/vue_shared/components/groups_list/groups_list_item_spec.js b/spec/frontend/vue_shared/components/groups_list/groups_list_item_spec.js
new file mode 100644
index 00000000000..877de4f4695
--- /dev/null
+++ b/spec/frontend/vue_shared/components/groups_list/groups_list_item_spec.js
@@ -0,0 +1,182 @@
+import { GlAvatarLabeled, GlIcon } from '@gitlab/ui';
+import { mountExtended } from 'helpers/vue_test_utils_helper';
+import GroupsListItem from '~/vue_shared/components/groups_list/groups_list_item.vue';
+import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
+import {
+ VISIBILITY_TYPE_ICON,
+ VISIBILITY_LEVEL_INTERNAL_STRING,
+ GROUP_VISIBILITY_TYPE,
+} from '~/visibility_level/constants';
+import UserAccessRoleBadge from '~/vue_shared/components/user_access_role_badge.vue';
+import { ACCESS_LEVEL_LABELS } from '~/access_level/constants';
+import { groups } from './mock_data';
+
+describe('GroupsListItem', () => {
+ let wrapper;
+
+ const [group] = groups;
+
+ const defaultPropsData = { group };
+
+ const createComponent = ({ propsData = {} } = {}) => {
+ wrapper = mountExtended(GroupsListItem, {
+ propsData: { ...defaultPropsData, ...propsData },
+ directives: {
+ GlTooltip: createMockDirective('gl-tooltip'),
+ },
+ });
+ };
+
+ const findAvatarLabeled = () => wrapper.findComponent(GlAvatarLabeled);
+ const findGroupDescription = () => wrapper.findByTestId('group-description');
+ const findVisibilityIcon = () => findAvatarLabeled().findComponent(GlIcon);
+
+ it('renders group avatar', () => {
+ createComponent();
+
+ const avatarLabeled = findAvatarLabeled();
+
+ expect(avatarLabeled.props()).toMatchObject({
+ label: group.fullName,
+ labelLink: group.webUrl,
+ });
+
+ expect(avatarLabeled.attributes()).toMatchObject({
+ 'entity-id': group.id.toString(),
+ 'entity-name': group.fullName,
+ shape: 'rect',
+ });
+ });
+
+ it('renders visibility icon with tooltip', () => {
+ createComponent();
+
+ const icon = findAvatarLabeled().findComponent(GlIcon);
+ const tooltip = getBinding(icon.element, 'gl-tooltip');
+
+ expect(icon.props('name')).toBe(VISIBILITY_TYPE_ICON[VISIBILITY_LEVEL_INTERNAL_STRING]);
+ expect(tooltip.value).toBe(GROUP_VISIBILITY_TYPE[VISIBILITY_LEVEL_INTERNAL_STRING]);
+ });
+
+ it('renders subgroup count', () => {
+ createComponent();
+
+ const countWrapper = wrapper.findByTestId('subgroups-count');
+ const tooltip = getBinding(countWrapper.element, 'gl-tooltip');
+
+ expect(tooltip.value).toBe(GroupsListItem.i18n.subgroups);
+ expect(countWrapper.text()).toBe(group.descendantGroupsCount.toString());
+ expect(countWrapper.findComponent(GlIcon).props('name')).toBe('subgroup');
+ });
+
+ it('renders projects count', () => {
+ createComponent();
+
+ const countWrapper = wrapper.findByTestId('projects-count');
+ const tooltip = getBinding(countWrapper.element, 'gl-tooltip');
+
+ expect(tooltip.value).toBe(GroupsListItem.i18n.projects);
+ expect(countWrapper.text()).toBe(group.projectsCount.toString());
+ expect(countWrapper.findComponent(GlIcon).props('name')).toBe('project');
+ });
+
+ it('renders members count', () => {
+ createComponent();
+
+ const countWrapper = wrapper.findByTestId('members-count');
+ const tooltip = getBinding(countWrapper.element, 'gl-tooltip');
+
+ expect(tooltip.value).toBe(GroupsListItem.i18n.directMembers);
+ expect(countWrapper.text()).toBe(group.groupMembersCount.toString());
+ expect(countWrapper.findComponent(GlIcon).props('name')).toBe('users');
+ });
+
+ describe('when visibility is not provided', () => {
+ it('does not render visibility icon', () => {
+ const { visibility, ...groupWithoutVisibility } = group;
+ createComponent({
+ propsData: {
+ group: groupWithoutVisibility,
+ },
+ });
+
+ expect(findVisibilityIcon().exists()).toBe(false);
+ });
+ });
+
+ it('renders access role badge', () => {
+ createComponent();
+
+ expect(findAvatarLabeled().findComponent(UserAccessRoleBadge).text()).toBe(
+ ACCESS_LEVEL_LABELS[group.accessLevel.integerValue],
+ );
+ });
+
+ describe('when group has a description', () => {
+ it('renders description', () => {
+ const descriptionHtml = '<p>Foo bar</p>';
+
+ createComponent({
+ propsData: {
+ group: {
+ ...group,
+ descriptionHtml,
+ },
+ },
+ });
+
+ expect(findGroupDescription().element.innerHTML).toBe(descriptionHtml);
+ });
+ });
+
+ describe('when group does not have a description', () => {
+ it('does not render description', () => {
+ createComponent({
+ propsData: {
+ group: {
+ ...group,
+ descriptionHtml: null,
+ },
+ },
+ });
+
+ expect(findGroupDescription().exists()).toBe(false);
+ });
+ });
+
+ describe('when `showGroupIcon` prop is `true`', () => {
+ describe('when `parent` attribute is `null`', () => {
+ it('shows group icon', () => {
+ createComponent({ propsData: { showGroupIcon: true } });
+
+ expect(wrapper.findByTestId('group-icon').exists()).toBe(true);
+ });
+ });
+
+ describe('when `parent` attribute is set', () => {
+ it('shows subgroup icon', () => {
+ createComponent({
+ propsData: {
+ showGroupIcon: true,
+ group: {
+ ...group,
+ parent: {
+ id: 'gid://gitlab/Group/35',
+ },
+ },
+ },
+ });
+
+ expect(wrapper.findByTestId('subgroup-icon').exists()).toBe(true);
+ });
+ });
+ });
+
+ describe('when `showGroupIcon` prop is `false`', () => {
+ it('does not show group icon', () => {
+ createComponent();
+
+ expect(wrapper.findByTestId('group-icon').exists()).toBe(false);
+ });
+ });
+});
diff --git a/spec/frontend/vue_shared/components/groups_list/groups_list_spec.js b/spec/frontend/vue_shared/components/groups_list/groups_list_spec.js
new file mode 100644
index 00000000000..c65aa347bcf
--- /dev/null
+++ b/spec/frontend/vue_shared/components/groups_list/groups_list_spec.js
@@ -0,0 +1,34 @@
+import { shallowMountExtended } from 'helpers/vue_test_utils_helper';
+import GroupsList from '~/vue_shared/components/groups_list/groups_list.vue';
+import GroupsListItem from '~/vue_shared/components/groups_list/groups_list_item.vue';
+import { groups } from './mock_data';
+
+describe('GroupsList', () => {
+ let wrapper;
+
+ const defaultPropsData = {
+ groups,
+ };
+
+ const createComponent = () => {
+ wrapper = shallowMountExtended(GroupsList, {
+ propsData: defaultPropsData,
+ });
+ };
+
+ it('renders list with `GroupsListItem` component', () => {
+ createComponent();
+
+ const groupsListItemWrappers = wrapper.findAllComponents(GroupsListItem).wrappers;
+ const expectedProps = groupsListItemWrappers.map((groupsListItemWrapper) =>
+ groupsListItemWrapper.props(),
+ );
+
+ expect(expectedProps).toEqual(
+ defaultPropsData.groups.map((group) => ({
+ group,
+ showGroupIcon: false,
+ })),
+ );
+ });
+});
diff --git a/spec/frontend/vue_shared/components/groups_list/mock_data.js b/spec/frontend/vue_shared/components/groups_list/mock_data.js
new file mode 100644
index 00000000000..0dad27f8311
--- /dev/null
+++ b/spec/frontend/vue_shared/components/groups_list/mock_data.js
@@ -0,0 +1,35 @@
+export const groups = [
+ {
+ id: 1,
+ fullName: 'Gitlab Org',
+ parent: null,
+ webUrl: 'http://127.0.0.1:3000/groups/gitlab-org',
+ descriptionHtml:
+ '<p data-sourcepos="1:1-1:64" dir="auto">Dolorem dolorem omnis impedit cupiditate pariatur officia velit. Fusce eget orci a ipsum tempus vehicula. Donec rhoncus ante sed lacus pharetra, vitae imperdiet felis lobortis. Donec maximus dapibus orci, sit amet euismod dolor rhoncus vel. In nec mauris nibh.</p>',
+ avatarUrl: null,
+ descendantGroupsCount: 1,
+ projectsCount: 1,
+ groupMembersCount: 2,
+ visibility: 'internal',
+ accessLevel: {
+ integerValue: 10,
+ },
+ },
+ {
+ id: 2,
+ fullName: 'Gitlab Org / test subgroup',
+ parent: {
+ id: 1,
+ },
+ webUrl: 'http://127.0.0.1:3000/groups/gitlab-org/test-subgroup',
+ descriptionHtml: '',
+ avatarUrl: null,
+ descendantGroupsCount: 4,
+ projectsCount: 4,
+ groupMembersCount: 4,
+ visibility: 'private',
+ accessLevel: {
+ integerValue: 20,
+ },
+ },
+];
diff --git a/spec/lib/gitlab/tracking/standard_context_spec.rb b/spec/lib/gitlab/tracking/standard_context_spec.rb
index e1ae362e797..c44cfdea1cd 100644
--- a/spec/lib/gitlab/tracking/standard_context_spec.rb
+++ b/spec/lib/gitlab/tracking/standard_context_spec.rb
@@ -3,10 +3,6 @@
require 'spec_helper'
RSpec.describe Gitlab::Tracking::StandardContext do
- let_it_be(:project) { create(:project) }
- let_it_be(:namespace) { create(:namespace) }
- let_it_be(:user) { create(:user) }
-
let(:snowplow_context) { subject.to_context }
describe '#to_context' do
@@ -62,21 +58,27 @@ RSpec.describe Gitlab::Tracking::StandardContext do
expect(snowplow_context.to_json.dig(:data, :context_generated_at)).to eq(Time.current)
end
- context 'plan' do
- context 'when namespace is not available' do
- it 'is nil' do
- expect(snowplow_context.to_json.dig(:data, :plan)).to be_nil
- end
- end
+ it 'contains standard properties' do
+ standard_properties = [:user_id, :project_id, :namespace_id, :plan]
+ expect(snowplow_context.to_json[:data].keys).to include(*standard_properties)
+ end
- context 'when namespace is available' do
- let(:namespace) { create(:namespace) }
+ context 'with standard properties' do
+ let(:user_id) { 1 }
+ let(:project_id) { 2 }
+ let(:namespace_id) { 3 }
+ let(:plan_name) { "plan name" }
- subject { described_class.new(namespace_id: namespace.id, plan_name: namespace.actual_plan_name) }
+ subject do
+ described_class.new(user_id: user_id, project_id: project_id, namespace_id: namespace_id, plan_name: plan_name)
+ end
- it 'contains plan name' do
- expect(snowplow_context.to_json.dig(:data, :plan)).to eq(Plan::DEFAULT)
- end
+ it 'holds the correct values', :aggregate_failures do
+ json_data = snowplow_context.to_json.fetch(:data)
+ expect(json_data[:user_id]).to eq(user_id)
+ expect(json_data[:project_id]).to eq(project_id)
+ expect(json_data[:namespace_id]).to eq(namespace_id)
+ expect(json_data[:plan]).to eq(plan_name)
end
end
@@ -95,24 +97,12 @@ RSpec.describe Gitlab::Tracking::StandardContext do
end
context 'with incorrect argument type' do
- subject { described_class.new(project_id: create(:group)) }
+ subject { described_class.new(project_id: "a string") }
it 'does call `track_and_raise_for_dev_exception`' do
expect(Gitlab::ErrorTracking).to receive(:track_and_raise_for_dev_exception)
snowplow_context
end
end
-
- it 'contains user id' do
- expect(snowplow_context.to_json[:data].keys).to include(:user_id)
- end
-
- it 'contains namespace and project ids' do
- expect(snowplow_context.to_json[:data].keys).to include(:project_id, :namespace_id)
- end
-
- it 'accepts just project id as integer' do
- expect { described_class.new(project: 1).to_context }.not_to raise_error
- end
end
end