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:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-01-09 21:10:06 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-01-09 21:10:06 +0300
commit17deb2a503bb8163514fe37618bf36f75376b9ae (patch)
treef0bc3819cb3f9f19f30301191e250d069461c8d3
parente9de69b545c25c9cb7fd410f9bf8ba34c6bb727b (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/issue_templates/Feature Flag Roll Out.md2
-rw-r--r--app/assets/javascripts/members/components/action_dropdowns/constants.js4
-rw-r--r--app/assets/javascripts/members/components/action_dropdowns/leave_group_dropdown_item.vue6
-rw-r--r--app/assets/javascripts/members/components/action_dropdowns/remove_member_dropdown_item.vue6
-rw-r--r--app/assets/javascripts/members/components/action_dropdowns/user_action_dropdown.vue24
-rw-r--r--app/assets/javascripts/members/components/modals/leave_modal.vue63
-rw-r--r--app/assets/javascripts/members/components/modals/remove_member_modal.vue36
-rw-r--r--app/assets/javascripts/members/components/table/members_table.vue12
-rw-r--r--app/assets/javascripts/members/components/table/members_table_cell.vue7
-rw-r--r--app/assets/javascripts/members/utils.js3
-rw-r--r--app/controllers/registrations/welcome_controller.rb5
-rw-r--r--app/views/groups/_group_admin_settings.html.haml2
-rw-r--r--config/feature_flags/development/admin_emails_vue.yml8
-rw-r--r--doc/administration/packages/container_registry.md2
-rw-r--r--doc/api/graphql/users_example.md1
-rw-r--r--doc/api/oauth2.md2
-rw-r--r--doc/ci/docker/using_docker_build.md2
-rw-r--r--doc/ci/jobs/ci_job_token.md2
-rw-r--r--doc/ci/migration/jenkins.md2
-rw-r--r--doc/development/architecture.md2
-rw-r--r--doc/development/features_inside_dot_gitlab.md2
-rw-r--r--doc/development/service_ping/implement.md2
-rw-r--r--doc/topics/autodevops/cicd_variables.md6
-rw-r--r--doc/topics/autodevops/customize.md294
-rw-r--r--doc/topics/autodevops/stages.md4
-rw-r--r--doc/topics/autodevops/troubleshooting.md2
-rw-r--r--doc/tutorials/move_personal_project_to_a_group.md2
-rw-r--r--doc/user/admin_area/settings/account_and_limit_settings.md3
-rw-r--r--doc/user/analytics/img/devops_metrics_comparison_v15_8.pngbin0 -> 82446 bytes
-rw-r--r--doc/user/analytics/value_streams_dashboard.md62
-rw-r--r--doc/user/application_security/container_scanning/index.md2
-rw-r--r--doc/user/application_security/index.md2
-rw-r--r--doc/user/application_security/offline_deployments/index.md2
-rw-r--r--doc/user/packages/container_registry/authenticate_with_container_registry.md60
-rw-r--r--doc/user/packages/container_registry/build_and_push_images.md214
-rw-r--r--doc/user/packages/container_registry/delete_container_registry_images.md117
-rw-r--r--doc/user/packages/container_registry/index.md510
-rw-r--r--doc/user/packages/container_registry/reduce_container_registry_storage.md4
-rw-r--r--doc/user/packages/container_registry/troubleshoot_container_registry.md2
-rw-r--r--doc/user/permissions.md2
-rw-r--r--doc/user/profile/account/two_factor_authentication.md2
-rw-r--r--doc/user/profile/personal_access_tokens.md2
-rw-r--r--doc/user/project/settings/index.md2
-rw-r--r--lib/gitlab/gitaly_client.rb24
-rw-r--r--locale/gitlab.pot17
-rw-r--r--spec/frontend/members/components/action_dropdowns/leave_group_dropdown_item_spec.js5
-rw-r--r--spec/frontend/members/components/action_dropdowns/remove_member_dropdown_item_spec.js5
-rw-r--r--spec/frontend/members/components/action_dropdowns/user_action_dropdown_spec.js58
-rw-r--r--spec/frontend/members/components/modals/leave_modal_spec.js122
-rw-r--r--spec/frontend/members/components/modals/remove_member_modal_spec.js24
-rw-r--r--spec/frontend/members/components/table/members_table_cell_spec.js16
-rw-r--r--spec/frontend/members/components/table/members_table_spec.js25
-rw-r--r--spec/frontend/members/mock_data.js9
-rw-r--r--spec/frontend/members/utils_spec.js12
-rw-r--r--workhorse/internal/lsif_transformer/parser/docs.go10
-rw-r--r--workhorse/internal/lsif_transformer/parser/docs_test.go32
56 files changed, 1138 insertions, 710 deletions
diff --git a/.gitlab/issue_templates/Feature Flag Roll Out.md b/.gitlab/issue_templates/Feature Flag Roll Out.md
index 3972368ddc4..8aa631dce76 100644
--- a/.gitlab/issue_templates/Feature Flag Roll Out.md
+++ b/.gitlab/issue_templates/Feature Flag Roll Out.md
@@ -113,12 +113,14 @@ For visibility, all `/chatops` commands that target production should be execute
For visibility, all `/chatops` commands that target production should be executed in the `#production` slack channel and cross-posted (with the command results) to the responsible team's slack channel (`#g_TEAM_NAME`).
- [ ] [Incrementally roll out](https://docs.gitlab.com/ee/development/feature_flags/controls.html#process) the feature.
+ - [ ] Between every step wait for at least 15 minutes and monitor the appropriate graphs on https://dashboards.gitlab.net.
- If the feature flag in code has [an actor](https://docs.gitlab.com/ee/development/feature_flags/#feature-actors), perform **actor-based** rollout.
- [ ] `/chatops run feature set <feature-flag-name> <rollout-percentage> --actors`
- If the feature flag in code does **NOT** have [an actor](https://docs.gitlab.com/ee/development/feature_flags/#feature-actors), perform time-based rollout (**random** rollout).
- [ ] `/chatops run feature set <feature-flag-name> <rollout-percentage> --random`
- Enable the feature globally on production environment.
- [ ] `/chatops run feature set <feature-flag-name> true`
+- [ ] Observe appropriate graphs on https://dashboards.gitlab.net and verify that services are not affected.
- [ ] Leave a comment on [the feature issue][main-issue] announcing that the feature has been globally enabled.
- [ ] Wait for [at least one day for the verification term](https://about.gitlab.com/handbook/product-development-flow/feature-flag-lifecycle/#including-a-feature-behind-feature-flag-in-the-final-release).
diff --git a/app/assets/javascripts/members/components/action_dropdowns/constants.js b/app/assets/javascripts/members/components/action_dropdowns/constants.js
index f6718713e2b..eb5b2182ece 100644
--- a/app/assets/javascripts/members/components/action_dropdowns/constants.js
+++ b/app/assets/javascripts/members/components/action_dropdowns/constants.js
@@ -11,4 +11,8 @@ export const I18N = {
confirmOrphanedUserRemoval: s__(
'Members|Are you sure you want to remove this orphaned member from "%{group}"?',
),
+ personalProjectOwnerCannotBeRemoved: s__("Members|A personal project's owner cannot be removed."),
+ lastGroupOwnerCannotBeRemoved: s__(
+ 'Members|A group must have at least one owner. To remove the member, assign a new owner.',
+ ),
};
diff --git a/app/assets/javascripts/members/components/action_dropdowns/leave_group_dropdown_item.vue b/app/assets/javascripts/members/components/action_dropdowns/leave_group_dropdown_item.vue
index b5e0317d54f..15606ad567c 100644
--- a/app/assets/javascripts/members/components/action_dropdowns/leave_group_dropdown_item.vue
+++ b/app/assets/javascripts/members/components/action_dropdowns/leave_group_dropdown_item.vue
@@ -18,6 +18,10 @@ export default {
type: Object,
required: true,
},
+ permissions: {
+ type: Object,
+ required: true,
+ },
},
};
</script>
@@ -27,6 +31,6 @@ export default {
<span class="gl-text-red-500">
<slot></slot>
</span>
- <leave-modal :member="member" />
+ <leave-modal :member="member" :permissions="permissions" />
</gl-dropdown-item>
</template>
diff --git a/app/assets/javascripts/members/components/action_dropdowns/remove_member_dropdown_item.vue b/app/assets/javascripts/members/components/action_dropdowns/remove_member_dropdown_item.vue
index 18f1a8739bf..f224aaa31f7 100644
--- a/app/assets/javascripts/members/components/action_dropdowns/remove_member_dropdown_item.vue
+++ b/app/assets/javascripts/members/components/action_dropdowns/remove_member_dropdown_item.vue
@@ -40,6 +40,11 @@ export default {
required: false,
default: () => ({}),
},
+ preventRemoval: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
computed: {
...mapState({
@@ -55,6 +60,7 @@ export default {
memberModelType: this.memberModelType,
message: this.modalMessage,
userDeletionObstacles: this.userDeletionObstacles,
+ preventRemoval: this.preventRemoval,
};
},
},
diff --git a/app/assets/javascripts/members/components/action_dropdowns/user_action_dropdown.vue b/app/assets/javascripts/members/components/action_dropdowns/user_action_dropdown.vue
index 4e5e6b0cab4..816481d4329 100644
--- a/app/assets/javascripts/members/components/action_dropdowns/user_action_dropdown.vue
+++ b/app/assets/javascripts/members/components/action_dropdowns/user_action_dropdown.vue
@@ -2,6 +2,10 @@
import { GlDropdown, GlTooltipDirective } from '@gitlab/ui';
import { sprintf } from '~/locale';
import { parseUserDeletionObstacles } from '~/vue_shared/components/user_deletion_obstacles/utils';
+import {
+ MEMBER_MODEL_TYPE_GROUP_MEMBER,
+ MEMBER_MODEL_TYPE_PROJECT_MEMBER,
+} from '~/members/constants';
import { I18N } from './constants';
import LeaveGroupDropdownItem from './leave_group_dropdown_item.vue';
import RemoveMemberDropdownItem from './remove_member_dropdown_item.vue';
@@ -37,6 +41,16 @@ export default {
modalMessage() {
const { user, source } = this.member;
+ if (this.permissions.canRemoveBlockedByLastOwner) {
+ if (this.member.type === MEMBER_MODEL_TYPE_PROJECT_MEMBER) {
+ return I18N.personalProjectOwnerCannotBeRemoved;
+ }
+
+ if (this.member.type === MEMBER_MODEL_TYPE_GROUP_MEMBER) {
+ return I18N.lastGroupOwnerCannotBeRemoved;
+ }
+ }
+
if (user) {
return sprintf(
this.$options.i18n.confirmNormalUserRemoval,
@@ -54,7 +68,10 @@ export default {
};
},
showDropdown() {
- return this.permissions.canRemove || this.showLdapOverride;
+ return this.showLeaveOrRemove || this.showLdapOverride;
+ },
+ showLeaveOrRemove() {
+ return this.permissions.canRemove || this.permissions.canRemoveBlockedByLastOwner;
},
showLdapOverride() {
return this.permissions.canOverride && !this.member.isOverridden;
@@ -76,8 +93,8 @@ export default {
data-testid="user-action-dropdown"
data-qa-selector="user_action_dropdown"
>
- <template v-if="permissions.canRemove">
- <leave-group-dropdown-item v-if="isCurrentUser" :member="member">{{
+ <template v-if="showLeaveOrRemove">
+ <leave-group-dropdown-item v-if="isCurrentUser" :member="member" :permissions="permissions">{{
$options.i18n.leaveGroup
}}</leave-group-dropdown-item>
<remove-member-dropdown-item
@@ -86,6 +103,7 @@ export default {
:member-model-type="member.type"
:user-deletion-obstacles="userDeletionObstaclesUserData"
:modal-message="modalMessage"
+ :prevent-removal="permissions.canRemoveBlockedByLastOwner"
>{{ $options.i18n.removeMember }}</remove-member-dropdown-item
>
</template>
diff --git a/app/assets/javascripts/members/components/modals/leave_modal.vue b/app/assets/javascripts/members/components/modals/leave_modal.vue
index e39669e17dd..8bc6aca9cc1 100644
--- a/app/assets/javascripts/members/components/modals/leave_modal.vue
+++ b/app/assets/javascripts/members/components/modals/leave_modal.vue
@@ -5,22 +5,30 @@ import csrf from '~/lib/utils/csrf';
import { __, s__, sprintf } from '~/locale';
import UserDeletionObstaclesList from '~/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.vue';
import { parseUserDeletionObstacles } from '~/vue_shared/components/user_deletion_obstacles/utils';
-import { LEAVE_MODAL_ID } from '../../constants';
+import {
+ LEAVE_MODAL_ID,
+ MEMBER_MODEL_TYPE_GROUP_MEMBER,
+ MEMBER_MODEL_TYPE_PROJECT_MEMBER,
+} from '../../constants';
export default {
name: 'LeaveModal',
actionCancel: {
text: __('Cancel'),
},
- actionPrimary: {
- text: __('Leave'),
- attributes: {
- variant: 'danger',
- },
- },
csrf,
modalId: LEAVE_MODAL_ID,
- modalContent: s__('Members|Are you sure you want to leave "%{source}"?'),
+ i18n: {
+ title: s__('Members|Leave "%{source}"'),
+ body: s__('Members|Are you sure you want to leave "%{source}"?'),
+ preventedTitle: s__('Members|Cannot leave "%{source}"'),
+ preventedBodyProjectMemberModelType: s__(
+ 'Members|You cannot remove yourself from a personal project.',
+ ),
+ preventedBodyGroupMemberModelType: s__(
+ 'Members|A group must have at least one owner. To leave this group, assign a new owner.',
+ ),
+ },
components: { GlModal, GlForm, GlSprintf, UserDeletionObstaclesList },
directives: {
GlTooltip: GlTooltipDirective,
@@ -31,6 +39,10 @@ export default {
type: Object,
required: true,
},
+ permissions: {
+ type: Object,
+ required: true,
+ },
},
computed: {
...mapState({
@@ -42,7 +54,35 @@ export default {
return this.memberPath.replace(/:id$/, 'leave');
},
modalTitle() {
- return sprintf(s__('Members|Leave "%{source}"'), { source: this.member.source.fullName });
+ return sprintf(
+ this.permissions.canRemoveBlockedByLastOwner
+ ? this.$options.i18n.preventedTitle
+ : this.$options.i18n.title,
+ { source: this.member.source.fullName },
+ );
+ },
+ preventedModalBody() {
+ if (this.member.type === MEMBER_MODEL_TYPE_PROJECT_MEMBER) {
+ return this.$options.i18n.preventedBodyProjectMemberModelType;
+ }
+
+ if (this.member.type === MEMBER_MODEL_TYPE_GROUP_MEMBER) {
+ return this.$options.i18n.preventedBodyGroupMemberModelType;
+ }
+
+ return null;
+ },
+ actionPrimary() {
+ if (this.permissions.canRemoveBlockedByLastOwner) {
+ return null;
+ }
+
+ return {
+ text: __('Leave'),
+ attributes: {
+ variant: 'danger',
+ },
+ };
},
obstacles() {
return parseUserDeletionObstacles(this.member.user);
@@ -64,13 +104,14 @@ export default {
v-bind="$attrs"
:modal-id="$options.modalId"
:title="modalTitle"
- :action-primary="$options.actionPrimary"
+ :action-primary="actionPrimary"
:action-cancel="$options.actionCancel"
@primary="handlePrimary"
>
<gl-form ref="form" :action="leavePath" method="post">
<p>
- <gl-sprintf :message="$options.modalContent">
+ <template v-if="permissions.canRemoveBlockedByLastOwner">{{ preventedModalBody }}</template>
+ <gl-sprintf v-else :message="$options.i18n.body">
<template #source>{{ member.source.fullName }}</template>
</gl-sprintf>
</p>
diff --git a/app/assets/javascripts/members/components/modals/remove_member_modal.vue b/app/assets/javascripts/members/components/modals/remove_member_modal.vue
index edd464574fb..337379d8b4e 100644
--- a/app/assets/javascripts/members/components/modals/remove_member_modal.vue
+++ b/app/assets/javascripts/members/components/modals/remove_member_modal.vue
@@ -42,6 +42,9 @@ export default {
userDeletionObstacles(state) {
return state[this.namespace].removeMemberModalData.userDeletionObstacles ?? {};
},
+ preventRemoval(state) {
+ return state[this.namespace].removeMemberModalData.preventRemoval;
+ },
removeMemberModalVisible(state) {
return state[this.namespace].removeMemberModalVisible;
},
@@ -59,6 +62,10 @@ export default {
return __('Remove member');
},
actionPrimary() {
+ if (this.preventRemoval) {
+ return null;
+ }
+
return {
text: this.actionText,
attributes: {
@@ -101,21 +108,22 @@ export default {
>
<form ref="form" :action="memberPath" method="post">
<p>{{ message }}</p>
+ <template v-if="!preventRemoval">
+ <user-deletion-obstacles-list
+ v-if="hasObstaclesToUserDeletion"
+ :obstacles="userDeletionObstacles.obstacles"
+ :user-name="userDeletionObstacles.name"
+ />
- <user-deletion-obstacles-list
- v-if="hasObstaclesToUserDeletion"
- :obstacles="userDeletionObstacles.obstacles"
- :user-name="userDeletionObstacles.name"
- />
-
- <input ref="method" type="hidden" name="_method" value="delete" />
- <input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
- <gl-form-checkbox v-if="isGroupMember" name="remove_sub_memberships">
- {{ __('Also remove direct user membership from subgroups and projects') }}
- </gl-form-checkbox>
- <gl-form-checkbox v-if="hasWorkspaceAccess" name="unassign_issuables">
- {{ __('Also unassign this user from related issues and merge requests') }}
- </gl-form-checkbox>
+ <input ref="method" type="hidden" name="_method" value="delete" />
+ <input :value="$options.csrf.token" type="hidden" name="authenticity_token" />
+ <gl-form-checkbox v-if="isGroupMember" name="remove_sub_memberships">
+ {{ __('Also remove direct user membership from subgroups and projects') }}
+ </gl-form-checkbox>
+ <gl-form-checkbox v-if="hasWorkspaceAccess" name="unassign_issuables">
+ {{ __('Also unassign this user from related issues and merge requests') }}
+ </gl-form-checkbox>
+ </template>
</form>
</gl-modal>
</template>
diff --git a/app/assets/javascripts/members/components/table/members_table.vue b/app/assets/javascripts/members/components/table/members_table.vue
index c847f9c8311..6d242f38d0e 100644
--- a/app/assets/javascripts/members/components/table/members_table.vue
+++ b/app/assets/javascripts/members/components/table/members_table.vue
@@ -2,7 +2,14 @@
import { GlTable, GlBadge, GlPagination } from '@gitlab/ui';
import { mapState } from 'vuex';
import MembersTableCell from 'ee_else_ce/members/components/table/members_table_cell.vue';
-import { canUnban, canOverride, canRemove, canResend, canUpdate } from 'ee_else_ce/members/utils';
+import {
+ canUnban,
+ canOverride,
+ canRemove,
+ canRemoveBlockedByLastOwner,
+ canResend,
+ canUpdate,
+} from 'ee_else_ce/members/utils';
import { mergeUrlParams } from '~/lib/utils/url_utility';
import {
FIELD_KEY_ACTIONS,
@@ -43,7 +50,7 @@ export default {
LdapOverrideConfirmationModal: () =>
import('ee_component/members/components/ldap/ldap_override_confirmation_modal.vue'),
},
- inject: ['namespace', 'currentUserId'],
+ inject: ['namespace', 'currentUserId', 'canManageMembers'],
props: {
tabQueryParamValue: {
type: String,
@@ -84,6 +91,7 @@ export default {
hasActionButtons(member) {
return (
canRemove(member) ||
+ canRemoveBlockedByLastOwner(member, this.canManageMembers) ||
canResend(member) ||
canUpdate(member, this.currentUserId) ||
canOverride(member) ||
diff --git a/app/assets/javascripts/members/components/table/members_table_cell.vue b/app/assets/javascripts/members/components/table/members_table_cell.vue
index 51eff428d63..407cbc55dd3 100644
--- a/app/assets/javascripts/members/components/table/members_table_cell.vue
+++ b/app/assets/javascripts/members/components/table/members_table_cell.vue
@@ -5,13 +5,14 @@ import {
isDirectMember,
isCurrentUser,
canRemove,
+ canRemoveBlockedByLastOwner,
canResend,
canUpdate,
} from '../../utils';
export default {
name: 'MembersTableCell',
- inject: ['currentUserId'],
+ inject: ['currentUserId', 'canManageMembers'],
props: {
member: {
type: Object,
@@ -45,6 +46,9 @@ export default {
isCurrentUser() {
return isCurrentUser(this.member, this.currentUserId);
},
+ canRemoveBlockedByLastOwner() {
+ return canRemoveBlockedByLastOwner(this.member, this.canManageMembers);
+ },
canRemove() {
return canRemove(this.member);
},
@@ -62,6 +66,7 @@ export default {
isCurrentUser: this.isCurrentUser,
permissions: {
canRemove: this.canRemove,
+ canRemoveBlockedByLastOwner: this.canRemoveBlockedByLastOwner,
canResend: this.canResend,
canUpdate: this.canUpdate,
},
diff --git a/app/assets/javascripts/members/utils.js b/app/assets/javascripts/members/utils.js
index bf87ab53d36..b7af97ebac5 100644
--- a/app/assets/javascripts/members/utils.js
+++ b/app/assets/javascripts/members/utils.js
@@ -51,6 +51,9 @@ export const canRemove = (member) => {
return isDirectMember(member) && member.canRemove;
};
+export const canRemoveBlockedByLastOwner = (member, canManageMembers) =>
+ isDirectMember(member) && canManageMembers && member.isLastOwner;
+
export const canResend = (member) => {
return Boolean(member.invite?.canResend);
};
diff --git a/app/controllers/registrations/welcome_controller.rb b/app/controllers/registrations/welcome_controller.rb
index 69cf1c42f34..8676dfa1da2 100644
--- a/app/controllers/registrations/welcome_controller.rb
+++ b/app/controllers/registrations/welcome_controller.rb
@@ -26,13 +26,14 @@ module Registrations
return redirect_to issues_dashboard_path(assignee_username: current_user.username) if show_tasks_to_be_done?
- return redirect_to update_success_path if show_signup_onboarding?
+ return redirect_to update_success_path if redirect_to_signup_onboarding?
members = current_user.members
if registering_from_invite?(members)
redirect_to members_activity_path(members), notice: helpers.invite_accepted_notice(members.last)
else
+ # subscription registrations goes through here as well
redirect_to path_for_signed_in_user(current_user)
end
else
@@ -79,7 +80,7 @@ module Registrations
end
# overridden in EE
- def show_signup_onboarding?
+ def redirect_to_signup_onboarding?
false
end
diff --git a/app/views/groups/_group_admin_settings.html.haml b/app/views/groups/_group_admin_settings.html.haml
index 0b26db64ffa..8547795b4b7 100644
--- a/app/views/groups/_group_admin_settings.html.haml
+++ b/app/views/groups/_group_admin_settings.html.haml
@@ -36,4 +36,4 @@
= f.gitlab_ui_checkbox_component :runner_registration_enabled,
s_('Runners|New group runners can be registered'),
checkbox_options: { checked: @group.runner_registration_enabled && !parent_disabled, disabled: parent_disabled },
- help_text: s_('Runners|Existing runners are not affected. To permit runner registration for all groups, enable this setting in the Admin Area in Settings &gt CI/CD.').html_safe
+ help_text: s_('Runners|Existing runners are not affected. To permit runner registration for all groups, enable this setting in the Admin Area in Settings &gt; CI/CD.').html_safe
diff --git a/config/feature_flags/development/admin_emails_vue.yml b/config/feature_flags/development/admin_emails_vue.yml
new file mode 100644
index 00000000000..63fe56e089f
--- /dev/null
+++ b/config/feature_flags/development/admin_emails_vue.yml
@@ -0,0 +1,8 @@
+---
+name: admin_emails_vue
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/106358
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/386976
+milestone: '15.8'
+type: development
+group: group::workspace
+default_enabled: false
diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md
index d76c728fb78..80a6d785789 100644
--- a/doc/administration/packages/container_registry.md
+++ b/doc/administration/packages/container_registry.md
@@ -777,7 +777,7 @@ auth:
Without these entries, the registry logins cannot authenticate with GitLab.
GitLab also remains unaware of
-[nested image names](../../user/packages/container_registry/index.md#image-naming-convention)
+[nested image names](../../user/packages/container_registry/index.md#naming-convention-for-your-container-images)
under the project hierarchy, like
`registry.example.com/group/project/image-name:tag` or
`registry.example.com/group/project/my/image-name:tag`, and only recognizes
diff --git a/doc/api/graphql/users_example.md b/doc/api/graphql/users_example.md
index 9d223f9e618..20185d81513 100644
--- a/doc/api/graphql/users_example.md
+++ b/doc/api/graphql/users_example.md
@@ -12,7 +12,6 @@ You can run the same query directly via a HTTP endpoint, using `cURL`. For more
guidance on getting started from the [command line](getting_started.md#command-line).
The [example users query](#set-up-the-graphiql-explorer) looks for a subset of users in
-o
a GitLab instance either by username or
[Global ID](../../development/api_graphql_styleguide.md#global-ids).
The query includes:
diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md
index 371e3f9ae47..14f8ae3b15b 100644
--- a/doc/api/oauth2.md
+++ b/doc/api/oauth2.md
@@ -417,7 +417,7 @@ Standard OAuth 2.0 tokens support different degrees of access to GitLab
registries, as they:
- Do not allow users to authenticate to:
- - The GitLab [Container registry](../user/packages/container_registry/index.md#authenticate-with-the-container-registry).
+ - The GitLab [Container registry](../user/packages/container_registry/authenticate_with_container_registry.md).
- Packages listed in the GitLab [Package registry](../user/packages/package_registry/index.md).
- Allow users to get, list, and delete registries through
the [Container registry API](container_registry.md).
diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md
index ea62133cb7f..04c790cf3c6 100644
--- a/doc/ci/docker/using_docker_build.md
+++ b/doc/ci/docker/using_docker_build.md
@@ -872,7 +872,7 @@ build:
## Use the GitLab Container Registry
After you've built a Docker image, you can push it up to the built-in
-[GitLab Container Registry](../../user/packages/container_registry/index.md#build-and-push-by-using-gitlab-cicd).
+[GitLab Container Registry](../../user/packages/container_registry/build_and_push_images.md#use-gitlab-cicd).
## Troubleshooting
diff --git a/doc/ci/jobs/ci_job_token.md b/doc/ci/jobs/ci_job_token.md
index d95451a67dc..4ae4456c56c 100644
--- a/doc/ci/jobs/ci_job_token.md
+++ b/doc/ci/jobs/ci_job_token.md
@@ -14,7 +14,7 @@ You can use a GitLab CI/CD job token to authenticate with specific API endpoints
- Packages:
- [Package Registry](../../user/packages/package_registry/index.md#use-gitlab-cicd-to-build-packages).
- [Packages API](../../api/packages.md) (project-level).
- - [Container Registry](../../user/packages/container_registry/index.md#build-and-push-by-using-gitlab-cicd)
+ - [Container Registry](../../user/packages/container_registry/build_and_push_images.md#use-gitlab-cicd)
(the `$CI_REGISTRY_PASSWORD` is `$CI_JOB_TOKEN`).
- [Container Registry API](../../api/container_registry.md)
(scoped to the job's project, when the `ci_job_token_scope` feature flag is enabled).
diff --git a/doc/ci/migration/jenkins.md b/doc/ci/migration/jenkins.md
index 235dd0e80ca..5e5d67fdaac 100644
--- a/doc/ci/migration/jenkins.md
+++ b/doc/ci/migration/jenkins.md
@@ -21,7 +21,7 @@ that were able to quickly complete this migration:
1. Educate and enable your developers to independently perform the following steps in their projects:
1. Review the [Quick Start Guide](../quick_start/index.md) and [Pipeline Configuration Reference](../yaml/index.md).
1. Use the [Jenkins Wrapper](#jenkinsfile-wrapper) to temporarily maintain fragile Jenkins jobs.
- 1. Migrate the build and CI jobs and configure them to show results directly in your merge requests. They can use [Auto DevOps](../../topics/autodevops/index.md) as a starting point, and [customize](../../topics/autodevops/customize.md) or [decompose](../../topics/autodevops/customize.md#using-components-of-auto-devops) the configuration as needed.
+ 1. Migrate the build and CI jobs and configure them to show results directly in your merge requests. They can use [Auto DevOps](../../topics/autodevops/index.md) as a starting point, and [customize](../../topics/autodevops/customize.md) or [decompose](../../topics/autodevops/customize.md#use-individual-components-of-auto-devops) the configuration as needed.
1. Add [Review Apps](../review_apps/index.md).
1. Migrate the deployment jobs using [cloud deployment templates](../cloud_deployment/index.md), adding [environments](../environments/index.md), and [deploy boards](../../user/project/deploy_boards.md).
1. Work to unwrap any jobs still running with the use of the Jenkins wrapper.
diff --git a/doc/development/architecture.md b/doc/development/architecture.md
index 5eb1dcc3208..c7aa3ed09c4 100644
--- a/doc/development/architecture.md
+++ b/doc/development/architecture.md
@@ -761,7 +761,7 @@ See our [Redis guidelines](redis.md) for more information about how GitLab uses
- [Source](../administration/packages/container_registry.md#enable-the-container-registry)
- [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/main/doc/howto/registry.md)
- Layer: Core Service (Processor)
-- GitLab.com: [GitLab Container Registry](../user/packages/container_registry/index.md#build-and-push-by-using-gitlab-cicd)
+- GitLab.com: [GitLab Container Registry](../user/packages/container_registry/build_and_push_images.md#use-gitlab-cicd)
The registry is what users use to store their own Docker images. The bundled
registry uses NGINX as a load balancer and GitLab as an authentication manager.
diff --git a/doc/development/features_inside_dot_gitlab.md b/doc/development/features_inside_dot_gitlab.md
index 7a46cd40da1..dda2c05288f 100644
--- a/doc/development/features_inside_dot_gitlab.md
+++ b/doc/development/features_inside_dot_gitlab.md
@@ -15,7 +15,7 @@ When implementing new features, please refer to these existing features to avoid
- [GitLab agent](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/blob/master/doc/configuration_repository.md#layout): `.gitlab/agents/`.
- [CODEOWNERS](../user/project/code_owners.md#set-up-code-owners): `.gitlab/CODEOWNERS`.
- [Route Maps](../ci/review_apps/index.md#route-maps): `.gitlab/route-map.yml`.
-- [Customize Auto DevOps Helm Values](../topics/autodevops/customize.md#customize-values-for-helm-chart): `.gitlab/auto-deploy-values.yaml`.
+- [Customize Auto DevOps Helm Values](../topics/autodevops/customize.md#customize-helm-chart-values): `.gitlab/auto-deploy-values.yaml`.
- [Insights](../user/project/insights/index.md#configure-project-insights): `.gitlab/insights.yml`.
- [Service Desk Templates](../user/project/service_desk.md#using-customized-email-templates): `.gitlab/service_desk_templates/`.
- [Web IDE](../user/project/web_ide/index.md#web-ide-configuration-file): `.gitlab/.gitlab-webide.yml`.
diff --git a/doc/development/service_ping/implement.md b/doc/development/service_ping/implement.md
index f828fa62244..1e5f4191375 100644
--- a/doc/development/service_ping/implement.md
+++ b/doc/development/service_ping/implement.md
@@ -804,7 +804,7 @@ and run a local container instance:
1. In the downstream pipeline, wait for the `gitlab-docker` job to finish.
1. Open the job logs and locate the full container name including the version. It takes the following form: `registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>`.
1. On your local machine, make sure you are signed in to the GitLab Docker registry. You can find the instructions for this in
- [Authenticate to the GitLab Container Registry](../../user/packages/container_registry/index.md#authenticate-with-the-container-registry).
+ [Authenticate to the GitLab Container Registry](../../user/packages/container_registry/authenticate_with_container_registry.md).
1. Once signed in, download the new image by using `docker pull registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>`
1. For more information about working with and running Omnibus GitLab containers in Docker, refer to [GitLab Docker images](../../install/docker.md) documentation.
diff --git a/doc/topics/autodevops/cicd_variables.md b/doc/topics/autodevops/cicd_variables.md
index ad248bc3ccd..470f973a318 100644
--- a/doc/topics/autodevops/cicd_variables.md
+++ b/doc/topics/autodevops/cicd_variables.md
@@ -22,7 +22,7 @@ Use these variables to customize and deploy your build.
| `AUTO_DEVOPS_ATOMIC_RELEASE` | As of GitLab 13.0, Auto DevOps uses [`--atomic`](https://v2.helm.sh/docs/helm/#options-43) for Helm deployments by default. Set this variable to `false` to disable the use of `--atomic` |
| `AUTO_DEVOPS_BUILD_IMAGE_CNB_ENABLED` | Set to `false` to use Herokuish instead of Cloud Native Buildpacks with Auto Build. [More details](stages.md#auto-build-using-cloud-native-buildpacks). |
| `AUTO_DEVOPS_BUILD_IMAGE_CNB_BUILDER` | The builder used when building with Cloud Native Buildpacks. The default builder is `heroku/buildpacks:18`. [More details](stages.md#auto-build-using-cloud-native-buildpacks). |
-| `AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` | Extra arguments to be passed to the `docker build` command. Using quotes doesn't prevent word splitting. [More details](customize.md#passing-arguments-to-docker-build). |
+| `AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` | Extra arguments to be passed to the `docker build` command. Using quotes doesn't prevent word splitting. [More details](customize.md#pass-arguments-to-docker-build). |
| `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` | A [comma-separated list of CI/CD variable names](customize.md#forward-cicd-variables-to-the-build-environment) to be forwarded to the build environment (the buildpack builder or `docker build`). |
| `AUTO_DEVOPS_BUILD_IMAGE_CNB_PORT` | In GitLab 15.0 and later, port exposed by the generated Docker image. Set to `false` to prevent exposing any ports. Defaults to `5000`. |
| `AUTO_DEVOPS_CHART` | Helm Chart used to deploy your apps. Defaults to the one [provided by GitLab](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app). |
@@ -42,7 +42,7 @@ Use these variables to customize and deploy your build.
| `CI_APPLICATION_REPOSITORY` | The repository of container image being built or deployed, `$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG`. For more details, read [Custom container image](customize.md#custom-container-image). |
| `CI_APPLICATION_TAG` | The tag of the container image being built or deployed, `$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG`. For more details, read [Custom container image](customize.md#custom-container-image). |
| `DAST_AUTO_DEPLOY_IMAGE_VERSION` | Customize the image version used for DAST deployments on the default branch. Should usually be the same as `AUTO_DEPLOY_IMAGE_VERSION`. See [list of versions](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/releases). |
-| `DOCKERFILE_PATH` | From GitLab 13.2, allows overriding the [default Dockerfile path for the build stage](customize.md#custom-dockerfile) |
+| `DOCKERFILE_PATH` | From GitLab 13.2, allows overriding the [default Dockerfile path for the build stage](customize.md#custom-dockerfiles) |
| `HELM_RELEASE_NAME` | Allows the `helm` release name to be overridden. Can be used to assign unique release names when deploying multiple projects to a single namespace. |
| `HELM_UPGRADE_VALUES_FILE` | Allows the `helm upgrade` values file to be overridden. Defaults to `.gitlab/auto-deploy-values.yaml`. |
| `HELM_UPGRADE_EXTRA_ARGS` | Allows extra options in `helm upgrade` commands when deploying the application. Using quotes doesn't prevent word splitting. |
@@ -53,7 +53,7 @@ Use these variables to customize and deploy your build.
| `KUBE_NAMESPACE` | The namespace used for deployments. When using certificate-based clusters, [this value should not be overwritten directly](../../user/project/clusters/deploy_to_cluster.md#custom-namespace). |
| `KUBECONFIG` | The kubeconfig to use for deployments. User-provided values take priority over GitLab-provided values. |
| `PRODUCTION_REPLICAS` | Number of replicas to deploy in the production environment. Takes precedence over `REPLICAS` and defaults to 1. For zero downtime upgrades, set to 2 or greater. |
-| `REPLICAS` | Number of replicas to deploy. Defaults to 1. Change this variable instead of [modifying](customize.md#customize-values-for-helm-chart) `replicaCount`. |
+| `REPLICAS` | Number of replicas to deploy. Defaults to 1. Change this variable instead of [modifying](customize.md#customize-helm-chart-values) `replicaCount`. |
| `ROLLOUT_RESOURCE_TYPE` | Allows specification of the resource type being deployed when using a custom Helm chart. Default value is `deployment`. |
| `ROLLOUT_STATUS_DISABLED` | Used to disable rollout status check because it does not support all resource types, for example, `cronjob`. |
| `STAGING_ENABLED` | Used to define a [deploy policy for staging and production environments](#deploy-policy-for-staging-and-production-environments). |
diff --git a/doc/topics/autodevops/customize.md b/doc/topics/autodevops/customize.md
index c42f5825b6a..43769410eba 100644
--- a/doc/topics/autodevops/customize.md
+++ b/doc/topics/autodevops/customize.md
@@ -4,23 +4,22 @@ group: Configure
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
-# Customizing Auto DevOps **(FREE)**
+# Customize Auto DevOps **(FREE)**
-While [Auto DevOps](index.md) provides great defaults to get you started, you can customize
-almost everything to fit your needs. Auto DevOps offers everything from custom
-[buildpacks](#custom-buildpacks), to [Dockerfiles](#custom-dockerfile), and
-[Helm charts](#custom-helm-chart). You can even copy the complete
-[CI/CD configuration](#customizing-gitlab-ciyml) into your project to enable
-staging and canary deployments,
-[manage Auto DevOps with GitLab APIs](customize.md#extend-auto-devops-with-the-api), and more.
+You can customize components of Auto DevOps to fit your needs. For example, you can:
+
+- Add custom [buildpacks](#custom-buildpacks), [Dockerfiles](#custom-dockerfiles), and [Helm charts](#custom-helm-chart).
+- Enable staging and canary deployments with a custom [CI/CD configuration](#customize-gitlab-ciyml).
+- Extend Auto DevOps with the [GitLab API](#extend-auto-devops-with-the-api).
## Custom buildpacks
-If the automatic buildpack detection fails for your project, or if you
-need more control over your build, you can customize the buildpacks
-used for the build.
+You can customize your buildpacks when either:
+
+- The automatic buildpack detection fails for your project.
+- You need more control over your build.
-### Custom buildpacks with Cloud Native Buildpacks
+### Customize buildpacks with Cloud Native Buildpacks
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/28165) in GitLab 12.10.
@@ -29,17 +28,18 @@ Specify either:
- The CI/CD variable `BUILDPACK_URL` with any of [`pack`'s URI specification formats](https://buildpacks.io/docs/app-developer-guide/specify-buildpacks/).
- A [`project.toml` project descriptor](https://buildpacks.io/docs/app-developer-guide/using-project-descriptor/) with the buildpacks you would like to include.
-### Custom buildpacks with Herokuish
+### Customize buildpacks with Herokuish
Specify either:
- The CI/CD variable `BUILDPACK_URL`.
-- A `.buildpacks` file at the root of your project, containing one buildpack URL per line.
+- A `.buildpacks` file at the root of your project that contains one buildpack URL per line.
The buildpack URL can point to either a Git repository URL or a tarball URL.
-For Git repositories, you can point to a specific Git reference (such as
-commit SHA, tag name, or branch name) by appending `#<ref>` to the Git repository URL.
-For example:
+
+For Git repositories, you can point to a specific Git reference by
+appending `#<ref>` to the Git repository URL. For example, you can
+reference:
- The tag `v142`: `https://github.com/heroku/heroku-buildpack-ruby.git#v142`.
- The branch `mybranch`: `https://github.com/heroku/heroku-buildpack-ruby.git#mybranch`.
@@ -47,35 +47,38 @@ For example:
### Multiple buildpacks
-Using multiple buildpacks is not fully supported by Auto DevOps, because Auto Test
-can't use the `.buildpacks` file. The buildpack
-[heroku-buildpack-multi](https://github.com/heroku/heroku-buildpack-multi/), used
-in the backend to parse the `.buildpacks` file, does not provide the necessary commands
-`bin/test-compile` and `bin/test`.
+Because Auto Test cannot use the `.buildpacks` file, Auto DevOps does
+not support multiple buildpacks. The buildpack
+[heroku-buildpack-multi](https://github.com/heroku/heroku-buildpack-multi/),
+used in the backend to parse the `.buildpacks` file, does not provide
+the necessary commands `bin/test-compile` and `bin/test`.
-If your goal is to use only a single custom buildpack, you should provide the project CI/CD variable
+To use only a single custom buildpack, you should provide the project CI/CD variable
`BUILDPACK_URL` instead.
-## Custom `Dockerfile`
+## Custom Dockerfiles
> Support for `DOCKERFILE_PATH` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/35662) in GitLab 13.2
-If your project has a `Dockerfile` in the root of the project repository, Auto DevOps
-builds a Docker image based on the Dockerfile, rather than using buildpacks.
-This can be much faster and result in smaller images, especially if your
-Dockerfile is based on [Alpine](https://hub.docker.com/_/alpine/).
+If you have a Dockerfile in the root of your project repository, Auto
+DevOps builds a Docker image based on the Dockerfile. This can be
+faster than using a buildpack. It can also result in smaller images,
+especially if your Dockerfile is based on
+[Alpine](https://hub.docker.com/_/alpine/).
If you set the `DOCKERFILE_PATH` CI/CD variable, Auto Build looks for a Dockerfile there
instead.
-## Passing arguments to `docker build`
+### Pass arguments to `docker build`
-Arguments can be passed to the `docker build` command using the
-`AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` project CI/CD variable. For example, to build a
-Docker image based on based on the `ruby:alpine` instead of the default `ruby:latest`:
+You can pass arguments to `docker build` with the
+`AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` project CI/CD variable.
+
+For example, to build a Docker image based on based on the
+`ruby:alpine` instead of the default `ruby:latest`:
1. Set `AUTO_DEVOPS_BUILD_IMAGE_EXTRA_ARGS` to `--build-arg=RUBY_VERSION=alpine`.
-1. Add the following to a custom `Dockerfile`:
+1. Add the following to a custom Dockerfile:
```dockerfile
ARG RUBY_VERSION=latest
@@ -84,14 +87,12 @@ Docker image based on based on the `ruby:alpine` instead of the default `ruby:la
# ... put your stuff here
```
-Use Base64 encoding if you need to pass complex values, such as newlines and
-spaces. Left unencoded, complex values like these can cause escaping issues
-due to how Auto DevOps uses the arguments.
+To pass complex values like spaces and newlines, use Base64 encoding.
+Complex, unencoded values can cause issues with character escaping.
WARNING:
-Avoid passing secrets as Docker build arguments if possible, as they may be
-persisted in your image. See
-[this discussion of best practices with secrets](https://github.com/moby/moby/issues/13490) for details.
+Do not pass secrets as Docker build arguments. Secrets might persist in your image. For more information, see
+[this discussion of best practices with secrets](https://github.com/moby/moby/issues/13490).
## Custom container image
@@ -104,12 +105,12 @@ You can override this behavior by defining specific variables:
| Image Tag | `$CI_COMMIT_SHA` for branch pipelines. `$CI_COMMIT_TAG` for tag pipelines. | `$CI_APPLICATION_TAG` |
These variables also affect Auto Build and Auto Container Scanning. If you don't want to build and push an image to
-`$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG`, consider
-including only `Jobs/Deploy.gitlab-ci.yml`, or [disabling the `build` jobs](cicd_variables.md#job-disabling-variables).
+`$CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG`, include only `Jobs/Deploy.gitlab-ci.yml`, or
+[disable the `build` jobs](cicd_variables.md#job-disabling-variables).
If you use Auto Container Scanning and set a value for `$CI_APPLICATION_REPOSITORY`, then you should
-also update `$CS_DEFAULT_BRANCH_IMAGE`. See [Setting the default branch image](../../user/application_security/container_scanning/index.md#setting-the-default-branch-image)
-for more details.
+also update `$CS_DEFAULT_BRANCH_IMAGE`. For more information, see
+[Setting the default branch image](../../user/application_security/container_scanning/index.md#setting-the-default-branch-image).
Here is an example setup in your `.gitlab-ci.yml`:
@@ -123,119 +124,120 @@ variables:
You can extend and manage your Auto DevOps configuration with GitLab APIs:
-- [Settings that can be accessed with API calls](../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls),
+- [Use API calls to access settings](../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls),
which include `auto_devops_enabled`, to enable Auto DevOps on projects by default.
-- [Creating a new project](../../api/projects.md#create-project).
-- [Editing groups](../../api/groups.md#update-group).
-- [Editing projects](../../api/projects.md#edit-project).
+- [Create a new project](../../api/projects.md#create-project).
+- [Edit groups](../../api/groups.md#update-group).
+- [Edit projects](../../api/projects.md#edit-project).
## Forward CI/CD variables to the build environment
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25514) in GitLab 12.3, but available in GitLab 12.0 and later.
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/25514) in GitLab 12.3.
+
+To forward CI/CD variables to the build environment, add the names of the variables
+you want to forward to the `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` CI/CD variable.
+Separate multiple variables with commas.
-CI/CD variables can be forwarded into the build environment using the
-`AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` CI/CD variable.
-The forwarded variables should be specified by name in a comma-separated
-list. For example, to forward the variables `CI_COMMIT_SHA` and
-`CI_ENVIRONMENT_NAME`, set `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES`
-to `CI_COMMIT_SHA,CI_ENVIRONMENT_NAME`.
+For example, to forward the variables `CI_COMMIT_SHA` and `CI_ENVIRONMENT_NAME`:
-- When using Buildpacks, the forwarded variables are available automatically
- as environment variables.
-- When using a `Dockerfile`, the following additional steps are required:
+```yaml
+variables:
+ AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES: CI_COMMIT_SHA,CI_ENVIRONMENT_NAME
+```
- 1. Activate the experimental `Dockerfile` syntax by adding the following code
- to the top of the file:
+If you use buildpacks, the forwarded variables are available automatically as environment variables.
- ```dockerfile
- # syntax = docker/dockerfile:experimental
- ```
+If you use a Dockerfile:
- 1. To make secrets available in any `RUN $COMMAND` in the `Dockerfile`, mount
- the secret file and source it prior to running `$COMMAND`:
+1. To activate the experimental Dockerfile syntax, add the following to your Dockerfile:
- ```dockerfile
- RUN --mount=type=secret,id=auto-devops-build-secrets . /run/secrets/auto-devops-build-secrets && $COMMAND
- ```
+ ```dockerfile
+ # syntax = docker/dockerfile:experimental
+ ```
+
+1. To make secrets available in any `RUN $COMMAND` in the `Dockerfile`, mount
+ the secret file and source it before you run `$COMMAND`:
+
+ ```dockerfile
+ RUN --mount=type=secret,id=auto-devops-build-secrets . /run/secrets/auto-devops-build-secrets && $COMMAND
+ ```
When `AUTO_DEVOPS_BUILD_IMAGE_FORWARDED_CI_VARIABLES` is set, Auto DevOps
enables the experimental [Docker BuildKit](https://docs.docker.com/build/buildkit/)
feature to use the `--secret` flag.
-## Custom Helm Chart
+## Custom Helm chart
Auto DevOps uses [Helm](https://helm.sh/) to deploy your application to Kubernetes.
-You can override the Helm chart used by bundling up a chart into your project
+You can override the Helm chart used by bundling a chart in your project
repository or by specifying a project CI/CD variable:
- **Bundled chart** - If your project has a `./chart` directory with a `Chart.yaml`
file in it, Auto DevOps detects the chart and uses it instead of the
- [default chart](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app), enabling
- you to control exactly how your application is deployed.
+ [default chart](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app).
- **Project variable** - Create a [project CI/CD variable](../../ci/variables/index.md)
- `AUTO_DEVOPS_CHART` with the URL of a custom chart to use, or create two project
- variables: `AUTO_DEVOPS_CHART_REPOSITORY` with the URL of a custom chart repository,
- and `AUTO_DEVOPS_CHART` with the path to the chart.
+ `AUTO_DEVOPS_CHART` with the URL of a custom chart. You can also create two project
+ variables:
+
+ - `AUTO_DEVOPS_CHART_REPOSITORY` - The URL of a custom chart repository.
+ - `AUTO_DEVOPS_CHART` - The path to the chart.
-## Customize values for Helm Chart
+### Customize Helm chart values
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/30628) in GitLab 12.6, `.gitlab/auto-deploy-values.yaml` is used by default for Helm upgrades.
-You can override the default values in the `values.yaml` file in the
-[default Helm chart](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app) by either:
+To override the default values in the `values.yaml` file in the
+[default Helm chart](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/tree/master/assets/auto-deploy-app), either:
-- Adding a file named `.gitlab/auto-deploy-values.yaml` to your repository, which is
- automatically used, if found.
-- Adding a file with a different name or path to the repository, and setting the
- `HELM_UPGRADE_VALUES_FILE` [CI/CD variable](cicd_variables.md) with
- the path and name.
+- Add a file named `.gitlab/auto-deploy-values.yaml` to your repository. This file is automatically used.
+- Add a file with a different name or path to the repository. Set the
+ `HELM_UPGRADE_VALUES_FILE` [CI/CD variable](cicd_variables.md) with the path and name of the file.
-Some values cannot be overridden with the options above. Settings like `replicaCount` should instead be overridden with the `REPLICAS`
-[build and deployment](cicd_variables.md#build-and-deployment-variables) CI/CD variable. Follow [this issue](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/issues/31) for more information.
+Some values cannot be overridden with the options above, but [this issue](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/issues/31) proposes to change this behavior.
+To override settings like `replicaCount`, use the `REPLICAS` [build and deployment](cicd_variables.md#build-and-deployment-variables) CI/CD variable.
-NOTE:
-For GitLab 12.5 and earlier, use the `HELM_UPGRADE_EXTRA_ARGS` variable
-to override the default chart values by setting `HELM_UPGRADE_EXTRA_ARGS` to `--values <my-values.yaml>`.
+### Customize `helm upgrade`
-## Customize the `helm upgrade` command
+The `helm upgrade` command is used by the [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image).
+To customize this command, pass it options with the `HELM_UPGRADE_EXTRA_ARGS` CI/CD variable.
-You can customize the `helm upgrade` command used in the [auto-deploy-image](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image)
-by passing options to the command with the `HELM_UPGRADE_EXTRA_ARGS` CI/CD variable.
-For example, set the value of `HELM_UPGRADE_EXTRA_ARGS` to `--no-hooks` to disable
-pre-upgrade and post-upgrade hooks when the command is executed.
+For example, to disable pre- and post-upgrade hooks when `helm upgrade` runs:
-See [the official documentation](https://helm.sh/docs/helm/helm_upgrade/) for the full
-list of options.
+```yaml
+variables:
+ HELM_UPGRADE_EXTRA_ARGS: --no-hooks
+```
-## Custom Helm chart per environment
+For a full list of options, see [the official `helm upgrade` documentation](https://helm.sh/docs/helm/helm_upgrade/).
-You can specify the use of a custom Helm chart per environment by scoping the CI/CD variable
-to the desired environment. See [Limit environment scope of CI/CD variables](../../ci/variables/index.md#limit-the-environment-scope-of-a-cicd-variable).
+### Limit a Helm chart to one environment
-## Customizing `.gitlab-ci.yml`
+To limit a custom chart to one environment, add the environment scope to your CI/CD variables.
+For more information, see [Limit the environment scope of CI/CD variables](../../ci/variables/index.md#limit-the-environment-scope-of-a-cicd-variable).
-Auto DevOps is completely customizable because the
-[Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
-is just an implementation of a [`.gitlab-ci.yml`](../../ci/yaml/index.md) file,
-and uses only features available to any implementation of `.gitlab-ci.yml`.
+## Customize `.gitlab-ci.yml`
-To modify the CI/CD pipeline used by Auto DevOps,
-[`include` the template](../../ci/yaml/index.md#includetemplate), and customize
-it as needed by adding a `.gitlab-ci.yml` file to the root of your repository
-containing the following:
+Auto DevOps is highly customizable because the [Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
+is an implementation of a [`.gitlab-ci.yml`](../../ci/yaml/index.md) file.
+The template uses only features available to any implementation of `.gitlab-ci.yml`.
-```yaml
-include:
- - template: Auto-DevOps.gitlab-ci.yml
-```
+To add custom behaviors to the CI/CD pipeline used by Auto DevOps:
+
+1. To the root of your repository, add a `.gitlab-ci.yml` file with the following contents:
+
+ ```yaml
+ include:
+ - template: Auto-DevOps.gitlab-ci.yml
+ ```
+
+1. Add your changes to the `.gitlab-ci.yml` file. Your changes are merged with the Auto DevOps template. For more information about
+how `include` merges your changes, see [the `include` documentation](../../ci/yaml/index.md#include).
-Add your changes, and your additions are merged with the
-[Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
-using the behavior described for [`include`](../../ci/yaml/index.md#include).
+To remove behaviors from the Auto DevOps pipeline:
-If you need to specifically remove a part of the file, you can also copy and paste the contents of the
-[Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
-into your project and edit it as needed.
+1. Copy the [Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml)
+into your project.
+1. Edit your copy of the template as needed.
## Use multiple Kubernetes clusters
@@ -249,13 +251,14 @@ However, this feature was [deprecated](https://gitlab.com/groups/gitlab-org/conf
along with certificate-based integration.
You should now use the `KUBE_NAMESPACE` environment variable and
-[limit the environments it is available for](../../ci/environments/index.md#scope-environments-with-specs).
+[limit its environment scope](../../ci/environments/index.md#scope-environments-with-specs).
-## Using components of Auto DevOps
+## Use individual components of Auto DevOps
-If you only require a subset of the features offered by Auto DevOps, you can include
-individual Auto DevOps jobs into your own `.gitlab-ci.yml`. Each component job relies
-on a stage that should be defined in the `.gitlab-ci.yml` that includes the template.
+If you only require a subset of the features offered by Auto DevOps,
+you can include individual Auto DevOps jobs in your own
+`.gitlab-ci.yml`. Be sure to also define the stage required by each
+job in your `.gitlab-ci.yml` file.
For example, to make use of [Auto Build](stages.md#auto-build), you can add the following to
your `.gitlab-ci.yml`:
@@ -268,18 +271,17 @@ include:
- template: Jobs/Build.gitlab-ci.yml
```
-See the [Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml) for information on available jobs.
+For a list of available jobs, see the [Auto DevOps template](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Auto-DevOps.gitlab-ci.yml).
WARNING:
-Auto DevOps templates using the [`only`](../../ci/yaml/index.md#only--except) or
+From [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213336),
+Auto DevOps templates that use the [`only`](../../ci/yaml/index.md#only--except) or
[`except`](../../ci/yaml/index.md#only--except) syntax have switched
-to the [`rules`](../../ci/yaml/index.md#rules) syntax, starting in
-[GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/213336).
-If your `.gitlab-ci.yml` extends these Auto DevOps templates and override the `only` or
+to the [`rules`](../../ci/yaml/index.md#rules) syntax.
+If your `.gitlab-ci.yml` extends these Auto DevOps templates and overrides the `only` or
`except` keywords, you must migrate your templates to use the
-[`rules`](../../ci/yaml/index.md#rules) syntax after the
-base template is migrated to use the `rules` syntax.
-For users who cannot migrate just yet, you can alternatively pin your templates to
+[`rules`](../../ci/yaml/index.md#rules) syntax.
+If you cannot migrate just yet, you can alternatively pin your templates to
the [GitLab 12.10 based templates](https://gitlab.com/gitlab-org/auto-devops-v12-10).
## Use images hosted in a local Docker registry
@@ -287,7 +289,7 @@ the [GitLab 12.10 based templates](https://gitlab.com/gitlab-org/auto-devops-v12
You can configure many Auto DevOps jobs to run in an [offline environment](../../user/application_security/offline_deployments/index.md):
1. Copy the required Auto DevOps Docker images from Docker Hub and `registry.gitlab.com` to their local GitLab container registry.
-1. After the images are hosted and available in a local registry, edit `.gitlab-ci.yml` to point to the locally-hosted images. For example:
+1. After the images are hosted and available in a local registry, edit `.gitlab-ci.yml` to point to the locally hosted images. For example:
```yaml
include:
@@ -316,12 +318,6 @@ postgres://user:password@postgres-host:postgres-port/postgres-database
### Upgrading PostgreSQL
-WARNING:
-The CI/CD variable `AUTO_DEVOPS_POSTGRES_CHANNEL` that controls default provisioned
-PostgreSQL was changed to `2` in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/210499).
-To keep using the old PostgreSQL, set the `AUTO_DEVOPS_POSTGRES_CHANNEL` variable to
-`1`.
-
The version of the chart used to provision PostgreSQL:
- Is 8.2.1 in GitLab 13.0 and later, but can be set back to 0.7.1 if needed.
@@ -331,6 +327,11 @@ The version of the chart used to provision PostgreSQL:
GitLab encourages users to [migrate their database](upgrading_postgresql.md)
to the newer PostgreSQL.
+The CI/CD variable `AUTO_DEVOPS_POSTGRES_CHANNEL` that controls default provisioned
+PostgreSQL was changed to `2` in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/issues/210499).
+To use the old PostgreSQL, set the `AUTO_DEVOPS_POSTGRES_CHANNEL` variable to
+`1`.
+
### Customize values for PostgreSQL Helm Chart
> [Introduced](https://gitlab.com/gitlab-org/cluster-integration/auto-deploy-image/-/issues/113) in auto-deploy-image v2, in GitLab 13.8.
@@ -344,32 +345,29 @@ To set custom values, do one of the following:
and name.
- Set the `POSTGRES_HELM_UPGRADE_EXTRA_ARGS` [environment variable](cicd_variables.md#database-variables).
-### Using external PostgreSQL database providers
+### Use external PostgreSQL database providers
-While Auto DevOps provides out-of-the-box support for a PostgreSQL container for
-production environments, for some use cases, it may not be sufficiently secure or
-resilient, and you may want to use an external managed provider (such as
+Auto DevOps provides out-of-the-box support for a PostgreSQL container for
+production environments. However, you might want to use an external managed provider (such as
AWS Relational Database Service) for PostgreSQL.
-You must define environment-scoped CI/CD variables for `POSTGRES_ENABLED` and
-`DATABASE_URL` in your project's CI/CD settings:
+To use an external managed provider:
-1. Disable the built-in PostgreSQL installation for the required environments using
+1. Disable the built-in PostgreSQL installation for the required environments with
environment-scoped [CI/CD variables](../../ci/environments/index.md#scope-environments-with-specs).
- For this use case, it's likely that only `production` must be added to this
- list. The built-in PostgreSQL setup for Review Apps and staging is sufficient.
+ Because the built-in PostgreSQL setup for Review Apps and staging is sufficient, you might only need to
+ disable the installation for `production`.
![Auto Metrics](img/disable_postgres.png)
-1. Define the `DATABASE_URL` variable as an environment-scoped variable that is
+1. Define the `DATABASE_URL` variable as an environment-scoped variable
available to your application. This should be a URL in the following format:
```yaml
postgres://user:password@postgres-host:postgres-port/postgres-database
```
-You must ensure that your Kubernetes cluster has network access to wherever
-PostgreSQL is hosted.
+1. Ensure your Kubernetes cluster has network access to where PostgreSQL is hosted.
## Auto DevOps banner
diff --git a/doc/topics/autodevops/stages.md b/doc/topics/autodevops/stages.md
index 0ca9c6fa3de..aba0b2d7fae 100644
--- a/doc/topics/autodevops/stages.md
+++ b/doc/topics/autodevops/stages.md
@@ -451,7 +451,7 @@ To use Auto Deploy on a Kubernetes 1.16+ cluster:
1. If you are deploying your application for the first time in GitLab 13.0 or
later, no configuration should be required.
-1. In GitLab 12.10 and earlier, set the following in the [`.gitlab/auto-deploy-values.yaml` file](customize.md#customize-values-for-helm-chart):
+1. In GitLab 12.10 and earlier, set the following in the [`.gitlab/auto-deploy-values.yaml` file](customize.md#customize-helm-chart-values):
```yaml
deploymentApiVersion: apps/v1
@@ -535,7 +535,7 @@ you must:
After configuring your worker to respond to health checks, run a Sidekiq
worker for your Rails application. You can enable workers by setting the
-following in the [`.gitlab/auto-deploy-values.yaml` file](customize.md#customize-values-for-helm-chart):
+following in the [`.gitlab/auto-deploy-values.yaml` file](customize.md#customize-helm-chart-values):
```yaml
workers:
diff --git a/doc/topics/autodevops/troubleshooting.md b/doc/topics/autodevops/troubleshooting.md
index ef420323b32..dd715e95512 100644
--- a/doc/topics/autodevops/troubleshooting.md
+++ b/doc/topics/autodevops/troubleshooting.md
@@ -230,7 +230,7 @@ LAST SEEN TYPE REASON OBJECT
```
To change the port used for the liveness checks, pass
-[custom values to the Helm chart](customize.md#customize-values-for-helm-chart)
+[custom values to the Helm chart](customize.md#customize-helm-chart-values)
used by Auto DevOps:
1. Create a directory and file at the root of your repository named `.gitlab/auto-deploy-values.yaml`.
diff --git a/doc/tutorials/move_personal_project_to_a_group.md b/doc/tutorials/move_personal_project_to_a_group.md
index 1431dc48d99..e3ab1e8fbd8 100644
--- a/doc/tutorials/move_personal_project_to_a_group.md
+++ b/doc/tutorials/move_personal_project_to_a_group.md
@@ -53,7 +53,7 @@ If you don't have a group, create one:
Before you move your project to a group:
- You must have the Owner role for the project.
-- Remove any [container images](../user/packages/container_registry/index.md#known-issues)
+- Remove any [container images](../user/packages/container_registry/index.md#move-or-rename-container-registry-repositories)
- Remove any npm packages. If you transfer a project to a different root namespace, the project must not contain any npm packages. When you update the path of a user or group, or transfer a subgroup or project, you must remove any npm packages first. You cannot update the root namespace of a project with npm packages. Make sure you update your .npmrc files to follow the naming convention and run npm publish if necessary.
Now you're ready to move your project:
diff --git a/doc/user/admin_area/settings/account_and_limit_settings.md b/doc/user/admin_area/settings/account_and_limit_settings.md
index 7c1616394a2..7f678344955 100644
--- a/doc/user/admin_area/settings/account_and_limit_settings.md
+++ b/doc/user/admin_area/settings/account_and_limit_settings.md
@@ -102,7 +102,8 @@ to find tokens more quickly, or for use with automation tools.
The default prefix is `glpat-` but administrators can change it.
-[Project access tokens](../../project/settings/project_access_tokens.md) also inherit this prefix.
+[Project access tokens](../../project/settings/project_access_tokens.md) and
+[group access tokens](../../group/settings/group_access_tokens.md) also inherit this prefix.
### Set a prefix
diff --git a/doc/user/analytics/img/devops_metrics_comparison_v15_8.png b/doc/user/analytics/img/devops_metrics_comparison_v15_8.png
new file mode 100644
index 00000000000..3a52d9e0781
--- /dev/null
+++ b/doc/user/analytics/img/devops_metrics_comparison_v15_8.png
Binary files differ
diff --git a/doc/user/analytics/value_streams_dashboard.md b/doc/user/analytics/value_streams_dashboard.md
new file mode 100644
index 00000000000..6efef3830d4
--- /dev/null
+++ b/doc/user/analytics/value_streams_dashboard.md
@@ -0,0 +1,62 @@
+---
+stage: Plan
+group: Optimize
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Value Streams Dashboard **(PREMIUM)**
+
+> Introduced in GitLab 15.8 as a [Closed Beta](https://about.gitlab.com/handbook/product/gitlab-the-product/#closed-beta) feature.
+
+You can leave feedback on dashboard bugs or functionality in [issue 381787](https://gitlab.com/gitlab-org/gitlab/-/issues/381787).
+
+This feature is not ready for production use.
+
+The Value Streams Dashboard is a customizable dashboard to enable decision-makers to identify trends, patterns, and opportunities for digital transformation improvements.
+This page is a work in progress, and we're updating the information as we add more features.
+For more information, see the [Value Stream Management category direction page](https://about.gitlab.com/direction/plan/value_stream_management/).
+
+## Initial use case
+
+Our initial use case is focused on providing the ability to compare software delivery metrics.
+This comparison can help decision-makers understand whether projects and groups are improving.
+
+The beta version of the Value Streams Dashboard includes the following metrics:
+
+- [DORA metrics](dora_metrics.md)
+- [Value Stream Analytics (VSA) - flow metrics](value_stream_analytics.md)
+
+The Value Streams Dashboard allows you to:
+
+- Aggregate data records from different APIs.
+- Track software performance (DORA) and flow of value (VSA) across the organization.
+
+## DevSecOps metrics comparison
+
+The DevOps metrics comparison displays DORA4 and flow metrics for a group or project in the
+month-to-date, last month, the month before, and the past 180 days.
+
+This visualization helps you get a high-level custom view over multiple DevOps metrics and
+understand whether they're improving month over month. You can compare the performance between
+groups, projects, and teams at a glance. This visualization helps you identify the teams and projects
+that are the largest value contributors, overperforming, or underperforming.
+
+![DevOps metrics comparison](img/devops_metrics_comparison_v15_8.png)
+
+You can also drill down the metrics for further analysis.
+When you hover over a metric, a tooltip displays an explanation of the metric and a link to the related documentation page.
+
+## Customize the dashboard widgets
+
+You can customize the Value Streams Dashboard and configure what subgroups and projects to include in the page.
+
+A view can display maximum four subgroups or projects.
+
+To display multiple subgroups and projects, specify their path as a URL parameter.
+
+For example, the parameter `query=gitlab-org/gitlab-foss,gitlab-org/gitlab,gitlab-org/gitlab-design,gitlab-org/gitlab-docs` displays three separate widgets, one each for the:
+
+- `gitlab-org` group
+- `gitlab-ui` project
+- `gitlab-org/plan-stage` subgroup
+- Select which groups, subgroups, or projects to display on the page. Each of them has its own widget.
diff --git a/doc/user/application_security/container_scanning/index.md b/doc/user/application_security/container_scanning/index.md
index e198f967eea..cc8f9d34f5a 100644
--- a/doc/user/application_security/container_scanning/index.md
+++ b/doc/user/application_security/container_scanning/index.md
@@ -81,7 +81,7 @@ To enable container scanning in your pipeline, you need the following:
- Docker `18.09.03` or higher installed on the same computer as the runner. If you're using the
shared runners on GitLab.com, then this is already the case.
- An image matching the [supported distributions](#supported-distributions).
-- [Build and push](../../packages/container_registry/index.md#build-and-push-by-using-gitlab-cicd)
+- [Build and push](../../packages/container_registry/build_and_push_images.md#use-gitlab-cicd)
the Docker image to your project's container registry.
- If you're using a third-party container registry, you might need to provide authentication
credentials through the `CS_REGISTRY_USER` and `CS_REGISTRY_PASSWORD` [configuration variables](#available-cicd-variables).
diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md
index 6629c798cfa..e8b1267fda6 100644
--- a/doc/user/application_security/index.md
+++ b/doc/user/application_security/index.md
@@ -126,7 +126,7 @@ To enable all GitLab Security scanning tools, with default settings, enable
- [Auto License Compliance](../../topics/autodevops/stages.md#auto-license-compliance)
- [Auto Container Scanning](../../topics/autodevops/stages.md#auto-container-scanning)
-While you cannot directly customize Auto DevOps, you can [include the Auto DevOps template in your project's `.gitlab-ci.yml` file](../../topics/autodevops/customize.md#customizing-gitlab-ciyml).
+While you cannot directly customize Auto DevOps, you can [include the Auto DevOps template in your project's `.gitlab-ci.yml` file](../../topics/autodevops/customize.md#customize-gitlab-ciyml).
## Security scanning without Auto DevOps
diff --git a/doc/user/application_security/offline_deployments/index.md b/doc/user/application_security/offline_deployments/index.md
index 05e56560f95..2082e2291e3 100644
--- a/doc/user/application_security/offline_deployments/index.md
+++ b/doc/user/application_security/offline_deployments/index.md
@@ -227,7 +227,7 @@ these steps:
The AutoDevOps templates leverage the `SECURE_ANALYZERS_PREFIX` variable to identify the location
of analyzer images. This variable is discussed above in [Using the secure bundle created](#using-the-secure-bundle-created).
Ensure that you set this variable to the correct value for where you loaded the analyzer images.
- You could consider doing this with a project CI/CD variable or by [modifying](../../../topics/autodevops/customize.md#customizing-gitlab-ciyml)
+ You could consider doing this with a project CI/CD variable or by [modifying](../../../topics/autodevops/customize.md#customize-gitlab-ciyml)
the `.gitlab-ci.yml` file directly.
Once these steps are complete, GitLab has local copies of the Secure analyzers and is set up to use
diff --git a/doc/user/packages/container_registry/authenticate_with_container_registry.md b/doc/user/packages/container_registry/authenticate_with_container_registry.md
new file mode 100644
index 00000000000..cdc7cbe947b
--- /dev/null
+++ b/doc/user/packages/container_registry/authenticate_with_container_registry.md
@@ -0,0 +1,60 @@
+---
+stage: Package
+group: Container Registry
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Authenticate with the Container Registry **(FREE)**
+
+To authenticate with the Container Registry, you can use a:
+
+- [Personal access token](../../profile/personal_access_tokens.md).
+- [Deploy token](../../project/deploy_tokens/index.md).
+- [Project access token](../../project/settings/project_access_tokens.md).
+- [Group access token](../../group/settings/group_access_tokens.md).
+
+All of these authentication methods require the minimum scope:
+
+- For read (pull) access, to be `read_registry`.
+- For write (push) access, to be`write_registry` and `read_registry`.
+
+To authenticate, run the `docker login` command. For example:
+
+ ```shell
+ docker login registry.example.com -u <username> -p <token>
+ ```
+
+## Use GitLab CI/CD to authenticate
+
+To use CI/CD to authenticate with the Container Registry, you can use:
+
+- The `CI_REGISTRY_USER` CI/CD variable.
+
+ This variable has read-write access to the Container Registry and is valid for
+ one job only. Its password is also automatically created and assigned to `CI_REGISTRY_PASSWORD`.
+
+ ```shell
+ docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+ ```
+
+- A [CI job token](../../../ci/jobs/ci_job_token.md).
+
+ ```shell
+ docker login -u $CI_REGISTRY_USER -p $CI_JOB_TOKEN $CI_REGISTRY
+ ```
+
+- A [deploy token](../../project/deploy_tokens/index.md#gitlab-deploy-token) with the minimum scope of:
+ - For read (pull) access, `read_registry`.
+ - For write (push) access, `write_registry`.
+
+ ```shell
+ docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
+ ```
+
+- A [personal access token](../../profile/personal_access_tokens.md) with the minimum scope of:
+ - For read (pull) access, `read_registry`.
+ - For write (push) access, `write_registry`.
+
+ ```shell
+ docker login -u <username> -p <access_token> $CI_REGISTRY
+ ```
diff --git a/doc/user/packages/container_registry/build_and_push_images.md b/doc/user/packages/container_registry/build_and_push_images.md
new file mode 100644
index 00000000000..bbb82300488
--- /dev/null
+++ b/doc/user/packages/container_registry/build_and_push_images.md
@@ -0,0 +1,214 @@
+---
+stage: Package
+group: Container Registry
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Build and push container images to the Container Registry **(FREE)**
+
+Before you can build and push container images, you must [authenticate](authenticate_with_container_registry.md) with the Container Registry.
+
+## Use Docker commands
+
+You can use Docker commands to build and push container images to your Container Registry:
+
+1. [Authenticate](authenticate_with_container_registry.md) with the Container Registry.
+1. Run the Docker command to build or push. For example:
+
+ - To build:
+
+ ```shell
+ docker build -t registry.example.com/group/project/image .
+ ```
+
+ - To push:
+
+ ```shell
+ docker push registry.example.com/group/project/image
+ ```
+
+## Configure your `.gitlab-ci.yml` file
+
+You can configure your `.gitlab-ci.yml` file to build and push container images to the Container Registry.
+
+- If multiple jobs require authentication, put the authentication command in the `before_script`.
+- Before building, use `docker build --pull` to fetch changes to base images. It takes slightly
+ longer, but it ensures your image is up-to-date.
+- Before each `docker run`, do an explicit `docker pull` to fetch
+ the image that was just built. This step is especially important if you are
+ using multiple runners that cache images locally.
+
+ If you use the Git SHA in your image tag, each job is unique and you
+ should never have a stale image. However, it's still possible to have a
+ stale image if you rebuild a given commit after a dependency has changed.
+- Don't build directly to the `latest` tag because multiple jobs may be
+ happening simultaneously.
+
+## Use GitLab CI/CD
+
+You can use [GitLab CI/CD](../../../ci/yaml/index.md) to build and push container images to the
+Container Registry. You can use CI/CD to test, build, and deploy your project from the container
+image you created.
+
+### Use a Docker-in-Docker container image from your Container Registry
+
+You can use your own container images for Docker-in-Docker.
+
+1. Set up [Docker-in-Docker](../../../ci/docker/using_docker_build.md#use-docker-in-docker).
+1. Update the `image` and `service` to point to your registry.
+1. Add a service [alias](../../../ci/services/index.md#available-settings-for-services).
+
+Your `.gitlab-ci.yml` should look similar to this:
+
+```yaml
+build:
+ image: $CI_REGISTRY/group/project/docker:20.10.16
+ services:
+ - name: $CI_REGISTRY/group/project/docker:20.10.16-dind
+ alias: docker
+ stage: build
+ script:
+ - docker build -t my-docker-image .
+ - docker run my-docker-image /script/to/run/tests
+```
+
+If you forget to set the service alias, the container image can't find the `dind` service,
+and an error like the following is shown:
+
+```plaintext
+error during connect: Get http://docker:2376/v1.39/info: dial tcp: lookup docker on 192.168.0.1:53: no such host
+```
+
+### Use a Docker-in-Docker container image with Dependency Proxy
+
+You can use your own container images with Dependency Proxy.
+
+1. Set up [Docker-in-Docker](../../../ci/docker/using_docker_build.md#use-docker-in-docker).
+1. Update the `image` and `service` to point to your registry.
+1. Add a service [alias](../../../ci/services/index.md#available-settings-for-services).
+
+Your `.gitlab-ci.yml` should look similar to this:
+
+```yaml
+build:
+ image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:20.10.16
+ services:
+ - name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:18.09.7-dind
+ alias: docker
+ stage: build
+ script:
+ - docker build -t my-docker-image .
+ - docker run my-docker-image /script/to/run/tests
+```
+
+If you forget to set the service alias, the container image can't find the `dind` service,
+and an error like the following is shown:
+
+```plaintext
+error during connect: Get http://docker:2376/v1.39/info: dial tcp: lookup docker on 192.168.0.1:53: no such host
+```
+
+## Container Registry examples with GitLab CI/CD
+
+If you're using Docker-in-Docker on your runners, your `.gitlab-ci.yml` file should look similar to this:
+
+```yaml
+build:
+ image: docker:20.10.16
+ stage: build
+ services:
+ - docker:20.10.16-dind
+ script:
+ - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+ - docker build -t $CI_REGISTRY/group/project/image:latest .
+ - docker push $CI_REGISTRY/group/project/image:latest
+```
+
+You can use [CI/CD variables](../../../ci/variables/index.md) in your `.gitlab-ci.yml` file. For example:
+
+```yaml
+build:
+ image: docker:20.10.16
+ stage: build
+ services:
+ - docker:20.10.16-dind
+ variables:
+ IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+ script:
+ - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+ - docker build -t $IMAGE_TAG .
+ - docker push $IMAGE_TAG
+```
+
+In this example, `$CI_REGISTRY_IMAGE` resolves to the address of the registry tied
+to this project. `$CI_COMMIT_REF_NAME` resolves to the branch or tag name, which
+can contain forward slashes. Image tags can't contain forward slashes. Use
+`$CI_COMMIT_REF_SLUG` as the image tag. You can declare the variable, `$IMAGE_TAG`,
+combining `$CI_REGISTRY_IMAGE` and `$CI_REGISTRY_IMAGE` to save some typing in the
+`script` section.
+
+This example splits the tasks into 4 pipeline stages, including two tests that run in parallel. The `build` is stored in the container
+registry and used by subsequent stages, downloading the container image when needed. Changes to `main` also get tagged as
+`latest` and deployed using an application-specific deploy script:
+
+```yaml
+image: docker:20.10.16
+services:
+ - docker:20.10.16-dind
+
+stages:
+ - build
+ - test
+ - release
+ - deploy
+
+variables:
+ # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
+ DOCKER_HOST: tcp://docker:2376
+ DOCKER_TLS_CERTDIR: "/certs"
+ CONTAINER_TEST_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+ CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest
+
+before_script:
+ - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+
+build:
+ stage: build
+ script:
+ - docker build --pull -t $CONTAINER_TEST_IMAGE .
+ - docker push $CONTAINER_TEST_IMAGE
+
+test1:
+ stage: test
+ script:
+ - docker pull $CONTAINER_TEST_IMAGE
+ - docker run $CONTAINER_TEST_IMAGE /script/to/run/tests
+
+test2:
+ stage: test
+ script:
+ - docker pull $CONTAINER_TEST_IMAGE
+ - docker run $CONTAINER_TEST_IMAGE /script/to/run/another/test
+
+release-image:
+ stage: release
+ script:
+ - docker pull $CONTAINER_TEST_IMAGE
+ - docker tag $CONTAINER_TEST_IMAGE $CONTAINER_RELEASE_IMAGE
+ - docker push $CONTAINER_RELEASE_IMAGE
+ only:
+ - main
+
+deploy:
+ stage: deploy
+ script:
+ - ./deploy.sh
+ only:
+ - main
+ environment: production
+```
+
+NOTE:
+This example explicitly calls `docker pull`. If you prefer to implicitly pull the container image using `image:`,
+and use either the [Docker](https://docs.gitlab.com/runner/executors/docker.html) or [Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html) executor,
+make sure that [`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html#how-pull-policies-work) is set to `always`.
diff --git a/doc/user/packages/container_registry/delete_container_registry_images.md b/doc/user/packages/container_registry/delete_container_registry_images.md
new file mode 100644
index 00000000000..9adb9313f09
--- /dev/null
+++ b/doc/user/packages/container_registry/delete_container_registry_images.md
@@ -0,0 +1,117 @@
+---
+stage: Package
+group: Container Registry
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Delete container images from the Container Registry **(FREE)**
+
+You can delete container images from your Container Registry.
+
+WARNING:
+Deleting container images is a destructive action and can't be undone. To restore
+a deleted container image, you must rebuild and re-upload it.
+
+Deleting a container image on self-managed instances doesn't free up storage space, it only marks the image
+as eligible for deletion. To actually delete unreferenced container images and recover storage space, administrators
+must run [garbage collection](../../../administration/packages/container_registry.md#container-registry-garbage-collection).
+
+On GitLab.com, the latest version of the Container Registry includes an automatic online garbage
+collector. For more information, see [this blog post](https://about.gitlab.com/blog/2021/10/25/gitlab-com-container-registry-update/).
+The automatic online garbage collector is an instance-wide feature, rolling out gradually to a subset
+of the user base. Some new container image repositories created from GitLab 14.5 onward are served by this
+new version of the Container Registry. In this new version of the Container Registry, layers that aren't
+referenced by any image manifest, and image manifests that have no tags and aren't referenced by another
+manifest (such as multi-architecture images), are automatically scheduled for deletion after 24 hours if
+left unreferenced.
+
+## Use the GitLab UI
+
+To delete container images using the GitLab UI:
+
+1. On the top bar, select **Main menu**, and:
+ - For a project, select **Projects** and find your project.
+ - For a group, select **Groups** and find your group.
+1. On the left sidebar, select **Packages and registries > Container Registry**.
+1. From the **Container Registry** page, you can select what you want to delete,
+ by either:
+
+ - Deleting the entire repository, and all the tags it contains, by selecting
+ the red **{remove}** **Trash** icon.
+ - Navigating to the repository, and deleting tags individually or in bulk
+ by selecting the red **{remove}** **Trash** icon next to the tag you want
+ to delete.
+
+1. In the dialog box, select **Remove tag**.
+
+## Use the GitLab API
+
+You can use the API to automate the process of deleting container images. For more
+information, see the following endpoints:
+
+- [Delete a Registry repository](../../../api/container_registry.md#delete-registry-repository)
+- [Delete an individual Registry repository tag](../../../api/container_registry.md#delete-a-registry-repository-tag)
+- [Delete Registry repository tags in bulk](../../../api/container_registry.md#delete-registry-repository-tags-in-bulk)
+
+## Use GitLab CI/CD
+
+NOTE:
+GitLab CI/CD doesn't provide a built-in way to remove your container images. This example uses a
+third-party tool called [reg](https://github.com/genuinetools/reg) that talks to the GitLab Registry API.
+For assistance with this third-party tool, see [the issue queue for reg](https://github.com/genuinetools/reg/issues).
+
+The following example defines two stages: `build`, and `clean`. The `build_image` job builds a container
+image for the branch, and the `delete_image` job deletes it. The `reg` executable is downloaded and used to
+remove the container image matching the `$CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG`
+[predefined CI/CD variable](../../../ci/variables/predefined_variables.md).
+
+To use this example, change the `IMAGE_TAG` variable to match your needs.
+
+```yaml
+stages:
+ - build
+ - clean
+
+build_image:
+ image: docker:20.10.16
+ stage: build
+ services:
+ - docker:20.10.16-dind
+ variables:
+ IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
+ script:
+ - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
+ - docker build -t $IMAGE_TAG .
+ - docker push $IMAGE_TAG
+ only:
+ - branches
+ except:
+ - main
+
+delete_image:
+ before_script:
+ - curl --fail --show-error --location "https://github.com/genuinetools/reg/releases/download/v$REG_VERSION/reg-linux-amd64" --output ./reg
+ - echo "$REG_SHA256 ./reg" | sha256sum -c -
+ - chmod a+x ./reg
+ image: curlimages/curl:7.86.0
+ script:
+ - ./reg rm -d --auth-url $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $IMAGE_TAG
+ stage: clean
+ variables:
+ IMAGE_TAG: $CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG
+ REG_SHA256: ade837fc5224acd8c34732bf54a94f579b47851cc6a7fd5899a98386b782e228
+ REG_VERSION: 0.16.1
+ only:
+ - branches
+ except:
+ - main
+```
+
+NOTE:
+You can download the latest `reg` release from [the releases page](https://github.com/genuinetools/reg/releases), then update
+the code example by changing the `REG_SHA256` and `REG_VERSION` variables defined in the `delete_image` job.
+
+## Use a cleanup policy
+
+You can create a per-project [cleanup policy](reduce_container_registry_storage.md#cleanup-policy) to ensure older tags and
+images are regularly removed from the Container Registry.
diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md
index 4b4d6190dc2..c3790c252cc 100644
--- a/doc/user/packages/container_registry/index.md
+++ b/doc/user/packages/container_registry/index.md
@@ -8,84 +8,86 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> Searching by image repository name was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31322) in GitLab 13.0.
-NOTE:
-If you pull container images from Docker Hub, you can use the [GitLab Dependency Proxy](../dependency_proxy/index.md#use-the-dependency-proxy-for-docker-images)
-to avoid rate limits and speed up your pipelines.
-
-With the Docker Container Registry integrated into GitLab, every GitLab project can
-have its own space to store its Docker images.
+You can use the integrated Container Registry to store container images for each GitLab project
-You can read more about Docker Registry at <https://docs.docker.com/registry/introduction/>.
+To enable the Container Registry for your GitLab instance, see the [administrator documentation](../../../administration/packages/container_registry.md).
-This document is the user guide. To learn how to enable the Container
-Registry for your GitLab instance, visit the
-[administrator documentation](../../../administration/packages/container_registry.md).
+NOTE:
+If you pull Docker container images from Docker Hub, you can use the
+[GitLab Dependency Proxy](../dependency_proxy/index.md#use-the-dependency-proxy-for-docker-images) to avoid
+rate limits and speed up your pipelines. For more information about the Docker Registry, see <https://docs.docker.com/registry/introduction/>.
## View the Container Registry
You can view the Container Registry for a project or group.
-1. Go to your project or group.
-1. Go to **Packages and registries > Container Registry**.
+1. On the top bar, select **Main menu**, and:
+ - For a project, select **Projects** and find your project.
+ - For a group, select **Groups** and find your group.
+1. On the left sidebar, select **Packages and registries > Container Registry**.
-You can search, sort, filter, and [delete](#delete-images-using-the-gitlab-ui)
-containers on this page. You can share a filtered view by copying the URL from your browser.
+You can search, sort, filter, and [delete](delete_container_registry_images.md#use-the-gitlab-ui)
+ 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 a private project's Container Registry.
-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).
+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).
-If a project is public, so is the Container Registry.
+If a project is public, the Container Registry is also public.
-### View the tags of a specific image
+### View the tags of a specific container image in the Container Registry
You can use the Container Registry **Tag Details** page to view a list of tags associated with a given container image:
-1. Go to your project or group.
-1. Go to **Packages and registries > Container Registry**.
-1. Select the container image you are interested in.
+1. On the top bar, select **Main menu**, and:
+ - For a project, select **Projects** and find your project.
+ - For a group, select **Groups** and find your group.
+1. On the left sidebar, select **Packages and registries > Container Registry**.
+1. Select your container image.
You can view details about each tag, such as when it was published, how much storage it consumes,
and the manifest and configuration digests.
-You can search, sort (by tag name), filter, and [delete](#delete-images-using-the-gitlab-ui)
+You can search, sort (by tag name), filter, and [delete](delete_container_registry_images.md#use-the-gitlab-ui)
tags on this page. You can share a filtered view by copying the URL from your browser.
-## Use images from the Container Registry
+## Use container images from the Container Registry
-To download and run a container image hosted in the GitLab Container Registry:
+To download and run a container image hosted in the Container Registry:
-1. Copy the link to your container image:
- - Go to your project or group's **Packages and registries > Container Registry**
- and find the image you want.
- - Next to the image name, select **Copy**.
+1. On the top bar, select **Main menu**, and:
+ - For a project, select **Projects** and find your project.
+ - For a group, select **Groups** and find your group.
+1. On the left sidebar, select **Packages and registries > Container Registry**.
+1. Find the container image you want to work with and select **Copy**.
![Container Registry image URL](img/container_registry_hover_path_13_4.png)
-1. Use `docker run` with the image link:
+1. Use `docker run` with the copied link:
```shell
docker run [options] registry.example.com/group/project/image [arguments]
```
-[Authentication](#authenticate-with-the-container-registry) is needed to download images from a private repository.
+NOTE:
+You must [authenticate with the container registry](authenticate_with_container_registry.md) to download
+container images from a private repository.
-For more information on running Docker containers, visit the
-[Docker documentation](https://docs.docker.com/get-started/).
+For more information on running container images, visit the [Docker documentation](https://docs.docker.com/get-started/).
-## Image naming convention
+## Naming convention for your container images
-Images follow this naming convention:
+Your container images must follow this naming convention:
```plaintext
<registry URL>/<namespace>/<project>/<image>
```
-If your project is `gitlab.example.com/mynamespace/myproject`, for example,
-then your image must be named `gitlab.example.com/mynamespace/myproject` at a minimum.
+For example, if your project is `gitlab.example.com/mynamespace/myproject`,
+then your container image must be named `gitlab.example.com/mynamespace/myproject`.
-You can append additional names to the end of an image name, up to two levels deep.
+You can append additional names to the end of a container image name, up to two levels deep.
-For example, these are all valid image names for images in the project named `myproject`:
+For example, these are all valid names for container images in the project named `myproject`:
```plaintext
registry.example.com/mynamespace/myproject:some-tag
@@ -99,399 +101,12 @@ registry.example.com/mynamespace/myproject/image:latest
registry.example.com/mynamespace/myproject/my/image:rc1
```
-## Authenticate with the Container Registry
-
-To authenticate with the Container Registry, you can use a:
-
-- [Personal access token](../../profile/personal_access_tokens.md).
-- [Deploy token](../../project/deploy_tokens/index.md).
-- [Project access token](../../project/settings/project_access_tokens.md).
-- [Group access token](../../group/settings/group_access_tokens.md).
-
-All of these require the minimum scope to be:
-
-- For read (pull) access, `read_registry`.
-- For write (push) access, `write_registry` & `read_registry`.
-
-To authenticate, run the `docker` command. For example:
-
- ```shell
- docker login registry.example.com -u <username> -p <token>
- ```
-
-## Build and push images by using Docker commands
-
-Before you can build and push images, you must [authenticate](#authenticate-with-the-container-registry) with the Container Registry.
-
-To build and push to the Container Registry:
-
-1. Authenticate with the Container Registry.
-
-1. Run the command to build or push. For example, to build:
-
- ```shell
- docker build -t registry.example.com/group/project/image .
- ```
-
- Or to push:
-
- ```shell
- docker push registry.example.com/group/project/image
- ```
-
-To view these commands, go to your project's **Packages and registries > Container Registry**.
-
-## Build and push by using GitLab CI/CD
-
-Use [GitLab CI/CD](../../../ci/yaml/index.md) to build and push images to the
-Container Registry. Use it to test, build, and deploy your project from the Docker
-image you created.
-
-### Authenticate by using GitLab CI/CD
-
-Before you can build and push images by using GitLab CI/CD, you must authenticate with the Container Registry.
-
-To use CI/CD to authenticate, you can use:
-
-- The `CI_REGISTRY_USER` CI/CD variable.
-
- This variable has read-write access to the Container Registry and is valid for
- one job only. Its password is also automatically created and assigned to `CI_REGISTRY_PASSWORD`.
-
- ```shell
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- ```
-
-- A [CI job token](../../../ci/jobs/ci_job_token.md).
-
- ```shell
- docker login -u $CI_REGISTRY_USER -p $CI_JOB_TOKEN $CI_REGISTRY
- ```
-
-- A [deploy token](../../project/deploy_tokens/index.md#gitlab-deploy-token) with the minimum scope of:
- - For read (pull) access, `read_registry`.
- - For write (push) access, `write_registry`.
-
- ```shell
- docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY
- ```
-
-- A [personal access token](../../profile/personal_access_tokens.md) with the minimum scope of:
- - For read (pull) access, `read_registry`.
- - For write (push) access, `write_registry`.
-
- ```shell
- docker login -u <username> -p <access_token> $CI_REGISTRY
- ```
-
-### Configure your `.gitlab-ci.yml` file
-
-You can configure your `.gitlab-ci.yml` file to build and push images to the Container Registry.
-
-- If multiple jobs require authentication, put the authentication command in the `before_script`.
-- Before building, use `docker build --pull` to fetch changes to base images. It takes slightly
- longer, but it ensures your image is up-to-date.
-- Before each `docker run`, do an explicit `docker pull` to fetch
- the image that was just built. This step is especially important if you are
- using multiple runners that cache images locally.
-
- If you use the Git SHA in your image tag, each job is unique and you
- should never have a stale image. However, it's still possible to have a
- stale image if you rebuild a given commit after a dependency has changed.
-- Don't build directly to the `latest` tag because multiple jobs may be
- happening simultaneously.
-
-### Container Registry examples with GitLab CI/CD
-
-If you're using Docker-in-Docker on your runners, this is how your `.gitlab-ci.yml`
-should look:
-
-```yaml
-build:
- image: docker:20.10.16
- stage: build
- services:
- - docker:20.10.16-dind
- script:
- - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- - docker build -t $CI_REGISTRY/group/project/image:latest .
- - docker push $CI_REGISTRY/group/project/image:latest
-```
-
-You can also make use of [other CI/CD variables](../../../ci/variables/index.md) to avoid hard-coding:
-
-```yaml
-build:
- image: docker:20.10.16
- stage: build
- services:
- - docker:20.10.16-dind
- variables:
- IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
- script:
- - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- - docker build -t $IMAGE_TAG .
- - docker push $IMAGE_TAG
-```
-
-In this example, `$CI_REGISTRY_IMAGE` resolves to the address of the registry tied
-to this project. `$CI_COMMIT_REF_NAME` resolves to the branch or tag name, which
-can contain forward slashes. Image tags can't contain forward slashes. Use
-`$CI_COMMIT_REF_SLUG` as the image tag. You can declare the variable, `$IMAGE_TAG`,
-combining `$CI_REGISTRY_IMAGE` and `$CI_REGISTRY_IMAGE` to save some typing in the
-`script` section.
-
-Here's a more elaborate example that splits up the tasks into 4 pipeline stages,
-including two tests that run in parallel. The `build` is stored in the container
-registry and used by subsequent stages, downloading the image
-when needed. Changes to `main` also get tagged as `latest` and deployed using
-an application-specific deploy script:
-
-```yaml
-image: docker:20.10.16
-services:
- - docker:20.10.16-dind
-
-stages:
- - build
- - test
- - release
- - deploy
-
-variables:
- # Use TLS https://docs.gitlab.com/ee/ci/docker/using_docker_build.html#tls-enabled
- DOCKER_HOST: tcp://docker:2376
- DOCKER_TLS_CERTDIR: "/certs"
- CONTAINER_TEST_IMAGE: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
- CONTAINER_RELEASE_IMAGE: $CI_REGISTRY_IMAGE:latest
-
-before_script:
- - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
-
-build:
- stage: build
- script:
- - docker build --pull -t $CONTAINER_TEST_IMAGE .
- - docker push $CONTAINER_TEST_IMAGE
-
-test1:
- stage: test
- script:
- - docker pull $CONTAINER_TEST_IMAGE
- - docker run $CONTAINER_TEST_IMAGE /script/to/run/tests
-
-test2:
- stage: test
- script:
- - docker pull $CONTAINER_TEST_IMAGE
- - docker run $CONTAINER_TEST_IMAGE /script/to/run/another/test
-
-release-image:
- stage: release
- script:
- - docker pull $CONTAINER_TEST_IMAGE
- - docker tag $CONTAINER_TEST_IMAGE $CONTAINER_RELEASE_IMAGE
- - docker push $CONTAINER_RELEASE_IMAGE
- only:
- - main
-
-deploy:
- stage: deploy
- script:
- - ./deploy.sh
- only:
- - main
- environment: production
-```
-
-NOTE:
-This example explicitly calls `docker pull`. If you prefer to implicitly pull the
-built image using `image:`, and use either the [Docker](https://docs.gitlab.com/runner/executors/docker.html)
-or [Kubernetes](https://docs.gitlab.com/runner/executors/kubernetes.html) executor,
-make sure that [`pull_policy`](https://docs.gitlab.com/runner/executors/docker.html#how-pull-policies-work)
-is set to `always`.
-
-### Using a Docker-in-Docker image from your Container Registry
-
-To use your own Docker images for Docker-in-Docker, follow these steps
-in addition to the steps in the
-[Docker-in-Docker](../../../ci/docker/using_docker_build.md#use-docker-in-docker) section:
-
-1. Update the `image` and `service` to point to your registry.
-1. Add a service [alias](../../../ci/services/index.md#available-settings-for-services).
-
-Below is an example of what your `.gitlab-ci.yml` should look like:
-
-```yaml
-build:
- image: $CI_REGISTRY/group/project/docker:20.10.16
- services:
- - name: $CI_REGISTRY/group/project/docker:20.10.16-dind
- alias: docker
- stage: build
- script:
- - docker build -t my-docker-image .
- - docker run my-docker-image /script/to/run/tests
-```
-
-If you forget to set the service alias, the `docker:20.10.16` image is unable to find the
-`dind` service, and an error like the following is thrown:
-
-```plaintext
-error during connect: Get http://docker:2376/v1.39/info: dial tcp: lookup docker on 192.168.0.1:53: no such host
-```
-
-### Using a Docker-in-Docker image with Dependency Proxy
-
-To use your own Docker images with Dependency Proxy, follow these steps
-in addition to the steps in the
-[Docker-in-Docker](../../../ci/docker/using_docker_build.md#use-docker-in-docker) section:
-
-1. Update the `image` and `service` to point to your registry.
-1. Add a service [alias](../../../ci/services/index.md#available-settings-for-services).
-
-Below is an example of what your `.gitlab-ci.yml` should look like:
-
-```yaml
-build:
- image: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:20.10.16
- services:
- - name: ${CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX}/docker:18.09.7-dind
- alias: docker
- stage: build
- script:
- - docker build -t my-docker-image .
- - docker run my-docker-image /script/to/run/tests
-```
-
-If you forget to set the service alias, the `docker:20.10.16` image is unable to find the
-`dind` service, and an error like the following is thrown:
-
-```plaintext
-error during connect: Get http://docker:2376/v1.39/info: dial tcp: lookup docker on 192.168.0.1:53: no such host
-```
-
-## Delete images
-
-You can delete images from your Container Registry in multiple ways.
-
-WARNING:
-Deleting images is a destructive action and can't be undone. To restore
-a deleted image, you must rebuild and re-upload it.
-
-On self-managed instances, deleting an image doesn't free up storage space - it only marks the image
-as eligible for deletion. To actually delete images and recover storage space, in case they're
-unreferenced, administrators must run [garbage collection](../../../administration/packages/container_registry.md#container-registry-garbage-collection).
-
-On GitLab.com, the latest version of the Container Registry includes an automatic online garbage
-collector. For more information, see [this blog post](https://about.gitlab.com/blog/2021/10/25/gitlab-com-container-registry-update/).
-The automatic online garbage collector is an instance-wide feature, rolling out gradually to a subset
-of the user base. Some new image repositories created from GitLab 14.5 onward are served by this
-new version of the Container Registry. In this new version of the Container Registry, layers that aren't
-referenced by any image manifest, and image manifests that have no tags and aren't referenced by another
-manifest (such as multi-architecture images), are automatically scheduled for deletion after 24 hours if
-left unreferenced.
-
-### Delete images using the GitLab UI
-
-To delete images using the GitLab UI:
-
-1. Go to your project's or group's **Packages and registries > Container Registry**.
-1. From the **Container Registry** page, you can select what you want to delete,
- by either:
-
- - Deleting the entire repository, and all the tags it contains, by selecting
- the red **{remove}** **Trash** icon.
- - Navigating to the repository, and deleting tags individually or in bulk
- by selecting the red **{remove}** **Trash** icon next to the tag you want
- to delete.
-
-1. In the dialog box, select **Remove tag**.
-
-### Delete images using the API
-
-If you want to automate the process of deleting images, GitLab provides an API. For more
-information, see the following endpoints:
-
-- [Delete a Registry repository](../../../api/container_registry.md#delete-registry-repository)
-- [Delete an individual Registry repository tag](../../../api/container_registry.md#delete-a-registry-repository-tag)
-- [Delete Registry repository tags in bulk](../../../api/container_registry.md#delete-registry-repository-tags-in-bulk)
-
-### Delete images using GitLab CI/CD
-
-WARNING:
-GitLab CI/CD doesn't provide a built-in way to remove your images. This example
-uses a third-party tool called [reg](https://github.com/genuinetools/reg)
-that talks to the GitLab Registry API. You are responsible for your own actions.
-For assistance with this tool, see
-[the issue queue for reg](https://github.com/genuinetools/reg/issues).
-
-The following example defines two stages: `build`, and `clean`. The
-`build_image` job builds the Docker image for the branch, and the
-`delete_image` job deletes it. The `reg` executable is downloaded and used to
-remove the image matching the `$CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG`
-[predefined CI/CD variable](../../../ci/variables/predefined_variables.md).
-
-To use this example, change the `IMAGE_TAG` variable to match your needs:
-
-```yaml
-stages:
- - build
- - clean
-
-build_image:
- image: docker:20.10.16
- stage: build
- services:
- - docker:20.10.16-dind
- variables:
- IMAGE_TAG: $CI_REGISTRY_IMAGE:$CI_COMMIT_REF_SLUG
- script:
- - docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- - docker build -t $IMAGE_TAG .
- - docker push $IMAGE_TAG
- only:
- - branches
- except:
- - main
-
-delete_image:
- before_script:
- - curl --fail --show-error --location "https://github.com/genuinetools/reg/releases/download/v$REG_VERSION/reg-linux-amd64" --output ./reg
- - echo "$REG_SHA256 ./reg" | sha256sum -c -
- - chmod a+x ./reg
- image: curlimages/curl:7.86.0
- script:
- - ./reg rm -d --auth-url $CI_REGISTRY -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $IMAGE_TAG
- stage: clean
- variables:
- IMAGE_TAG: $CI_PROJECT_PATH:$CI_COMMIT_REF_SLUG
- REG_SHA256: ade837fc5224acd8c34732bf54a94f579b47851cc6a7fd5899a98386b782e228
- REG_VERSION: 0.16.1
- only:
- - branches
- except:
- - main
-```
-
-NOTE:
-You can download the latest `reg` release from
-[the releases page](https://github.com/genuinetools/reg/releases), then update
-the code example by changing the `REG_SHA256` and `REG_VERSION` variables
-defined in the `delete_image` job.
-
-### Delete images by using a cleanup policy
-
-You can create a per-project [cleanup policy](reduce_container_registry_storage.md#cleanup-policy) to ensure older tags and images are regularly removed from the
-Container Registry.
-
-## Known issues
+## Move or rename Container Registry repositories
-Moving or renaming existing Container Registry repositories is not supported
-after you have pushed images. The images are stored in a path that matches
-the repository path. To move or rename a repository with a
-Container Registry, you must delete all existing images.
-Community suggestions to work around this known issue have been shared in
+Moving or renaming existing Container Registry repositories is not supported after you have pushed
+container images. The container images are stored in a path that matches the repository path. To move
+or rename a repository with a Container Registry, you must delete all existing container images.
+Community suggestions to work around this known issue are shared in
[issue 18383](https://gitlab.com/gitlab-org/gitlab/-/issues/18383#possible-workaround).
## Disable the Container Registry for a project
@@ -500,7 +115,8 @@ The Container Registry is enabled by default.
You can, however, remove the Container Registry for a project:
-1. Go to your project's **Settings > General** page.
+1. On the top bar, select **Main menu > Projects**.
+1. On the left sidebar, select **Settings > General**.
1. Expand the **Visibility, project features, permissions** section
and disable **Container Registry**.
1. Select **Save changes**.
@@ -514,10 +130,11 @@ The **Packages and registries > Container Registry** entry is removed from the p
By default, the Container Registry is visible to everyone with access to the project.
You can, however, change the visibility of the Container Registry for a project.
-See the [Container Registry visibility permissions](#container-registry-visibility-permissions)
-for more details about the permissions that this setting grants to users.
+For more information about the permissions that this setting grants to users,
+see [Container Registry visibility permissions](#container-registry-visibility-permissions).
-1. Go to your project's **Settings > General** page.
+1. On the top bar, select **Main menu > Projects**.
+1. On the left sidebar, select **Settings > General**.
1. Expand the section **Visibility, project features, permissions**.
1. Under **Container Registry**, select an option from the dropdown list:
@@ -533,19 +150,18 @@ for more details about the permissions that this setting grants to users.
## Container Registry visibility permissions
-The ability to view the Container Registry and pull images is controlled by the Container Registry's
-visibility permissions. You can change this through the [visibility setting on the UI](#change-visibility-of-the-container-registry)
+The ability to view the Container Registry and pull container images is controlled by the Container Registry's
+visibility permissions. You can change the visibility through the [visibility setting on the UI](#change-visibility-of-the-container-registry)
or the [API](../../../api/container_registry.md#change-the-visibility-of-the-container-registry).
-[Other permissions](../../permissions.md)
-such as updating the Container Registry and pushing or deleting images are not affected by
+[Other permissions](../../permissions.md) such as updating the Container Registry and pushing or deleting container images are not affected by
this setting. However, disabling the Container Registry disables all Container Registry operations.
-| | | Anonymous<br/>(Everyone on internet) | Guest | Reporter, Developer, Maintainer, Owner |
-| -------------------- | --------------------- | --------- | ----- | ------------------------------------------ |
-| Public project with Container Registry visibility <br/> set to **Everyone With Access** (UI) or `enabled` (API) | View Container Registry <br/> and pull images | Yes | Yes | Yes |
-| Public project with Container Registry visibility <br/> set to **Only Project Members** (UI) or `private` (API) | View Container Registry <br/> and pull images | No | No | Yes |
-| Internal project with Container Registry visibility <br/> set to **Everyone With Access** (UI) or `enabled` (API) | View Container Registry <br/> and pull images | No | Yes | Yes |
-| Internal project with Container Registry visibility <br/> set to **Only Project Members** (UI) or `private` (API) | View Container Registry <br/> and pull images | No | No | Yes |
-| Private project with Container Registry visibility <br/> set to **Everyone With Access** (UI) or `enabled` (API) | View Container Registry <br/> and pull images | No | No | Yes |
-| Private project with Container Registry visibility <br/> set to **Only Project Members** (UI) or `private` (API) | View Container Registry <br/> and pull images | No | No | Yes |
-| Any project with Container Registry `disabled` | All operations on Container Registry | No | No | No |
+| | | Anonymous<br/>(Everyone on internet) | Guest | Reporter, Developer, Maintainer, Owner |
+|-------------------------------------------------------------------------------------------------------------------|-----------------------------------------------|--------------------------------------|-------|----------------------------------------|
+| Public project with Container Registry visibility <br/> set to **Everyone With Access** (UI) or `enabled` (API) | View Container Registry <br/> and pull images | Yes | Yes | Yes |
+| Public project with Container Registry visibility <br/> set to **Only Project Members** (UI) or `private` (API) | View Container Registry <br/> and pull images | No | No | Yes |
+| Internal project with Container Registry visibility <br/> set to **Everyone With Access** (UI) or `enabled` (API) | View Container Registry <br/> and pull images | No | Yes | Yes |
+| Internal project with Container Registry visibility <br/> set to **Only Project Members** (UI) or `private` (API) | View Container Registry <br/> and pull images | No | No | Yes |
+| Private project with Container Registry visibility <br/> set to **Everyone With Access** (UI) or `enabled` (API) | View Container Registry <br/> and pull images | No | No | Yes |
+| Private project with Container Registry visibility <br/> set to **Only Project Members** (UI) or `private` (API) | View Container Registry <br/> and pull images | No | No | Yes |
+| Any project with Container Registry `disabled` | All operations on Container Registry | No | No | No |
diff --git a/doc/user/packages/container_registry/reduce_container_registry_storage.md b/doc/user/packages/container_registry/reduce_container_registry_storage.md
index cbf9af633ac..15948569cb8 100644
--- a/doc/user/packages/container_registry/reduce_container_registry_storage.md
+++ b/doc/user/packages/container_registry/reduce_container_registry_storage.md
@@ -36,7 +36,7 @@ An image layer is only counted once if:
- You share the image layer across different repositories.
Only layers that are referenced by tagged images are accounted for. Untagged images and any layers
-referenced exclusively by them are subject to [online garbage collection](index.md#delete-images).
+referenced exclusively by them are subject to [online garbage collection](delete_container_registry_images.md).
Untagged images are automatically deleted after 24 hours if they remain unreferenced during that period.
Image layers are stored on the storage backend in the original (usually compressed) format. This
@@ -269,7 +269,7 @@ only if the number of tags being cleaned up is minimal.
Here are some other options you can use to reduce the Container Registry storage used by your project:
-- Use the [GitLab UI](index.md#delete-images)
+- Use the [GitLab UI](delete_container_registry_images.md#use-the-gitlab-ui)
to delete individual image tags or the entire repository containing all the tags.
- Use the API to [delete individual image tags](../../../api/container_registry.md#delete-a-registry-repository-tag).
- Use the API to [delete the entire container registry repository containing all the tags](../../../api/container_registry.md#delete-registry-repository).
diff --git a/doc/user/packages/container_registry/troubleshoot_container_registry.md b/doc/user/packages/container_registry/troubleshoot_container_registry.md
index eac7e0fcacd..68fe430e531 100644
--- a/doc/user/packages/container_registry/troubleshoot_container_registry.md
+++ b/doc/user/packages/container_registry/troubleshoot_container_registry.md
@@ -87,7 +87,7 @@ The following procedure uses these sample project names:
docker tag gitlab.example.com/org/build/sample_project/cr:v2.9.1 gitlab.example.com/new_org/build/new_sample_project/cr:v2.9.1
```
-1. Delete the images in the old project by using the [UI](index.md#delete-images) or [API](../../../api/packages.md#delete-a-project-package).
+1. Delete the images in the old project by using the [UI](delete_container_registry_images.md) or [API](../../../api/packages.md#delete-a-project-package).
There may be a delay while the images are queued and deleted.
1. Change the path or transfer the project:
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index 5d1db760bff..321b351a86a 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -71,7 +71,7 @@ The following table lists project permissions available for each role:
| [Application security](application_security/index.md):<br>Create or assign [security policy project](application_security/policies/index.md) | | | | | ✓ |
| [Clusters](infrastructure/clusters/index.md):<br>View clusters | | | ✓ | ✓ | ✓ |
| [Clusters](infrastructure/clusters/index.md):<br>Manage clusters | | | | ✓ | ✓ |
-| [Container Registry](packages/container_registry/index.md):<br>Create, edit, delete [cleanup policies](packages/container_registry/index.md#delete-images-by-using-a-cleanup-policy) | | | | ✓ | ✓ |
+| [Container Registry](packages/container_registry/index.md):<br>Create, edit, delete [cleanup policies](packages/container_registry/delete_container_registry_images.md#use-a-cleanup-policy) | | | | ✓ | ✓ |
| [Container Registry](packages/container_registry/index.md):<br>Push an image to the Container Registry | | | ✓ | ✓ | ✓ |
| [Container Registry](packages/container_registry/index.md):<br>Pull an image from the Container Registry | ✓ (*19*) | ✓ (*19*) | ✓ | ✓ | ✓ |
| [Container Registry](packages/container_registry/index.md):<br>Remove a Container Registry image | | | ✓ | ✓ | ✓ |
diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md
index 39826bf59c4..5f23f50f439 100644
--- a/doc/user/profile/account/two_factor_authentication.md
+++ b/doc/user/profile/account/two_factor_authentication.md
@@ -444,7 +444,7 @@ This error occurs in the following scenarios:
password. For 2FA-enabled users, a [personal access token](../personal_access_tokens.md) (PAT)
must be used instead of a password. To authenticate:
- Git requests over HTTP(S), a PAT with `read_repository` or `write_repository` scope is required.
- - [GitLab Container Registry](../../packages/container_registry/index.md#authenticate-with-the-container-registry) requests, a PAT
+ - [GitLab Container Registry](../../packages/container_registry/authenticate_with_container_registry.md) requests, a PAT
with `read_registry` or `write_registry` scope is required.
- [Dependency Proxy](../../packages/dependency_proxy/index.md#authenticate-with-the-dependency-proxy) requests, a PAT with
`read_registry` and `write_registry` scopes is required.
diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md
index 507ad6378bc..9490ab151aa 100644
--- a/doc/user/profile/personal_access_tokens.md
+++ b/doc/user/profile/personal_access_tokens.md
@@ -31,7 +31,7 @@ Personal access tokens are:
- Required when [two-factor authentication (2FA)](account/two_factor_authentication.md) is enabled.
- Used with a GitLab username to authenticate with GitLab features that require usernames. For example,
[GitLab-managed Terraform state backend](../infrastructure/iac/terraform_state.md#use-your-gitlab-backend-as-a-remote-data-source)
- and [Docker container registry](../packages/container_registry/index.md#authenticate-with-the-container-registry),
+ and [Docker container registry](../packages/container_registry/authenticate_with_container_registry.md),
- Similar to [project access tokens](../project/settings/project_access_tokens.md) and [group access tokens](../group/settings/group_access_tokens.md), but are attached
to a user rather than a project or group.
diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md
index a88427ab20b..6c29cba281d 100644
--- a/doc/user/project/settings/index.md
+++ b/doc/user/project/settings/index.md
@@ -239,7 +239,7 @@ Prerequisites:
- You must have at least the Maintainer role for the [group](../../group/manage.md#create-a-group) to which you are transferring.
- You must be the Owner of the project you transfer.
- The group must allow creation of new projects.
-- The project must not contain any [container images](../../packages/container_registry/index.md#known-issues).
+- The project must not contain any [container images](../../packages/container_registry/index.md#move-or-rename-container-registry-repositories).
- Remove any npm packages. If you transfer a project to a different root namespace, the project must not contain any npm packages. When you update the path of a user or group, or transfer a subgroup or project, you must remove any npm packages first. You cannot update the root namespace of a project with npm packages. Make sure you update your .npmrc files to follow the naming convention and run npm publish if necessary.
To transfer a project:
diff --git a/lib/gitlab/gitaly_client.rb b/lib/gitlab/gitaly_client.rb
index 735c7fcf80c..20eff74c4b1 100644
--- a/lib/gitlab/gitaly_client.rb
+++ b/lib/gitlab/gitaly_client.rb
@@ -52,11 +52,29 @@ module Gitlab
private_class_method :interceptors
def self.channel_args
- # These values match the go Gitaly client
- # https://gitlab.com/gitlab-org/gitaly/-/blob/bf9f52bc/client/dial.go#L78
{
+ # These keepalive values match the go Gitaly client
+ # https://gitlab.com/gitlab-org/gitaly/-/blob/bf9f52bc/client/dial.go#L78
'grpc.keepalive_time_ms': 20000,
- 'grpc.keepalive_permit_without_calls': 1
+ 'grpc.keepalive_permit_without_calls': 1,
+ # Enable client-side automatic retry. After enabled, gRPC requests will be retried when there are connectivity
+ # problems with the target host. Only transparent failures, which mean requests fail before leaving clients, are
+ # eligible. Other cases are configurable via retry policy in service config (below). In theory, we can auto-retry
+ # read-only RPCs. Gitaly defines a custom field in service proto. Unfortunately, gRPC ruby doesn't support
+ # descriptor reflection.
+ # For more information please visit https://github.com/grpc/proposal/blob/master/A6-client-retries.md
+ 'grpc.enable_retries': 1,
+ # Service config is a mechanism for grpc to control the behavior of gRPC client. It defines the client-side
+ # balancing strategy and retry policy. The config receives a raw JSON string. The format is defined here:
+ # https://github.com/grpc/grpc-proto/blob/master/grpc/service_config/service_config.proto
+ 'grpc.service_config': {
+ # By default, gRPC uses pick_first strategy. This strategy establishes one single connection to the first
+ # target returned by the name resolver. We would like to use round_robin load-balancing strategy so that
+ # grpc creates multiple subchannels to all targets retrurned by the resolver. Requests are distributed to
+ # those subchannels in a round-robin fashion.
+ # More about client-side load-balancing: https://gitlab.com/groups/gitlab-org/-/epics/8971#note_1207008162
+ "loadBalancingConfig": [{ "round_robin": {} }]
+ }.to_json
}
end
private_class_method :channel_args
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index d05f0c9807d..47b744ef423 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -25905,6 +25905,15 @@ msgstr ""
msgid "Members|2FA"
msgstr ""
+msgid "Members|A group must have at least one owner. To leave this group, assign a new owner."
+msgstr ""
+
+msgid "Members|A group must have at least one owner. To remove the member, assign a new owner."
+msgstr ""
+
+msgid "Members|A personal project's owner cannot be removed."
+msgstr ""
+
msgid "Members|Access granted"
msgstr ""
@@ -25944,6 +25953,9 @@ msgstr ""
msgid "Members|Are you sure you want to withdraw your access request for \"%{source}\""
msgstr ""
+msgid "Members|Cannot leave \"%{source}\""
+msgstr ""
+
msgid "Members|Direct"
msgstr ""
@@ -26010,6 +26022,9 @@ msgstr ""
msgid "Members|User created"
msgstr ""
+msgid "Members|You cannot remove yourself from a personal project."
+msgstr ""
+
msgid "Member|Deny access"
msgstr ""
@@ -36161,7 +36176,7 @@ msgstr ""
msgid "Runners|Executor"
msgstr ""
-msgid "Runners|Existing runners are not affected. To permit runner registration for all groups, enable this setting in the Admin Area in Settings &gt CI/CD."
+msgid "Runners|Existing runners are not affected. To permit runner registration for all groups, enable this setting in the Admin Area in Settings &gt; CI/CD."
msgstr ""
msgid "Runners|Filter projects"
diff --git a/spec/frontend/members/components/action_dropdowns/leave_group_dropdown_item_spec.js b/spec/frontend/members/components/action_dropdowns/leave_group_dropdown_item_spec.js
index 4b47b156cba..90f5b217007 100644
--- a/spec/frontend/members/components/action_dropdowns/leave_group_dropdown_item_spec.js
+++ b/spec/frontend/members/components/action_dropdowns/leave_group_dropdown_item_spec.js
@@ -4,7 +4,7 @@ import { createMockDirective, getBinding } from 'helpers/vue_mock_directive';
import LeaveGroupDropdownItem from '~/members/components/action_dropdowns/leave_group_dropdown_item.vue';
import LeaveModal from '~/members/components/modals/leave_modal.vue';
import { LEAVE_MODAL_ID } from '~/members/constants';
-import { member } from '../../mock_data';
+import { member, permissions } from '../../mock_data';
describe('LeaveGroupDropdownItem', () => {
let wrapper;
@@ -14,6 +14,7 @@ describe('LeaveGroupDropdownItem', () => {
wrapper = shallowMount(LeaveGroupDropdownItem, {
propsData: {
member,
+ permissions,
...propsData,
},
directives: {
@@ -42,7 +43,7 @@ describe('LeaveGroupDropdownItem', () => {
it('contains LeaveModal component', () => {
const leaveModal = wrapper.findComponent(LeaveModal);
- expect(leaveModal.props('member')).toEqual(member);
+ expect(leaveModal.props()).toEqual({ member, permissions });
});
it('binds to the LeaveModal component', () => {
diff --git a/spec/frontend/members/components/action_dropdowns/remove_member_dropdown_item_spec.js b/spec/frontend/members/components/action_dropdowns/remove_member_dropdown_item_spec.js
index 0ae9e257f2b..e1c498249d7 100644
--- a/spec/frontend/members/components/action_dropdowns/remove_member_dropdown_item_spec.js
+++ b/spec/frontend/members/components/action_dropdowns/remove_member_dropdown_item_spec.js
@@ -69,6 +69,9 @@ describe('RemoveMemberDropdownItem', () => {
it('calls Vuex action to show `remove member` modal when clicked', () => {
findDropdownItem().vm.$emit('click');
- expect(actions.showRemoveMemberModal).toHaveBeenCalledWith(expect.any(Object), modalData);
+ expect(actions.showRemoveMemberModal).toHaveBeenCalledWith(expect.any(Object), {
+ ...modalData,
+ preventRemoval: false,
+ });
});
});
diff --git a/spec/frontend/members/components/action_dropdowns/user_action_dropdown_spec.js b/spec/frontend/members/components/action_dropdowns/user_action_dropdown_spec.js
index ae45e737581..5a2de1cac80 100644
--- a/spec/frontend/members/components/action_dropdowns/user_action_dropdown_spec.js
+++ b/spec/frontend/members/components/action_dropdowns/user_action_dropdown_spec.js
@@ -74,6 +74,7 @@ describe('UserActionDropdown', () => {
name: member.user.name,
obstacles: parseUserDeletionObstacles(member.user),
},
+ preventRemoval: false,
});
});
@@ -120,6 +121,63 @@ describe('UserActionDropdown', () => {
});
});
+ describe('when user can remove but it is blocked by last owner', () => {
+ const permissions = {
+ canRemove: false,
+ canRemoveBlockedByLastOwner: true,
+ };
+
+ it('renders remove member dropdown', () => {
+ createComponent({
+ permissions,
+ });
+
+ expect(findRemoveMemberDropdownItem().exists()).toBe(true);
+ });
+
+ describe('when member model type is `GroupMember`', () => {
+ it('passes correct message to the modal', () => {
+ createComponent({
+ permissions,
+ });
+
+ expect(findRemoveMemberDropdownItem().props('modalMessage')).toBe(
+ I18N.lastGroupOwnerCannotBeRemoved,
+ );
+ });
+ });
+
+ describe('when member model type is `ProjectMember`', () => {
+ it('passes correct message to the modal', () => {
+ createComponent({
+ member: {
+ ...member,
+ type: MEMBER_MODEL_TYPE_PROJECT_MEMBER,
+ },
+ permissions,
+ });
+
+ expect(findRemoveMemberDropdownItem().props('modalMessage')).toBe(
+ I18N.personalProjectOwnerCannotBeRemoved,
+ );
+ });
+ });
+
+ describe('when member is the current user', () => {
+ it('renders leave dropdown with correct props', () => {
+ createComponent({
+ isCurrentUser: true,
+ permissions,
+ });
+
+ expect(wrapper.findComponent(LeaveGroupDropdownItem).props()).toEqual({
+ member,
+ permissions,
+ });
+ });
+ });
+ });
+
describe('when group member', () => {
beforeEach(() => {
createComponent({
diff --git a/spec/frontend/members/components/modals/leave_modal_spec.js b/spec/frontend/members/components/modals/leave_modal_spec.js
index cdbabb2f646..ba587c6f0b3 100644
--- a/spec/frontend/members/components/modals/leave_modal_spec.js
+++ b/spec/frontend/members/components/modals/leave_modal_spec.js
@@ -1,11 +1,14 @@
import { GlModal, GlForm } from '@gitlab/ui';
-import { within } from '@testing-library/dom';
-import { mount, createWrapper } from '@vue/test-utils';
import { cloneDeep } from 'lodash';
import Vue, { nextTick } from 'vue';
import Vuex from 'vuex';
+import { mountExtended, extendedWrapper } from 'helpers/vue_test_utils_helper';
import LeaveModal from '~/members/components/modals/leave_modal.vue';
-import { LEAVE_MODAL_ID, MEMBER_TYPES } from '~/members/constants';
+import {
+ LEAVE_MODAL_ID,
+ MEMBER_TYPES,
+ MEMBER_MODEL_TYPE_PROJECT_MEMBER,
+} from '~/members/constants';
import UserDeletionObstaclesList from '~/vue_shared/components/user_deletion_obstacles/user_deletion_obstacles_list.vue';
import { parseUserDeletionObstacles } from '~/vue_shared/components/user_deletion_obstacles/utils';
import { member } from '../../mock_data';
@@ -31,14 +34,17 @@ describe('LeaveModal', () => {
});
};
- const createComponent = (propsData = {}, state) => {
- wrapper = mount(LeaveModal, {
+ const createComponent = async (propsData = {}, state) => {
+ wrapper = mountExtended(LeaveModal, {
store: createStore(state),
provide: {
namespace: MEMBER_TYPES.user,
},
propsData: {
member,
+ permissions: {
+ canRemove: true,
+ },
...propsData,
},
attrs: {
@@ -46,39 +52,98 @@ describe('LeaveModal', () => {
visible: true,
},
});
+
+ await nextTick();
};
- const findModal = () => wrapper.findComponent(GlModal);
+ const findModal = () => extendedWrapper(wrapper.findComponent(GlModal));
const findForm = () => findModal().findComponent(GlForm);
const findUserDeletionObstaclesList = () => findModal().findComponent(UserDeletionObstaclesList);
- const getByText = (text, options) =>
- createWrapper(within(findModal().element).getByText(text, options));
-
- beforeEach(async () => {
- createComponent();
- await nextTick();
- });
-
afterEach(() => {
wrapper.destroy();
});
- it('sets modal ID', () => {
+ it('sets modal ID', async () => {
+ await createComponent();
+
expect(findModal().props('modalId')).toBe(LEAVE_MODAL_ID);
});
- it('displays modal title', () => {
- expect(getByText(`Leave "${member.source.fullName}"`).exists()).toBe(true);
+ describe('when leave is allowed', () => {
+ it('displays modal title', async () => {
+ await createComponent();
+
+ expect(findModal().findByText(`Leave "${member.source.fullName}"`).exists()).toBe(true);
+ });
+
+ it('displays modal body', async () => {
+ await createComponent();
+
+ expect(
+ findModal()
+ .findByText(`Are you sure you want to leave "${member.source.fullName}"?`)
+ .exists(),
+ ).toBe(true);
+ });
});
- it('displays modal body', () => {
- expect(getByText(`Are you sure you want to leave "${member.source.fullName}"?`).exists()).toBe(
- true,
- );
+ describe('when leave is blocked by last owner', () => {
+ const permissions = {
+ canRemove: false,
+ canRemoveBlockedByLastOwner: true,
+ };
+
+ it('does not show primary action button', async () => {
+ await createComponent({
+ permissions,
+ });
+
+ expect(findModal().props('actionPrimary')).toBe(null);
+ });
+
+ it('displays modal title', async () => {
+ await createComponent({
+ permissions,
+ });
+
+ expect(findModal().findByText(`Cannot leave "${member.source.fullName}"`).exists()).toBe(
+ true,
+ );
+ });
+
+ describe('when member model type is `GroupMember`', () => {
+ it('displays modal body', async () => {
+ await createComponent({
+ permissions,
+ });
+
+ expect(
+ findModal().findByText(LeaveModal.i18n.preventedBodyGroupMemberModelType).exists(),
+ ).toBe(true);
+ });
+ });
+
+ describe('when member model type is `ProjectMember`', () => {
+ it('displays modal body', async () => {
+ await createComponent({
+ member: {
+ ...member,
+ type: MEMBER_MODEL_TYPE_PROJECT_MEMBER,
+ },
+ permissions,
+ });
+
+ expect(
+ findModal().findByText(LeaveModal.i18n.preventedBodyProjectMemberModelType).exists(),
+ ).toBe(true);
+ });
+ });
});
- it('displays form with correct action and inputs', () => {
+ it('displays form with correct action and inputs', async () => {
+ await createComponent();
+
const form = findForm();
expect(form.attributes('action')).toBe('/groups/foo-bar/-/group_members/leave');
@@ -89,7 +154,9 @@ describe('LeaveModal', () => {
});
describe('User deletion obstacles list', () => {
- it("displays obstacles list when member's user is part of on-call management", () => {
+ it("displays obstacles list when member's user is part of on-call management", async () => {
+ await createComponent();
+
const obstaclesList = findUserDeletionObstaclesList();
expect(obstaclesList.exists()).toBe(true);
expect(obstaclesList.props()).toMatchObject({
@@ -105,17 +172,18 @@ describe('LeaveModal', () => {
delete memberWithoutOncall.user.oncallSchedules;
delete memberWithoutOncall.user.escalationPolicies;
- createComponent({ member: memberWithoutOncall });
- await nextTick();
+ await createComponent({ member: memberWithoutOncall });
expect(findUserDeletionObstaclesList().exists()).toBe(false);
});
});
- it('submits the form when "Leave" button is clicked', () => {
+ it('submits the form when "Leave" button is clicked', async () => {
+ await createComponent();
+
const submitSpy = jest.spyOn(findForm().element, 'submit');
- getByText('Leave').trigger('click');
+ findModal().findByText('Leave').trigger('click');
expect(submitSpy).toHaveBeenCalled();
diff --git a/spec/frontend/members/components/modals/remove_member_modal_spec.js b/spec/frontend/members/components/modals/remove_member_modal_spec.js
index a9ff95dd948..47a03b5083a 100644
--- a/spec/frontend/members/components/modals/remove_member_modal_spec.js
+++ b/spec/frontend/members/components/modals/remove_member_modal_spec.js
@@ -137,4 +137,28 @@ describe('RemoveMemberModal', () => {
});
},
);
+
+ describe('when removal is prevented', () => {
+ const message =
+ 'A group must have at least one owner. To remove the member, assign a new owner.';
+
+ beforeEach(() => {
+ createComponent({
+ actionText: 'Remove member',
+ memberModelType: MEMBER_MODEL_TYPE_GROUP_MEMBER,
+ isAccessRequest: false,
+ isInvite: false,
+ message,
+ preventRemoval: true,
+ });
+ });
+
+ it('does not show primary action button', () => {
+ expect(findGlModal().props('actionPrimary')).toBe(null);
+ });
+
+ it('only shows the message', () => {
+ expect(findGlModal().text()).toBe(message);
+ });
+ });
});
diff --git a/spec/frontend/members/components/table/members_table_cell_spec.js b/spec/frontend/members/components/table/members_table_cell_spec.js
index 0b0140b0cdb..ac5d83d028d 100644
--- a/spec/frontend/members/components/table/members_table_cell_spec.js
+++ b/spec/frontend/members/components/table/members_table_cell_spec.js
@@ -3,6 +3,7 @@ import Vue from 'vue';
import Vuex from 'vuex';
import MembersTableCell from '~/members/components/table/members_table_cell.vue';
import { MEMBER_TYPES } from '~/members/constants';
+import { canRemoveBlockedByLastOwner } from '~/members/utils';
import {
member as memberMock,
directMember,
@@ -12,6 +13,11 @@ import {
accessRequest,
} from '../../mock_data';
+jest.mock('~/members/utils', () => ({
+ ...jest.requireActual('~/members/utils'),
+ canRemoveBlockedByLastOwner: jest.fn().mockImplementation(() => true),
+}));
+
describe('MembersTableCell', () => {
const WrappedComponent = {
props: {
@@ -55,6 +61,7 @@ describe('MembersTableCell', () => {
provide: {
sourceId: 1,
currentUserId: 1,
+ canManageMembers: true,
},
scopedSlots: {
default: `
@@ -179,6 +186,15 @@ describe('MembersTableCell', () => {
});
});
+ describe('canRemoveBlockedByLastOwner', () => {
+ it('calls util and returns value', () => {
+ createComponentWithDirectMember();
+
+ expect(canRemoveBlockedByLastOwner).toHaveBeenCalledWith(directMember, true);
+ expect(findWrappedComponent().props('permissions').canRemoveBlockedByLastOwner).toBe(true);
+ });
+ });
+
describe('canResend', () => {
describe('when member type is `invite`', () => {
it('returns `true` when `canResend` is `true`', () => {
diff --git a/spec/frontend/members/components/table/members_table_spec.js b/spec/frontend/members/components/table/members_table_spec.js
index 3165173ce21..1d18026a410 100644
--- a/spec/frontend/members/components/table/members_table_spec.js
+++ b/spec/frontend/members/components/table/members_table_spec.js
@@ -63,6 +63,7 @@ describe('MembersTable', () => {
provide: {
sourceId: 1,
currentUserId: 1,
+ canManageMembers: true,
namespace: MEMBER_TYPES.invite,
...provide,
},
@@ -200,16 +201,23 @@ describe('MembersTable', () => {
canRemove: true,
};
+ const memberCanRemoveBlockedLastOwner = {
+ ...directMember,
+ canRemove: false,
+ isLastOwner: true,
+ };
+
const memberNoPermissions = {
...memberMock,
id: 2,
};
describe.each`
- permission | members
- ${'canUpdate'} | ${[memberNoPermissions, memberCanUpdate]}
- ${'canRemove'} | ${[memberNoPermissions, memberCanRemove]}
- ${'canResend'} | ${[memberNoPermissions, invite]}
+ permission | members
+ ${'canUpdate'} | ${[memberNoPermissions, memberCanUpdate]}
+ ${'canRemove'} | ${[memberNoPermissions, memberCanRemove]}
+ ${'canRemoveBlockedByLastOwner'} | ${[memberNoPermissions, memberCanRemoveBlockedLastOwner]}
+ ${'canResend'} | ${[memberNoPermissions, invite]}
`('when one of the members has $permission permissions', ({ members }) => {
it('renders the "Actions" field', () => {
createComponent({ members, tableFields: ['actions'] });
@@ -228,10 +236,11 @@ describe('MembersTable', () => {
});
describe.each`
- permission | members
- ${'canUpdate'} | ${[memberMock]}
- ${'canRemove'} | ${[memberMock]}
- ${'canResend'} | ${[{ ...invite, invite: { ...invite.invite, canResend: false } }]}
+ permission | members
+ ${'canUpdate'} | ${[memberMock]}
+ ${'canRemove'} | ${[memberMock]}
+ ${'canRemoveBlockedByLastOwner'} | ${[memberMock]}
+ ${'canResend'} | ${[{ ...invite, invite: { ...invite.invite, canResend: false } }]}
`('when none of the members have $permission permissions', ({ members }) => {
it('does not render the "Actions" field', () => {
createComponent({ members, tableFields: ['actions'] });
diff --git a/spec/frontend/members/mock_data.js b/spec/frontend/members/mock_data.js
index 3f88cb7b386..7ab642c84a7 100644
--- a/spec/frontend/members/mock_data.js
+++ b/spec/frontend/members/mock_data.js
@@ -17,7 +17,7 @@ export const member = {
fullName: 'Foo Bar',
webUrl: 'https://gitlab.com/groups/foo-bar',
},
- type: 'GroupMember',
+ type: MEMBER_MODEL_TYPE_GROUP_MEMBER,
state: MEMBER_STATE_CREATED,
user: {
id: 123,
@@ -131,3 +131,10 @@ export const dataAttribute = JSON.stringify({
source_id: 234,
can_manage_members: true,
});
+
+export const permissions = {
+ canRemove: true,
+ canRemoveBlockedByLastOwner: false,
+ canResend: true,
+ canUpdate: true,
+};
diff --git a/spec/frontend/members/utils_spec.js b/spec/frontend/members/utils_spec.js
index 8bef2096a2a..9d52c789db2 100644
--- a/spec/frontend/members/utils_spec.js
+++ b/spec/frontend/members/utils_spec.js
@@ -13,6 +13,7 @@ import {
isDirectMember,
isCurrentUser,
canRemove,
+ canRemoveBlockedByLastOwner,
canResend,
canUpdate,
canOverride,
@@ -129,6 +130,17 @@ describe('Members Utils', () => {
});
});
+ describe('canRemoveBlockedByLastOwner', () => {
+ it.each`
+ member | canManageMembers | expected
+ ${{ ...directMember, isLastOwner: true }} | ${true} | ${true}
+ ${{ ...inheritedMember, isLastOwner: false }} | ${true} | ${false}
+ ${{ ...directMember, isLastOwner: true }} | ${false} | ${false}
+ `('returns $expected', ({ member, canManageMembers, expected }) => {
+ expect(canRemoveBlockedByLastOwner(member, canManageMembers)).toBe(expected);
+ });
+ });
+
describe('canResend', () => {
it.each`
member | expected
diff --git a/workhorse/internal/lsif_transformer/parser/docs.go b/workhorse/internal/lsif_transformer/parser/docs.go
index f87bc7fd86c..9cdec4c8d42 100644
--- a/workhorse/internal/lsif_transformer/parser/docs.go
+++ b/workhorse/internal/lsif_transformer/parser/docs.go
@@ -5,6 +5,7 @@ import (
"bufio"
"encoding/json"
"io"
+ "path/filepath"
"strings"
)
@@ -116,7 +117,7 @@ func (d *Docs) addMetadata(line []byte) error {
return err
}
- d.Root = strings.TrimSpace(metadata.Root) + "/"
+ d.Root = strings.TrimSpace(metadata.Root)
return nil
}
@@ -127,7 +128,12 @@ func (d *Docs) addDocument(line []byte) error {
return err
}
- d.Entries[doc.Id] = strings.TrimPrefix(doc.Uri, d.Root)
+ relativePath, err := filepath.Rel(d.Root, doc.Uri)
+ if err != nil {
+ relativePath = doc.Uri
+ }
+
+ d.Entries[doc.Id] = relativePath
return nil
}
diff --git a/workhorse/internal/lsif_transformer/parser/docs_test.go b/workhorse/internal/lsif_transformer/parser/docs_test.go
index 24e3eba8ac5..805bc53c0b7 100644
--- a/workhorse/internal/lsif_transformer/parser/docs_test.go
+++ b/workhorse/internal/lsif_transformer/parser/docs_test.go
@@ -18,16 +18,32 @@ func TestParse(t *testing.T) {
require.NoError(t, err)
defer d.Close()
- data := []byte(`{"id":"1","label":"metaData","projectRoot":"file:///Users/nested"}` + "\n")
- data = append(data, createLine("2", "document", "file:///Users/nested/file.rb")...)
- data = append(data, createLine("3", "document", "file:///Users/nested/folder/file.rb")...)
- data = append(data, createLine("4", "document", "file:///Users/wrong/file.rb")...)
+ for _, root := range []string{
+ "file:///Users/nested",
+ "file:///Users/nested/.",
+ "file:///Users/nested/",
+ } {
+ t.Run("Document with root: "+root, func(t *testing.T) {
+ data := []byte(`{"id":"1","label":"metaData","projectRoot":"` + root + `"}` + "\n")
+ data = append(data, createLine("2", "document", "file:///Users/nested/file.rb")...)
+ data = append(data, createLine("3", "document", "file:///Users/nested/folder/file.rb")...)
- require.NoError(t, d.Parse(bytes.NewReader(data)))
+ require.NoError(t, d.Parse(bytes.NewReader(data)))
+
+ require.Equal(t, "file.rb", d.Entries[2])
+ require.Equal(t, "folder/file.rb", d.Entries[3])
+ })
+ }
+
+ t.Run("Relative path cannot be calculated", func(t *testing.T) {
+ originalUri := "file:///Users/nested/folder/file.rb"
+ data := []byte(`{"id":"1","label":"metaData","projectRoot":"/a"}` + "\n")
+ data = append(data, createLine("2", "document", originalUri)...)
+
+ require.NoError(t, d.Parse(bytes.NewReader(data)))
- require.Equal(t, d.Entries[2], "file.rb")
- require.Equal(t, d.Entries[3], "folder/file.rb")
- require.Equal(t, d.Entries[4], "file:///Users/wrong/file.rb")
+ require.Equal(t, originalUri, d.Entries[2])
+ })
}
func TestParseContainsLine(t *testing.T) {