Commit c3f24fcb authored by Mike Greiling's avatar Mike Greiling

Merge branch 'master' into 'ps-ide-defer-loading-terminal-modules'

# Conflicts:
#   doc/development/testing_guide/frontend_testing.md
parents 14d8c620 5891d8c0
...@@ -20,8 +20,7 @@ export const init = ({ dispatch }, { endpoint, logState, pagePath }) => { ...@@ -20,8 +20,7 @@ export const init = ({ dispatch }, { endpoint, logState, pagePath }) => {
logState, logState,
pagePath, pagePath,
}); });
dispatch('fetchJob');
return Promise.all([dispatch('fetchJob'), dispatch('fetchTrace')]);
}; };
export const setJobEndpoint = ({ commit }, endpoint) => commit(types.SET_JOB_ENDPOINT, endpoint); export const setJobEndpoint = ({ commit }, endpoint) => commit(types.SET_JOB_ENDPOINT, endpoint);
...@@ -39,6 +38,7 @@ export const toggleSidebar = ({ dispatch, state }) => { ...@@ -39,6 +38,7 @@ export const toggleSidebar = ({ dispatch, state }) => {
}; };
let eTagPoll; let eTagPoll;
let isTraceReadyForRender;
export const clearEtagPoll = () => { export const clearEtagPoll = () => {
eTagPoll = null; eTagPoll = null;
...@@ -70,7 +70,14 @@ export const fetchJob = ({ state, dispatch }) => { ...@@ -70,7 +70,14 @@ export const fetchJob = ({ state, dispatch }) => {
}); });
if (!Visibility.hidden()) { if (!Visibility.hidden()) {
eTagPoll.makeRequest(); // eslint-disable-next-line promise/catch-or-return
eTagPoll.makeRequest().then(() => {
// if a job is canceled we still need to dispatch
// fetchTrace to get the trace so we check for has_trace
if (state.job.started || state.job.has_trace) {
dispatch('fetchTrace');
}
});
} else { } else {
axios axios
.get(state.jobEndpoint) .get(state.jobEndpoint)
...@@ -80,9 +87,15 @@ export const fetchJob = ({ state, dispatch }) => { ...@@ -80,9 +87,15 @@ export const fetchJob = ({ state, dispatch }) => {
Visibility.change(() => { Visibility.change(() => {
if (!Visibility.hidden()) { if (!Visibility.hidden()) {
// This check is needed to ensure the loading icon
// is not shown for a finished job during a visibility change
if (!isTraceReadyForRender) {
dispatch('startPollingTrace');
}
dispatch('restartPolling'); dispatch('restartPolling');
} else { } else {
dispatch('stopPolling'); dispatch('stopPolling');
dispatch('stopPollingTrace');
} }
}); });
}; };
...@@ -163,6 +176,8 @@ export const fetchTrace = ({ dispatch, state }) => ...@@ -163,6 +176,8 @@ export const fetchTrace = ({ dispatch, state }) =>
params: { state: state.traceState }, params: { state: state.traceState },
}) })
.then(({ data }) => { .then(({ data }) => {
isTraceReadyForRender = data.complete;
dispatch('toggleScrollisInBottom', isScrolledToBottom()); dispatch('toggleScrollisInBottom', isScrolledToBottom());
dispatch('receiveTraceSuccess', data); dispatch('receiveTraceSuccess', data);
......
...@@ -49,6 +49,7 @@ export default { ...@@ -49,6 +49,7 @@ export default {
[types.SET_TRACE_TIMEOUT](state, id) { [types.SET_TRACE_TIMEOUT](state, id) {
state.traceTimeout = id; state.traceTimeout = id;
state.isTraceComplete = false;
}, },
/** /**
......
<script> <script>
import { GlPagination } from '@gitlab/ui'; import { GlKeysetPagination } from '@gitlab/ui';
import ImageListRow from './image_list_row.vue'; import ImageListRow from './image_list_row.vue';
export default { export default {
name: 'ImageList', name: 'ImageList',
components: { components: {
GlPagination, GlKeysetPagination,
ImageListRow, ImageListRow,
}, },
props: { props: {
...@@ -13,19 +13,14 @@ export default { ...@@ -13,19 +13,14 @@ export default {
type: Array, type: Array,
required: true, required: true,
}, },
pagination: { pageInfo: {
type: Object, type: Object,
required: true, required: true,
}, },
}, },
computed: { computed: {
currentPage: { showPagination() {
get() { return this.pageInfo.hasPreviousPage || this.pageInfo.hasNextPage;
return this.pagination.page;
},
set(page) {
this.$emit('pageChange', page);
},
}, },
}, },
}; };
...@@ -40,13 +35,15 @@ export default { ...@@ -40,13 +35,15 @@ export default {
:first="index === 0" :first="index === 0"
@delete="$emit('delete', $event)" @delete="$emit('delete', $event)"
/> />
<div class="gl-display-flex gl-justify-content-center">
<gl-pagination <gl-keyset-pagination
v-model="currentPage" v-if="showPagination"
:per-page="pagination.perPage" :has-next-page="pageInfo.hasNextPage"
:total-items="pagination.total" :has-previous-page="pageInfo.hasPreviousPage"
align="center" class="gl-mt-3"
class="w-100 gl-mt-3" @prev="$emit('prev-page')"
/> @next="$emit('next-page')"
/>
</div>
</div> </div>
</template> </template>
<script> <script>
import { GlTooltipDirective, GlIcon, GlSprintf } from '@gitlab/ui'; import { GlTooltipDirective, GlIcon, GlSprintf } from '@gitlab/ui';
import { n__ } from '~/locale'; import { n__ } from '~/locale';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue';
import ListItem from '~/vue_shared/components/registry/list_item.vue'; import ListItem from '~/vue_shared/components/registry/list_item.vue';
import DeleteButton from '../delete_button.vue'; import DeleteButton from '../delete_button.vue';
...@@ -11,6 +13,8 @@ import { ...@@ -11,6 +13,8 @@ import {
REMOVE_REPOSITORY_LABEL, REMOVE_REPOSITORY_LABEL,
ROW_SCHEDULED_FOR_DELETION, ROW_SCHEDULED_FOR_DELETION,
CLEANUP_TIMED_OUT_ERROR_MESSAGE, CLEANUP_TIMED_OUT_ERROR_MESSAGE,
IMAGE_DELETE_SCHEDULED_STATUS,
IMAGE_FAILED_DELETED_STATUS,
} from '../../constants/index'; } from '../../constants/index';
export default { export default {
...@@ -38,19 +42,29 @@ export default { ...@@ -38,19 +42,29 @@ export default {
}, },
computed: { computed: {
disabledDelete() { disabledDelete() {
return !this.item.destroy_path || this.item.deleting; return !this.item.canDelete || this.deleting;
},
id() {
return getIdFromGraphQLId(this.item.id);
},
deleting() {
return this.item.status === IMAGE_DELETE_SCHEDULED_STATUS;
},
failedDelete() {
return this.item.status === IMAGE_FAILED_DELETED_STATUS;
}, },
tagsCountText() { tagsCountText() {
return n__( return n__(
'ContainerRegistry|%{count} Tag', 'ContainerRegistry|%{count} Tag',
'ContainerRegistry|%{count} Tags', 'ContainerRegistry|%{count} Tags',
this.item.tags_count, this.item.tagsCount,
); );
}, },
warningIconText() { warningIconText() {
if (this.item.failedDelete) { if (this.failedDelete) {
return ASYNC_DELETE_IMAGE_ERROR_MESSAGE; return ASYNC_DELETE_IMAGE_ERROR_MESSAGE;
} else if (this.item.cleanup_policy_started_at) { }
if (this.item.expirationPolicyStartedAt) {
return CLEANUP_TIMED_OUT_ERROR_MESSAGE; return CLEANUP_TIMED_OUT_ERROR_MESSAGE;
} }
return null; return null;
...@@ -63,23 +77,23 @@ export default { ...@@ -63,23 +77,23 @@ export default {
<list-item <list-item
v-gl-tooltip="{ v-gl-tooltip="{
placement: 'left', placement: 'left',
disabled: !item.deleting, disabled: !deleting,
title: $options.i18n.ROW_SCHEDULED_FOR_DELETION, title: $options.i18n.ROW_SCHEDULED_FOR_DELETION,
}" }"
v-bind="$attrs" v-bind="$attrs"
:disabled="item.deleting" :disabled="deleting"
> >
<template #left-primary> <template #left-primary>
<router-link <router-link
class="gl-text-body gl-font-weight-bold" class="gl-text-body gl-font-weight-bold"
data-testid="details-link" data-testid="details-link"
:to="{ name: 'details', params: { id: item.id } }" :to="{ name: 'details', params: { id } }"
> >
{{ item.path }} {{ item.path }}
</router-link> </router-link>
<clipboard-button <clipboard-button
v-if="item.location" v-if="item.location"
:disabled="item.deleting" :disabled="deleting"
:text="item.location" :text="item.location"
:title="item.location" :title="item.location"
category="tertiary" category="tertiary"
...@@ -97,7 +111,7 @@ export default { ...@@ -97,7 +111,7 @@ export default {
<gl-icon name="tag" class="gl-mr-2" /> <gl-icon name="tag" class="gl-mr-2" />
<gl-sprintf :message="tagsCountText"> <gl-sprintf :message="tagsCountText">
<template #count> <template #count>
{{ item.tags_count }} {{ item.tagsCount }}
</template> </template>
</gl-sprintf> </gl-sprintf>
</span> </span>
...@@ -106,7 +120,7 @@ export default { ...@@ -106,7 +120,7 @@ export default {
<delete-button <delete-button
:title="$options.i18n.REMOVE_REPOSITORY_LABEL" :title="$options.i18n.REMOVE_REPOSITORY_LABEL"
:disabled="disabledDelete" :disabled="disabledDelete"
:tooltip-disabled="Boolean(item.destroy_path)" :tooltip-disabled="item.canDelete"
:tooltip-title="$options.i18n.LIST_DELETE_BUTTON_DISABLED" :tooltip-title="$options.i18n.LIST_DELETE_BUTTON_DISABLED"
@delete="$emit('delete', item)" @delete="$emit('delete', item)"
/> />
......
...@@ -44,5 +44,6 @@ export const EMPTY_RESULT_MESSAGE = s__( ...@@ -44,5 +44,6 @@ export const EMPTY_RESULT_MESSAGE = s__(
// Parameters // Parameters
export const IMAGE_DELETE_SCHEDULED_STATUS = 'delete_scheduled'; export const IMAGE_DELETE_SCHEDULED_STATUS = 'DELETE_SCHEDULED';
export const IMAGE_FAILED_DELETED_STATUS = 'delete_failed'; export const IMAGE_FAILED_DELETED_STATUS = 'DELETE_FAILED';
export const GRAPHQL_PAGE_SIZE = 10;
fragment ContainerRepositoryFields on ContainerRepository {
id
name
path
status
location
canDelete
createdAt
tagsCount
expirationPolicyStartedAt
}
import Vue from 'vue';
import VueApollo from 'vue-apollo';
import createDefaultClient from '~/lib/graphql';
Vue.use(VueApollo);
export const apolloProvider = new VueApollo({
defaultClient: createDefaultClient(
{},
{
assumeImmutableResults: true,
},
),
});
mutation destroyContainerRepository($id: ContainerRepositoryID!) {
destroyContainerRepository(input: { id: $id }) {
containerRepository {
id
status
}
errors
}
}
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
#import "../fragments/container_repository.fragment.graphql"
query getProjectContainerRepositories(
$fullPath: ID!
$name: String
$first: Int
$last: Int
$after: String
$before: String
) {
group(fullPath: $fullPath) {
containerRepositoriesCount
containerRepositories(name: $name, after: $after, before: $before, first: $first, last: $last) {
nodes {
...ContainerRepositoryFields
}
pageInfo {
...PageInfo
}
}
}
}
#import "~/graphql_shared/fragments/pageInfo.fragment.graphql"
#import "../fragments/container_repository.fragment.graphql"
query getProjectContainerRepositories(
$fullPath: ID!
$name: String
$first: Int
$last: Int
$after: String
$before: String
) {
project(fullPath: $fullPath) {
containerRepositoriesCount
containerRepositories(name: $name, after: $after, before: $before, first: $first, last: $last) {
nodes {
...ContainerRepositoryFields
}
pageInfo {
...PageInfo
}
}
}
}
...@@ -5,6 +5,7 @@ import RegistryExplorer from './pages/index.vue'; ...@@ -5,6 +5,7 @@ import RegistryExplorer from './pages/index.vue';
import RegistryBreadcrumb from './components/registry_breadcrumb.vue'; import RegistryBreadcrumb from './components/registry_breadcrumb.vue';
import { createStore } from './stores'; import { createStore } from './stores';
import createRouter from './router'; import createRouter from './router';
import { apolloProvider } from './graphql/index';
Vue.use(Translate); Vue.use(Translate);
Vue.use(GlToast); Vue.use(GlToast);
...@@ -27,6 +28,7 @@ export default () => { ...@@ -27,6 +28,7 @@ export default () => {
el, el,
store, store,
router, router,
apolloProvider,
components: { components: {
RegistryExplorer, RegistryExplorer,
}, },
......
<script> <script>
import { mapState, mapActions } from 'vuex'; import { mapState } from 'vuex';
import { import {
GlEmptyState, GlEmptyState,
GlTooltipDirective, GlTooltipDirective,
...@@ -11,6 +11,7 @@ import { ...@@ -11,6 +11,7 @@ import {
GlSearchBoxByClick, GlSearchBoxByClick,
} from '@gitlab/ui'; } from '@gitlab/ui';
import Tracking from '~/tracking'; import Tracking from '~/tracking';
import createFlash from '~/flash';
import ProjectEmptyState from '../components/list_page/project_empty_state.vue'; import ProjectEmptyState from '../components/list_page/project_empty_state.vue';
import GroupEmptyState from '../components/list_page/group_empty_state.vue'; import GroupEmptyState from '../components/list_page/group_empty_state.vue';
...@@ -18,6 +19,10 @@ import RegistryHeader from '../components/list_page/registry_header.vue'; ...@@ -18,6 +19,10 @@ import RegistryHeader from '../components/list_page/registry_header.vue';
import ImageList from '../components/list_page/image_list.vue'; import ImageList from '../components/list_page/image_list.vue';
import CliCommands from '../components/list_page/cli_commands.vue'; import CliCommands from '../components/list_page/cli_commands.vue';
import getProjectContainerRepositories from '../graphql/queries/get_project_container_repositories.graphql';
import getGroupContainerRepositories from '../graphql/queries/get_group_container_repositories.graphql';
import deleteContainerRepository from '../graphql/mutations/delete_container_repository.graphql';
import { import {
DELETE_IMAGE_SUCCESS_MESSAGE, DELETE_IMAGE_SUCCESS_MESSAGE,
DELETE_IMAGE_ERROR_MESSAGE, DELETE_IMAGE_ERROR_MESSAGE,
...@@ -29,6 +34,8 @@ import { ...@@ -29,6 +34,8 @@ import {
IMAGE_REPOSITORY_LIST_LABEL, IMAGE_REPOSITORY_LIST_LABEL,
EMPTY_RESULT_TITLE, EMPTY_RESULT_TITLE,
EMPTY_RESULT_MESSAGE, EMPTY_RESULT_MESSAGE,
GRAPHQL_PAGE_SIZE,
FETCH_IMAGES_LIST_ERROR_MESSAGE,
} from '../constants/index'; } from '../constants/index';
export default { export default {
...@@ -66,21 +73,63 @@ export default { ...@@ -66,21 +73,63 @@ export default {
EMPTY_RESULT_TITLE, EMPTY_RESULT_TITLE,
EMPTY_RESULT_MESSAGE, EMPTY_RESULT_MESSAGE,
}, },
apollo: {
images: {
query() {
return this.graphQlQuery;
},
variables() {
return this.queryVariables;
},
update(data) {
return data[this.graphqlResource]?.containerRepositories.nodes;
},
result({ data }) {
this.pageInfo = data[this.graphqlResource]?.containerRepositories?.pageInfo;
this.containerRepositoriesCount = data[this.graphqlResource]?.containerRepositoriesCount;
},
error() {
createFlash({ message: FETCH_IMAGES_LIST_ERROR_MESSAGE });
},
},
},
data() { data() {
return { return {
images: [],
pageInfo: {},
containerRepositoriesCount: 0,
itemToDelete: {}, itemToDelete: {},
deleteAlertType: null, deleteAlertType: null,
search: null, searchValue: null,
isEmpty: false, name: null,
mutationLoading: false,
}; };
}, },
computed: { computed: {
...mapState(['config', 'isLoading', 'images', 'pagination']), ...mapState(['config']),
graphqlResource() {
return this.config.isGroupPage ? 'group' : 'project';
},
graphQlQuery() {
return this.config.isGroupPage
? getGroupContainerRepositories
: getProjectContainerRepositories;
},
queryVariables() {
return {
name: this.name,
fullPath: this.config.isGroupPage ? this.config.groupPath : this.config.projectPath,
first: GRAPHQL_PAGE_SIZE,
};
},
tracking() { tracking() {
return { return {
label: 'registry_repository_delete', label: 'registry_repository_delete',
}; };
}, },
isLoading() {
return this.$apollo.queries.images.loading || this.mutationLoading;
},
showCommands() { showCommands() {
return Boolean(!this.isLoading && !this.config?.isGroupPage && this.images?.length); return Boolean(!this.isLoading && !this.config?.isGroupPage && this.images?.length);
}, },
...@@ -93,19 +142,7 @@ export default { ...@@ -93,19 +142,7 @@ export default {
: DELETE_IMAGE_ERROR_MESSAGE; : DELETE_IMAGE_ERROR_MESSAGE;
}, },
}, },
mounted() {
this.loadImageList(this.$route.name);
},
methods: { methods: {
...mapActions(['requestImagesList', 'requestDeleteImage']),
loadImageList(fromName) {
if (!fromName || !this.images?.length) {
return this.requestImagesList().then(() => {
this.isEmpty = this.images.length === 0;
});
}
return Promise.resolve();
},
deleteImage(item) { deleteImage(item) {
this.track('click_button'); this.track('click_button');
this.itemToDelete = item; this.itemToDelete = item;
...@@ -113,18 +150,59 @@ export default { ...@@ -113,18 +150,59 @@ export default {
}, },
handleDeleteImage() { handleDeleteImage() {
this.track('confirm_delete'); this.track('confirm_delete');
return this.requestDeleteImage(this.itemToDelete) this.mutationLoading = true;
.then(() => { return this.$apollo
this.deleteAlertType = 'success'; .mutate({
mutation: deleteContainerRepository,
variables: {
id: this.itemToDelete.id,
},
})
.then(({ data }) => {
if (data?.destroyContainerRepository?.errors[0]) {
this.deleteAlertType = 'danger';
} else {
this.deleteAlertType = 'success';
}
}) })
.catch(() => { .catch(() => {
this.deleteAlertType = 'danger'; this.deleteAlertType = 'danger';
})
.finally(() => {
this.mutationLoading = false;
}); });
}, },
dismissDeleteAlert() { dismissDeleteAlert() {
this.deleteAlertType = null; this.deleteAlertType = null;
this.itemToDelete = {}; this.itemToDelete = {};
}, },
fetchNextPage() {
if (this.pageInfo?.hasNextPage) {
this.$apollo.queries.images.fetchMore({
variables: {
after: this.pageInfo?.endCursor,
first: GRAPHQL_PAGE_SIZE,
},
updateQuery(previousResult, { fetchMoreResult }) {
return fetchMoreResult;
},
});
}
},
fetchPreviousPage() {
if (this.pageInfo?.hasPreviousPage) {
this.$apollo.queries.images.fetchMore({
variables: {
first: null,
before: this.pageInfo?.startCursor,
last: GRAPHQL_PAGE_SIZE,
},
updateQuery(previousResult, { fetchMoreResult }) {
return fetchMoreResult;
},
});
}
},
}, },
}; };
</script> </script>
...@@ -134,7 +212,7 @@ export default { ...@@ -134,7 +212,7 @@ export default {
<gl-alert <gl-alert
v-if="showDeleteAlert" v-if="showDeleteAlert"
:variant="deleteAlertType" :variant="deleteAlertType"
class="mt-2" class="gl-mt-5"
dismissible dismissible
@dismiss="dismissDeleteAlert" @dismiss="dismissDeleteAlert"
> >
...@@ -165,7 +243,7 @@ export default { ...@@ -165,7 +243,7 @@ export default {
<template v-else> <template v-else>
<registry-header <registry-header
:images-count="pagination.total" :images-count="containerRepositoriesCount"
:expiration-policy="config.expirationPolicy" :expiration-policy="config.expirationPolicy"
:help-page-path="config.helpPagePath" :help-page-path="config.helpPagePath"
:expiration-policy-help-page-path="config.expirationPolicyHelpPagePath" :expiration-policy-help-page-path="config.expirationPolicyHelpPagePath"
...@@ -176,7 +254,7 @@ export default { ...@@ -176,7 +254,7 @@ export default {
</template> </template>
</registry-header> </registry-header>
<div v-if="isLoading" class="mt-2"> <div v-if="isLoading" class="gl-mt-5">
<gl-skeleton-loader <gl-skeleton-loader
v-for="index in $options.loader.repeat" v-for="index in $options.loader.repeat"
:key="index" :key="index"
...@@ -190,16 +268,17 @@ export default { ...@@ -190,16 +268,17 @@ export default {
</gl-skeleton-loader> </gl-skeleton-loader>
</div> </div>
<template v-else> <template v-else>
<template v-if="!isEmpty"> <template v-if="images.length > 0 || name">
<div class="gl-display-flex gl-p-1 gl-mt-3" data-testid="listHeader"> <div class="gl-display-flex gl-p-1 gl-mt-3" data-testid="listHeader">
<div class="gl-flex-fill-1"> <div class="gl-flex-fill-1">
<h5>{{ $options.i18n.IMAGE_REPOSITORY_LIST_LABEL }}</h5> <h5>{{ $options.i18n.IMAGE_REPOSITORY_LIST_LABEL }}</h5>
</div> </div>
<div> <div>
<gl-search-box-by-click <gl-search-box-by-click
v-model="search" v-model="searchValue"
:placeholder="$options.i18n.SEARCH_PLACEHOLDER_TEXT" :placeholder="$options.i18n.SEARCH_PLACEHOLDER_TEXT"
@submit="requestImagesList({ name: $event })" @clear="name = null"
@submit="name = $event"
/> />
</div> </div>
</div> </div>
...@@ -207,9 +286,10 @@ export default { ...@@ -207,9 +286,10 @@ export default {
<image-list <image-list
v-if="images.length" v-if="images.length"
:images="images" :images="images"
:pagination="pagination" :page-info="pageInfo"
@pageChange="requestImagesList({ pagination: { page: $event }, name: search })"
@delete="deleteImage" @delete="deleteImage"
@prev-page="fetchPreviousPage"
@next-page="fetchNextPage"
/> />
<gl-empty-state <gl-empty-state
......
...@@ -11,7 +11,7 @@ module Mutations ...@@ -11,7 +11,7 @@ module Mutations
argument :iid, GraphQL::STRING_TYPE, argument :iid, GraphQL::STRING_TYPE,
required: true, required: true,
description: "The iid of the alert to mutate" description: "The IID of the alert to mutate"
field :alert, field :alert,
Types::AlertManagement::AlertType, Types::AlertManagement::AlertType,
......
...@@ -8,7 +8,7 @@ module Mutations ...@@ -8,7 +8,7 @@ module Mutations
argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration], argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
required: true, required: true,
description: "The id of the integration to remove" description: "The ID of the integration to remove"
def resolve(id:) def resolve(id:)
integration = authorized_find!(id: id) integration = authorized_find!(id: id)
......
...@@ -8,7 +8,7 @@ module Mutations ...@@ -8,7 +8,7 @@ module Mutations
argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration], argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
required: true, required: true,
description: "The id of the integration to mutate" description: "The ID of the integration to mutate"
def resolve(id:) def resolve(id:)
integration = authorized_find!(id: id) integration = authorized_find!(id: id)
......
...@@ -8,7 +8,7 @@ module Mutations ...@@ -8,7 +8,7 @@ module Mutations
argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration], argument :id, Types::GlobalIDType[::AlertManagement::HttpIntegration],
required: true, required: true,
description: "The id of the integration to mutate" description: "The ID of the integration to mutate"
argument :name, GraphQL::STRING_TYPE, argument :name, GraphQL::STRING_TYPE,
required: false, required: false,
......
...@@ -8,7 +8,7 @@ module Mutations ...@@ -8,7 +8,7 @@ module Mutations
argument :id, Types::GlobalIDType[::PrometheusService], argument :id, Types::GlobalIDType[::PrometheusService],
required: true, required: true,
description: "The id of the integration to mutate" description: "The ID of the integration to mutate"
def resolve(id:) def resolve(id:)
integration = authorized_find!(id: id) integration = authorized_find!(id: id)
......
...@@ -8,7 +8,7 @@ module Mutations ...@@ -8,7 +8,7 @@ module Mutations
argument :id, Types::GlobalIDType[::PrometheusService], argument :id, Types::GlobalIDType[::PrometheusService],
required: true, required: true,
description: "The id of the integration to mutate" description: "The ID of the integration to mutate"
argument :active, GraphQL::BOOLEAN_TYPE, argument :active, GraphQL::BOOLEAN_TYPE,
required: false, required: false,
......
...@@ -12,7 +12,7 @@ module Mutations ...@@ -12,7 +12,7 @@ module Mutations
argument :awardable_id, argument :awardable_id,
::Types::GlobalIDType[::Awardable], ::Types::GlobalIDType[::Awardable],
required: true, required: true,
description: 'The global id of the awardable resource' description: 'The global ID of the awardable resource'
argument :name, argument :name,
GraphQL::STRING_TYPE, GraphQL::STRING_TYPE,
......
...@@ -7,7 +7,7 @@ module Mutations ...@@ -7,7 +7,7 @@ module Mutations
argument :id, PipelineID, argument :id, PipelineID,
required: true, required: true,
description: 'The id of the pipeline to mutate' description: 'The ID of the pipeline to mutate'
private private
......
...@@ -11,7 +11,7 @@ module Mutations ...@@ -11,7 +11,7 @@ module Mutations
argument :iid, GraphQL::ID_TYPE, argument :iid, GraphQL::ID_TYPE,
required: true, required: true,
description: "The iid of the issue to modify designs for" description: "The IID of the issue to modify designs for"
private private
......
...@@ -10,7 +10,7 @@ module Mutations ...@@ -10,7 +10,7 @@ module Mutations
argument :id, argument :id,
Types::GlobalIDType[Discussion], Types::GlobalIDType[Discussion],
required: true, required: true,
description: 'The global id of the discussion' description: 'The global ID of the discussion'
argument :resolve, argument :resolve,
GraphQL::BOOLEAN_TYPE, GraphQL::BOOLEAN_TYPE,
......
...@@ -11,7 +11,7 @@ module Mutations ...@@ -11,7 +11,7 @@ module Mutations
argument :iid, GraphQL::STRING_TYPE, argument :iid, GraphQL::STRING_TYPE,
required: true, required: true,
description: "The iid of the merge request to mutate" description: "The IID of the merge request to mutate"
field :merge_request, field :merge_request,
Types::MergeRequestType, Types::MergeRequestType,
......
...@@ -20,12 +20,12 @@ module Mutations ...@@ -20,12 +20,12 @@ module Mutations
argument :environment_id, argument :environment_id,
::Types::GlobalIDType[::Environment], ::Types::GlobalIDType[::Environment],
required: false, required: false,
description: 'The global id of the environment to add an annotation to' description: 'The global ID of the environment to add an annotation to'
argument :cluster_id, argument :cluster_id,
::Types::GlobalIDType[::Clusters::Cluster], ::Types::GlobalIDType[::Clusters::Cluster],
required: false, required: false,
description: 'The global id of the cluster to add an annotation to' description: 'The global ID of the cluster to add an annotation to'
argument :starting_at, Types::TimeType, argument :starting_at, Types::TimeType,
required: true, required: true,
......
...@@ -11,7 +11,7 @@ module Mutations ...@@ -11,7 +11,7 @@ module Mutations
argument :noteable_id, argument :noteable_id,
::Types::GlobalIDType[::Noteable], ::Types::GlobalIDType[::Noteable],
required: true, required: true,
description: 'The global id of the resource to add a note to' description: 'The global ID of the resource to add a note to'
argument :body, argument :body,
GraphQL::STRING_TYPE, GraphQL::STRING_TYPE,
......
...@@ -9,7 +9,7 @@ module Mutations ...@@ -9,7 +9,7 @@ module Mutations
argument :discussion_id, argument :discussion_id,
::Types::GlobalIDType[::Discussion], ::Types::GlobalIDType[::Discussion],
required: false, required: false,
description: 'The global id of the discussion this note is in reply to' description: 'The global ID of the discussion this note is in reply to'
private private
......
...@@ -10,7 +10,7 @@ module Mutations ...@@ -10,7 +10,7 @@ module Mutations
argument :id, argument :id,
::Types::GlobalIDType[::Note], ::Types::GlobalIDType[::Note],
required: true, required: true,
description: 'The global id of the note to destroy' description: 'The global ID of the note to destroy'
def resolve(id:) def resolve(id:)
note = authorized_find!(id: id) note = authorized_find!(id: id)
......
...@@ -16,7 +16,7 @@ module Mutations ...@@ -16,7 +16,7 @@ module Mutations
loads: Types::Notes::NoteType, loads: Types::Notes::NoteType,
as: :note, as: :note,
required: true, required: true,
description: 'The global id of the DiffNote to update' description: 'The global ID of the DiffNote to update'
argument :position, argument :position,
Types::Notes::UpdateDiffImagePositionInputType, Types::Notes::UpdateDiffImagePositionInputType,
......
...@@ -11,7 +11,7 @@ module Mutations ...@@ -11,7 +11,7 @@ module Mutations
argument :id, argument :id,
::Types::GlobalIDType[::Note], ::Types::GlobalIDType[::Note],
required: true, required: true,
description: 'The global id of the note to update' description: 'The global ID of the note to update'
def resolve(args) def resolve(args)
note = authorized_find!(id: args[:id]) note = authorized_find!(id: args[:id])
......
...@@ -9,7 +9,7 @@ module Mutations ...@@ -9,7 +9,7 @@ module Mutations
argument :id, ::Types::GlobalIDType[::Snippet], argument :id, ::Types::GlobalIDType[::Snippet],
required: true, required: true,
description: 'The global id of the snippet to destroy' description: 'The global ID of the snippet to destroy'
def resolve(id:) def resolve(id:)
snippet = authorized_find!(id: id) snippet = authorized_find!(id: id)
......
...@@ -7,7 +7,7 @@ module Mutations ...@@ -7,7 +7,7 @@ module Mutations
argument :id, ::Types::GlobalIDType[::Snippet], argument :id, ::Types::GlobalIDType[::Snippet],
required: true, required: true,
description: 'The global id of the snippet to update' description: 'The global ID of the snippet to update'
def resolve(id:) def resolve(id:)
snippet = authorized_find!(id: id) snippet = authorized_find!(id: id)
......
...@@ -9,7 +9,7 @@ module Mutations ...@@ -9,7 +9,7 @@ module Mutations
argument :id, ::Types::GlobalIDType[::Snippet], argument :id, ::Types::GlobalIDType[::Snippet],
required: true, required: true,
description: 'The global id of the snippet to update' description: 'The global ID of the snippet to update'
argument :title, GraphQL::STRING_TYPE, argument :title, GraphQL::STRING_TYPE,
required: false, required: false,
......
...@@ -10,7 +10,7 @@ module Mutations ...@@ -10,7 +10,7 @@ module Mutations
argument :id, argument :id,
::Types::GlobalIDType[::Todo], ::Types::GlobalIDType[::Todo],
required: true, required: true,
description: 'The global id of the todo to mark as done' description: 'The global ID of the todo to mark as done'
field :todo, Types::TodoType, field :todo, Types::TodoType,
null: false, null: false,
......
...@@ -10,7 +10,7 @@ module Mutations ...@@ -10,7 +10,7 @@ module Mutations
argument :id, argument :id,
::Types::GlobalIDType[::Todo], ::Types::GlobalIDType[::Todo],
required: true, required: true,
description: 'The global id of the todo to restore' description: 'The global ID of the todo to restore'
field :todo, Types::TodoType, field :todo, Types::TodoType,
null: false, null: false,
......
...@@ -10,11 +10,11 @@ module Mutations ...@@ -10,11 +10,11 @@ module Mutations
argument :ids, argument :ids,
[::Types::GlobalIDType[::Todo]], [::Types::GlobalIDType[::Todo]],
required: true, required: true,
description: 'The global ids of the todos to restore (a maximum of 50 is supported at once)' description: 'The global IDs of the todos to restore (a maximum of 50 is supported at once)'
field :updated_ids, [::Types::GlobalIDType[Todo]], field :updated_ids, [::Types::GlobalIDType[Todo]],
null: false, null: false,
description: 'The ids of the updated todo items', description: 'The IDs of the updated todo items',
deprecated: { reason: 'Use todos', milestone: '13.2' } deprecated: { reason: 'Use todos', milestone: '13.2' }
field :todos, [::Types::TodoType], field :todos, [::Types::TodoType],
......
...@@ -8,7 +8,7 @@ module Types ...@@ -8,7 +8,7 @@ module Types
argument :jira_account_id, argument :jira_account_id,
GraphQL::STRING_TYPE, GraphQL::STRING_TYPE,
required: true, required: true,
description: 'Jira account id of the user' description: 'Jira account ID of the user'
argument :gitlab_id, argument :gitlab_id,
GraphQL::INT_TYPE, GraphQL::INT_TYPE,
required: false, required: false,
......
...@@ -16,4 +16,5 @@ ...@@ -16,4 +16,5 @@
"cleanup_policies_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'how-the-cleanup-policy-works'), "cleanup_policies_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'how-the-cleanup-policy-works'),
"is_admin": current_user&.admin.to_s, "is_admin": current_user&.admin.to_s,
is_group_page: "true", is_group_page: "true",
"group_path": @group.full_path,
character_error: @character_error.to_s } } character_error: @character_error.to_s } }
...@@ -17,6 +17,6 @@ ...@@ -17,6 +17,6 @@
"garbage_collection_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'container-registry-garbage-collection'), "garbage_collection_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'container-registry-garbage-collection'),
"run_cleanup_policies_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'run-the-cleanup-policy-now'), "run_cleanup_policies_help_page_path" => help_page_path('administration/packages/container_registry', anchor: 'run-the-cleanup-policy-now'),
"cleanup_policies_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'how-the-cleanup-policy-works'), "cleanup_policies_help_page_path" => help_page_path('user/packages/container_registry/index', anchor: 'how-the-cleanup-policy-works'),
"project_path": @project.full_path,
"is_admin": current_user&.admin.to_s, "is_admin": current_user&.admin.to_s,
character_error: @character_error.to_s } } character_error: @character_error.to_s } }
---
title: Refactor container registry list page to grapqhl
merge_request: 48602
author:
type: changed
---
title: Update template to use codequality 0.85.18-gitlab.1
merge_request: 49034
author:
type: changed
---
title: Ensure job trace endpoint is not called if the current job has not started or the browser is not visible
merge_request: 48516
author:
type: fixed
...@@ -484,6 +484,7 @@ sudo ...@@ -484,6 +484,7 @@ sudo
swimlane swimlane
swimlanes swimlanes
syslog syslog
tanuki
tcpdump tcpdump
Thanos Thanos
Tiller Tiller
......
...@@ -133,7 +133,7 @@ you will need to follow the Consul [outage recovery](#outage-recovery) process. ...@@ -133,7 +133,7 @@ you will need to follow the Consul [outage recovery](#outage-recovery) process.
To be safe, it's recommended that you only restart Consul in one node at a time to To be safe, it's recommended that you only restart Consul in one node at a time to
ensure the cluster remains intact. For larger clusters, it is possible to restart ensure the cluster remains intact. For larger clusters, it is possible to restart
multiple nodes at a time. See the multiple nodes at a time. See the
[Consul consensus document](https://www.consul.io/docs/internals/consensus.html#deployment-table) [Consul consensus document](https://www.consul.io/docs/architecture/consensus#deployment-table)
for how many failures it can tolerate. This will be the number of simultaneous for how many failures it can tolerate. This will be the number of simultaneous
restarts it can sustain. restarts it can sustain.
......
...@@ -167,7 +167,7 @@ When the list of hosts is updated, it might take a while for the old connections ...@@ -167,7 +167,7 @@ When the list of hosts is updated, it might take a while for the old connections
to be terminated. The `disconnect_timeout` setting can be used to enforce an to be terminated. The `disconnect_timeout` setting can be used to enforce an
upper limit on the time it will take to terminate all old database connections. upper limit on the time it will take to terminate all old database connections.
Some nameservers (like [Consul](https://www.consul.io/docs/agent/dns.html#udp-based-dns-queries)) can return a truncated list of hosts when Some nameservers (like [Consul](https://www.consul.io/docs/discovery/dns#udp-based-dns-queries)) can return a truncated list of hosts when
queried over UDP. To overcome this issue, you can use TCP for querying by setting queried over UDP. To overcome this issue, you can use TCP for querying by setting
`use_tcp` to `true`. `use_tcp` to `true`.
......
...@@ -144,7 +144,7 @@ package (highly recommended), follow the steps below: ...@@ -144,7 +144,7 @@ package (highly recommended), follow the steps below:
Before beginning, you should already have a working GitLab instance. [Learn how Before beginning, you should already have a working GitLab instance. [Learn how
to install GitLab](https://about.gitlab.com/install/). to install GitLab](https://about.gitlab.com/install/).
Provision a PostgreSQL server (PostgreSQL 11 or newer). Provision a PostgreSQL server (PostgreSQL 11 or newer).
Prepare all your new nodes by [installing Prepare all your new nodes by [installing
GitLab](https://about.gitlab.com/install/). GitLab](https://about.gitlab.com/install/).
......
...@@ -185,7 +185,7 @@ Feature.enable(:ci_enable_live_trace) ...@@ -185,7 +185,7 @@ Feature.enable(:ci_enable_live_trace)
``` ```
NOTE: **Note:** NOTE: **Note:**
The transition period is handled gracefully. Upcoming logs are The transition period is handled gracefully. Upcoming logs are
generated with the incremental architecture, and on-going logs stay with the generated with the incremental architecture, and on-going logs stay with the
legacy architecture, which means that on-going logs aren't forcibly legacy architecture, which means that on-going logs aren't forcibly
re-generated with the incremental architecture. re-generated with the incremental architecture.
......
...@@ -55,7 +55,7 @@ guides you through the process. ...@@ -55,7 +55,7 @@ guides you through the process.
NOTE: **Note:** NOTE: **Note:**
After the Packages feature is enabled, the repositories are available After the Packages feature is enabled, the repositories are available
for all new projects by default. To enable it for existing projects, users for all new projects by default. To enable it for existing projects, users
explicitly do so in the project's settings. explicitly do so in the project's settings.
To enable the Packages feature: To enable the Packages feature:
......
...@@ -94,7 +94,7 @@ Upload a logo to your GitLab instance. ...@@ -94,7 +94,7 @@ Upload a logo to your GitLab instance.
To upload an avatar from your file system, use the `--form` argument. This causes To upload an avatar from your file system, use the `--form` argument. This causes
cURL to post data using the header `Content-Type: multipart/form-data`. The cURL to post data using the header `Content-Type: multipart/form-data`. The
`file=` parameter must point to an image file on your file system and be `file=` parameter must point to an image file on your file system and be
preceded by `@`. preceded by `@`.
```plaintext ```plaintext
......
...@@ -31,7 +31,7 @@ The following outline re-uses the [maturity metric](https://about.gitlab.com/dir ...@@ -31,7 +31,7 @@ The following outline re-uses the [maturity metric](https://about.gitlab.com/dir
The initial step for integrating a new component with GitLab starts with creating a [Feature proposal in the issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20proposal). The initial step for integrating a new component with GitLab starts with creating a [Feature proposal in the issue tracker](https://gitlab.com/gitlab-org/gitlab/-/issues/new?issuable_template=Feature%20proposal).
Identify the [product category](https://about.gitlab.com/handbook/product/categories/) the component falls under and assign the Engineering Manager and Product Manager responsible for that category. Identify the [product category](https://about.gitlab.com/handbook/product/product-categories/) the component falls under and assign the Engineering Manager and Product Manager responsible for that category.
The general steps for getting any GitLab feature from proposal to release can be found in the [Product development flow](https://about.gitlab.com/handbook/product-development-flow/). The general steps for getting any GitLab feature from proposal to release can be found in the [Product development flow](https://about.gitlab.com/handbook/product-development-flow/).
......
...@@ -33,7 +33,7 @@ The agent can help you perform tasks like these: ...@@ -33,7 +33,7 @@ The agent can help you perform tasks like these:
## Architecture of the Kubernetes Agent ## Architecture of the Kubernetes Agent
The GitLab Kubernetes Agent and the GitLab Kubernetes Agent Server use The GitLab Kubernetes Agent and the GitLab Kubernetes Agent Server use
[bidirectional streaming](https://grpc.io/docs/guides/concepts/#bidirectional-streaming-rpc) [bidirectional streaming](https://grpc.io/docs/what-is-grpc/core-concepts/#bidirectional-streaming-rpc)
to allow the connection acceptor (the gRPC server, GitLab Kubernetes Agent Server) to to allow the connection acceptor (the gRPC server, GitLab Kubernetes Agent Server) to
act as a client. The connection acceptor sends requests as gRPC replies. The client-server act as a client. The connection acceptor sends requests as gRPC replies. The client-server
relationship is inverted because the connection must be initiated from inside the relationship is inverted because the connection must be initiated from inside the
......
...@@ -47,7 +47,7 @@ the `author` field. GitLab team members **should not**. ...@@ -47,7 +47,7 @@ the `author` field. GitLab team members **should not**.
- Any user-facing change **must** have a changelog entry. This includes both visual changes (regardless of how minor), and changes to the rendered DOM which impact how a screen reader may announce the content. - Any user-facing change **must** have a changelog entry. This includes both visual changes (regardless of how minor), and changes to the rendered DOM which impact how a screen reader may announce the content.
- Any client-facing change to our REST and GraphQL APIs **must** have a changelog entry. - Any client-facing change to our REST and GraphQL APIs **must** have a changelog entry.
- Performance improvements **should** have a changelog entry. - Performance improvements **should** have a changelog entry.
- Changes that need to be documented in the Product Analytics [Event Dictionary](https://about.gitlab.com/handbook/product/product-analytics-guide#event-dictionary) - Changes that need to be documented in the Product Analytics [Event Dictionary](https://about.gitlab.com/handbook/product/product-analytics-guide/#event-dictionary)
also require a changelog entry. also require a changelog entry.
- _Any_ contribution from a community member, no matter how small, **may** have - _Any_ contribution from a community member, no matter how small, **may** have
a changelog entry regardless of these guidelines if the contributor wants one. a changelog entry regardless of these guidelines if the contributor wants one.
...@@ -55,7 +55,7 @@ the `author` field. GitLab team members **should not**. ...@@ -55,7 +55,7 @@ the `author` field. GitLab team members **should not**.
- Any docs-only changes **should not** have a changelog entry. - Any docs-only changes **should not** have a changelog entry.
- Any change behind a disabled feature flag **should not** have a changelog entry. - Any change behind a disabled feature flag **should not** have a changelog entry.
- Any change behind an enabled feature flag **should** have a changelog entry. - Any change behind an enabled feature flag **should** have a changelog entry.
- Any change that adds new usage data metrics and changes that needs to be documented in Product Analytics [Event Dictionary](https://about.gitlab.com/handbook/product/product-analytics-guide#event-dictionary) **should** have a changelog entry. - Any change that adds new usage data metrics and changes that needs to be documented in Product Analytics [Event Dictionary](https://about.gitlab.com/handbook/product/product-analytics-guide/#event-dictionary) **should** have a changelog entry.
- A change that adds snowplow events **should** have a changelog entry - - A change that adds snowplow events **should** have a changelog entry -
- A change that [removes a feature flag](feature_flags/development.md) **should** have a changelog entry - - A change that [removes a feature flag](feature_flags/development.md) **should** have a changelog entry -
only if the feature flag did not default to true already. only if the feature flag did not default to true already.
......
...@@ -107,7 +107,7 @@ Rendered example: ...@@ -107,7 +107,7 @@ Rendered example:
## cURL Examples ## cURL Examples
The following sections include a set of [cURL](https://curl.haxx.se) examples The following sections include a set of [cURL](https://curl.se/) examples
you can use in the API documentation. you can use in the API documentation.
CAUTION: **Caution:** CAUTION: **Caution:**
......
...@@ -533,7 +533,9 @@ tenses, words, and phrases: ...@@ -533,7 +533,9 @@ tenses, words, and phrases:
content is accessible to more readers. content is accessible to more readers.
- Don't write in the first person singular. - Don't write in the first person singular.
(Tested in [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml).) (Tested in [`FirstPerson.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FirstPerson.yml).)
<!-- vale gitlab.FirstPerson = NO -->
- Instead of _I_ or _me_, use _we_, _you_, _us_, or _one_. - Instead of _I_ or _me_, use _we_, _you_, _us_, or _one_.
<!-- vale gitlab.FirstPerson = YES -->
- When possible, stay user focused by writing in the second person (_you_ or - When possible, stay user focused by writing in the second person (_you_ or
the imperative). the imperative).
- Don't overuse "that". In many cases, you can remove "that" from a sentence - Don't overuse "that". In many cases, you can remove "that" from a sentence
...@@ -795,6 +797,8 @@ Items nested in lists should always align with the first character of the list ...@@ -795,6 +797,8 @@ Items nested in lists should always align with the first character of the list
item. In unordered lists (using `-`), this means two spaces for each level of item. In unordered lists (using `-`), this means two spaces for each level of
indentation: indentation:
<!-- vale off -->
````markdown ````markdown
- Unordered list item 1 - Unordered list item 1
...@@ -816,8 +820,12 @@ indentation: ...@@ -816,8 +820,12 @@ indentation:
![an image that will nest inside list item 4](image.png) ![an image that will nest inside list item 4](image.png)
```` ````
<!-- vale on -->
For ordered lists, use three spaces for each level of indentation: For ordered lists, use three spaces for each level of indentation:
<!-- vale off -->
````markdown ````markdown
1. Ordered list item 1 1. Ordered list item 1
...@@ -839,6 +847,8 @@ For ordered lists, use three spaces for each level of indentation: ...@@ -839,6 +847,8 @@ For ordered lists, use three spaces for each level of indentation:
![an image that will nest inside list item 4](image.png) ![an image that will nest inside list item 4](image.png)
```` ````
<!-- vale on -->
You can nest full lists inside other lists using the same rules as above. If you You can nest full lists inside other lists using the same rules as above. If you
want to mix types, that's also possible, if you don't mix items at the same want to mix types, that's also possible, if you don't mix items at the same
level: level:
...@@ -904,7 +914,7 @@ Valid for Markdown content only, not for front matter entries: ...@@ -904,7 +914,7 @@ Valid for Markdown content only, not for front matter entries:
- Standard quotes: double quotes (`"`). Example: "This is wrapped in double - Standard quotes: double quotes (`"`). Example: "This is wrapped in double
quotes". quotes".
- Quote inside a quote: double quotes (`"`) wrap single quotes (`'`). Example: - Quote inside a quote: double quotes (`"`) wrap single quotes (`'`). Example:
"I am 'quoting' something in a quote". "This sentence 'quotes' something in a quote".
For other punctuation rules, refer to the For other punctuation rules, refer to the
[GitLab UX guide](https://design.gitlab.com/content/punctuation/). [GitLab UX guide](https://design.gitlab.com/content/punctuation/).
...@@ -1367,6 +1377,8 @@ hidden on the documentation site, but is displayed by `/help`. ...@@ -1367,6 +1377,8 @@ hidden on the documentation site, but is displayed by `/help`.
- For regular fenced code blocks, always use a highlighting class corresponding to - For regular fenced code blocks, always use a highlighting class corresponding to
the language for better readability. Examples: the language for better readability. Examples:
<!-- vale off -->
````markdown ````markdown
```ruby ```ruby
Ruby code Ruby code
...@@ -1385,6 +1397,8 @@ hidden on the documentation site, but is displayed by `/help`. ...@@ -1385,6 +1397,8 @@ hidden on the documentation site, but is displayed by `/help`.
``` ```
```` ````
<!-- vale on -->
Syntax highlighting is required for fenced code blocks added to the GitLab Syntax highlighting is required for fenced code blocks added to the GitLab
documentation. Refer to the following table for the most common language classes, documentation. Refer to the following table for the most common language classes,
or check the [complete list](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers) or check the [complete list](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers)
...@@ -1771,8 +1785,7 @@ for use in GitLab X.X, and is planned for [removal](link-to-issue) in GitLab X.X ...@@ -1771,8 +1785,7 @@ for use in GitLab X.X, and is planned for [removal](link-to-issue) in GitLab X.X
``` ```
After the feature or product is officially deprecated and removed, remove After the feature or product is officially deprecated and removed, remove
its information from the GitLab documentation based on its information from the GitLab documentation.
the GitLab version where it's actually removed.
### Versions in the past or future ### Versions in the past or future
...@@ -1926,6 +1939,8 @@ Configuration settings include: ...@@ -1926,6 +1939,8 @@ Configuration settings include:
When you document a list of steps, it may entail editing the configuration file When you document a list of steps, it may entail editing the configuration file
and reconfiguring or restarting GitLab. In that case, use these styles: and reconfiguring or restarting GitLab. In that case, use these styles:
<!-- vale off -->
````markdown ````markdown
**For Omnibus installations** **For Omnibus installations**
...@@ -1953,6 +1968,8 @@ and reconfiguring or restarting GitLab. In that case, use these styles: ...@@ -1953,6 +1968,8 @@ and reconfiguring or restarting GitLab. In that case, use these styles:
GitLab for the changes to take effect. GitLab for the changes to take effect.
```` ````
<!-- vale on -->
In this case: In this case:
- Before each step list the installation method is declared in bold. - Before each step list the installation method is declared in bold.
......
...@@ -15,7 +15,7 @@ the [Elasticsearch integration documentation](../integration/elasticsearch.md#en ...@@ -15,7 +15,7 @@ the [Elasticsearch integration documentation](../integration/elasticsearch.md#en
In June 2019, Mario de la Ossa hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`) on GitLab's [Elasticsearch integration](../integration/elasticsearch.md) to share his domain specific knowledge with anyone who may work in this part of the code base in the future. You can find the [recording on YouTube](https://www.youtube.com/watch?v=vrvl-tN2EaA), and the slides on [Google Slides](https://docs.google.com/presentation/d/1H-pCzI_LNrgrL5pJAIQgvLX8Ji0-jIKOg1QeJQzChug/edit) and in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/c5aa32b6b07476fa8b597004899ec538/Elasticsearch_Deep_Dive.pdf). Everything covered in this deep dive was accurate as of GitLab 12.0, and while specific details may have changed since then, it should still serve as a good introduction. In June 2019, Mario de la Ossa hosted a Deep Dive (GitLab team members only: `https://gitlab.com/gitlab-org/create-stage/issues/1`) on GitLab's [Elasticsearch integration](../integration/elasticsearch.md) to share his domain specific knowledge with anyone who may work in this part of the code base in the future. You can find the [recording on YouTube](https://www.youtube.com/watch?v=vrvl-tN2EaA), and the slides on [Google Slides](https://docs.google.com/presentation/d/1H-pCzI_LNrgrL5pJAIQgvLX8Ji0-jIKOg1QeJQzChug/edit) and in [PDF](https://gitlab.com/gitlab-org/create-stage/uploads/c5aa32b6b07476fa8b597004899ec538/Elasticsearch_Deep_Dive.pdf). Everything covered in this deep dive was accurate as of GitLab 12.0, and while specific details may have changed since then, it should still serve as a good introduction.
In August 2020, a second Deep Dive was hosted, focusing on [GitLab's specific architecture for multi-indices support](#zero-downtime-reindexing-with-multiple-indices). The [recording on YouTube](https://www.youtube.com/watch?v=0WdPR9oB2fg) and the [slides](https://lulalala.gitlab.io/gitlab-elasticsearch-deepdive) are available. Everything covered in this deep dive was accurate as of GitLab 13.3. In August 2020, a second Deep Dive was hosted, focusing on [GitLab's specific architecture for multi-indices support](#zero-downtime-reindexing-with-multiple-indices). The [recording on YouTube](https://www.youtube.com/watch?v=0WdPR9oB2fg) and the [slides](https://lulalala.gitlab.io/gitlab-elasticsearch-deepdive/) are available. Everything covered in this deep dive was accurate as of GitLab 13.3.
## Supported Versions ## Supported Versions
......
...@@ -279,6 +279,17 @@ Subsequent calls to this method for the same experiment and the same user have n ...@@ -279,6 +279,17 @@ Subsequent calls to this method for the same experiment and the same user have n
Note that this data is completely separate from the [events tracking data](#implement-the-tracking-events). They are not linked together in any way. Note that this data is completely separate from the [events tracking data](#implement-the-tracking-events). They are not linked together in any way.
#### Add context
You can add arbitrary context data in a hash which gets stored as part of the experiment user record.
This data can then be used by data analytics dashboards.
```ruby
before_action do
record_experiment_user(:signup_flow, foo: 42)
end
```
### Record experiment conversion event ### Record experiment conversion event
Along with the tracking of backend and frontend events and the [recording of experiment participants](#record-experiment-user), we can also record when a user performs the desired conversion event action. For example: Along with the tracking of backend and frontend events and the [recording of experiment participants](#record-experiment-user), we can also record when a user performs the desired conversion event action. For example:
......
...@@ -411,7 +411,7 @@ handleClick() { ...@@ -411,7 +411,7 @@ handleClick() {
### Working with pagination ### Working with pagination
GitLab's GraphQL API uses [Relay-style cursor pagination](https://www.apollographql.com/docs/react/data/pagination/#cursor-based) GitLab's GraphQL API uses [Relay-style cursor pagination](https://www.apollographql.com/docs/react/pagination/overview/#cursor-based)
for connection types. This means a "cursor" is used to keep track of where in the data for connection types. This means a "cursor" is used to keep track of where in the data
set the next items should be fetched from. [GraphQL Ruby Connection Concepts](https://graphql-ruby.org/pagination/connection_concepts.html) set the next items should be fetched from. [GraphQL Ruby Connection Concepts](https://graphql-ruby.org/pagination/connection_concepts.html)
is a good overview and introduction to connections. is a good overview and introduction to connections.
......
...@@ -119,21 +119,21 @@ browser's developer console while on any page within GitLab. ...@@ -119,21 +119,21 @@ browser's developer console while on any page within GitLab.
``` ```
Note that `waitForCSSLoaded()` methods supports receiving the action in different ways: Note that `waitForCSSLoaded()` methods supports receiving the action in different ways:
- With a callback: - With a callback:
```javascript ```javascript
waitForCSSLoaded(action) waitForCSSLoaded(action)
``` ```
- With `then()`: - With `then()`:
```javascript ```javascript
waitForCSSLoaded().then(action); waitForCSSLoaded().then(action);
``` ```
- With `await` followed by `action`: - With `await` followed by `action`:
```javascript ```javascript
await waitForCSSLoaded; await waitForCSSLoaded;
action(); action();
......
...@@ -50,7 +50,7 @@ change feature flags or you do not [have access](#access). ...@@ -50,7 +50,7 @@ change feature flags or you do not [have access](#access).
### Enabling a feature for preproduction testing ### Enabling a feature for preproduction testing
As a first step in a feature rollout, you should enable the feature on <https://staging.gitlab.com> As a first step in a feature rollout, you should enable the feature on <https://about.staging.gitlab.com>
and <https://dev.gitlab.org>. and <https://dev.gitlab.org>.
These two environments have different scopes. These two environments have different scopes.
......
...@@ -100,7 +100,7 @@ To propose additions to the glossary please ...@@ -100,7 +100,7 @@ To propose additions to the glossary please
### Inclusive language in French ### Inclusive language in French
<!-- vale gitlab.Spelling = NO --> <!-- vale gitlab.Spelling = NO -->
In French, the "écriture inclusive" is now over (see on [Legifrance](https://www.legifrance.gouv.fr/affichTexte.do?cidTexte=JORFTEXT000036068906&categorieLien=id)). In French, the "écriture inclusive" is now over (see on [Legifrance](https://www.legifrance.gouv.fr/jorf/id/JORFTEXT000036068906/)).
So, to include both genders, write “Utilisateurs et utilisatrices” instead of “Utilisateur·rice·s”. So, to include both genders, write “Utilisateurs et utilisatrices” instead of “Utilisateur·rice·s”.
When space is missing, the male gender should be used alone. When space is missing, the male gender should be used alone.
<!-- vale gitlab.Spelling = YES --> <!-- vale gitlab.Spelling = YES -->
...@@ -243,8 +243,8 @@ end ...@@ -243,8 +243,8 @@ end
The iteration uses the primary key index (on the `id` column) which makes it safe from statement The iteration uses the primary key index (on the `id` column) which makes it safe from statement
timeouts. The filter (`sign_in_count: 0`) is applied on the `relation` where the `id` is already constrained (range). The number of rows are limited. timeouts. The filter (`sign_in_count: 0`) is applied on the `relation` where the `id` is already constrained (range). The number of rows are limited.
Slow iteration generally takes more time to finish. The iteration count is higher and Slow iteration generally takes more time to finish. The iteration count is higher and
one iteration could yield fewer records than the batch size. Iterations may even yield one iteration could yield fewer records than the batch size. Iterations may even yield
0 records. This is not an optimal solution; however, in some cases (especially when 0 records. This is not an optimal solution; however, in some cases (especially when
dealing with large tables) this is the only viable option. dealing with large tables) this is the only viable option.
...@@ -346,7 +346,7 @@ Here, we expect that the `relation` query reads the `BATCH_SIZE` of user records ...@@ -346,7 +346,7 @@ Here, we expect that the `relation` query reads the `BATCH_SIZE` of user records
filters down the results according to the provided queries. The planner might decide that filters down the results according to the provided queries. The planner might decide that
using a bitmap index lookup with the index on the `confidential` column is a better way to using a bitmap index lookup with the index on the `confidential` column is a better way to
execute the query. This can cause unexpectedly high amount of rows to be read and the query execute the query. This can cause unexpectedly high amount of rows to be read and the query
could time out. could time out.
Problem: we know for sure that the relation is returning maximum `BATCH_SIZE` of records, however the planner does not know this. Problem: we know for sure that the relation is returning maximum `BATCH_SIZE` of records, however the planner does not know this.
......
...@@ -42,7 +42,7 @@ In forms we should use the `for` attribute in the label statement: ...@@ -42,7 +42,7 @@ In forms we should use the `for` attribute in the label statement:
## Testing ## Testing
1. On MacOS you can use [VoiceOver](https://www.apple.com/accessibility/mac/vision/) by pressing `cmd+F5`. 1. On MacOS you can use [VoiceOver](http://www.apple.com/accessibility/vision/) by pressing `cmd+F5`.
1. On Windows you can use [Narrator](https://www.microsoft.com/en-us/accessibility/windows) by pressing Windows logo key + Control + Enter. 1. On Windows you can use [Narrator](https://www.microsoft.com/en-us/accessibility/windows) by pressing Windows logo key + Control + Enter.
## Online resources ## Online resources
......
...@@ -118,7 +118,7 @@ sequenceDiagram ...@@ -118,7 +118,7 @@ sequenceDiagram
1. `GitLab::UsageData.to_json` [cascades down](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L22) to ~400+ other counter method calls. 1. `GitLab::UsageData.to_json` [cascades down](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L22) to ~400+ other counter method calls.
1. The response of all methods calls are [merged together](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L14) into a single JSON payload in `GitLab::UsageData.to_json`. 1. The response of all methods calls are [merged together](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L14) into a single JSON payload in `GitLab::UsageData.to_json`.
1. The JSON payload is then [posted to the Versions application]( https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L20) 1. The JSON payload is then [posted to the Versions application]( https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L20)
If a firewall exception is needed, the required URL depends on several things. If If a firewall exception is needed, the required URL depends on several things. If
the hostname is `version.gitlab.com`, the protocol is `TCP`, and the port number is `443`, the hostname is `version.gitlab.com`, the protocol is `TCP`, and the port number is `443`,
the required URL is <https://version.gitlab.com/>. the required URL is <https://version.gitlab.com/>.
...@@ -477,20 +477,20 @@ Next, get the unique events for the current week. ...@@ -477,20 +477,20 @@ Next, get the unique events for the current week.
We have the following recommendations for [Adding new events](#adding-new-events): We have the following recommendations for [Adding new events](#adding-new-events):
- Event aggregation: weekly. - Event aggregation: weekly.
- Key expiry time: - Key expiry time:
- Daily: 29 days. - Daily: 29 days.
- Weekly: 42 days. - Weekly: 42 days.
- When adding new metrics, use a [feature flag](../../operations/feature_flags.md) to control the impact. - When adding new metrics, use a [feature flag](../../operations/feature_flags.md) to control the impact.
- For feature flags triggered by another service, set `default_enabled: false`, - For feature flags triggered by another service, set `default_enabled: false`,
- Events can be triggered using the `UsageData` API, which helps when there are > 10 events per change - Events can be triggered using the `UsageData` API, which helps when there are > 10 events per change
##### Enable/Disable Redis HLL tracking ##### Enable/Disable Redis HLL tracking
Events are tracked behind [feature flags](../feature_flags/index.md) due to concerns for Redis performance and scalability. Events are tracked behind [feature flags](../feature_flags/index.md) due to concerns for Redis performance and scalability.
For a full list of events and coresponding feature flags see, [known_events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/) files. For a full list of events and corresponding feature flags see, [known_events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/) files.
To enable or disable tracking for specific event within <https://gitlab.com> or <https://staging.gitlab.com>, run commands such as the following to To enable or disable tracking for specific event within <https://gitlab.com> or <https://about.staging.gitlab.com>, run commands such as the following to
[enable or disable the corresponding feature](../feature_flags/index.md). [enable or disable the corresponding feature](../feature_flags/index.md).
```shell ```shell
...@@ -666,7 +666,7 @@ We also use `#database-lab` and [explain.depesz.com](https://explain.depesz.com/ ...@@ -666,7 +666,7 @@ We also use `#database-lab` and [explain.depesz.com](https://explain.depesz.com/
### 5. Add the metric definition ### 5. Add the metric definition
When adding, changing, or updating metrics, please update the [Event Dictionary's **Usage Ping** table](https://about.gitlab.com/handbook/product/product-analytics-guide#event-dictionary). When adding, changing, or updating metrics, please update the [Event Dictionary's **Usage Ping** table](https://about.gitlab.com/handbook/product/product-analytics-guide/#event-dictionary).
### 6. Add new metric to Versions Application ### 6. Add new metric to Versions Application
......
...@@ -27,7 +27,7 @@ After adding a new queue, run `bin/rake ...@@ -27,7 +27,7 @@ After adding a new queue, run `bin/rake
gitlab:sidekiq:all_queues_yml:generate` to regenerate gitlab:sidekiq:all_queues_yml:generate` to regenerate
`app/workers/all_queues.yml` or `ee/app/workers/all_queues.yml` so that `app/workers/all_queues.yml` or `ee/app/workers/all_queues.yml` so that
it can be picked up by it can be picked up by
[`sidekiq-cluster`](../administration/operations/extra_sidekiq_processes.md). [`sidekiq-cluster`](../administration/operations/extra_sidekiq_processes.md).
Additionally, run Additionally, run
`bin/rake gitlab:sidekiq:sidekiq_queues_yml:generate` to regenerate `bin/rake gitlab:sidekiq:sidekiq_queues_yml:generate` to regenerate
`config/sidekiq_queues.yml`. `config/sidekiq_queues.yml`.
......
...@@ -192,8 +192,8 @@ Following you'll find some general common practices you will find as part of our ...@@ -192,8 +192,8 @@ Following you'll find some general common practices you will find as part of our
When it comes to querying DOM elements in your tests, it is best to uniquely and semantically target When it comes to querying DOM elements in your tests, it is best to uniquely and semantically target
the element. the element.
Preferentially, this is done by targeting what the user actually sees using [DOM Testing Library](https://testing-library.com/docs/dom-testing-library/intro). Preferentially, this is done by targeting what the user actually sees using [DOM Testing Library](https://testing-library.com/docs/dom-testing-library/intro/).
When selecting by text it is best to use [`getByRole` or `findByRole`](https://testing-library.com/docs/dom-testing-library/api-queries#byrole) When selecting by text it is best to use [`getByRole` or `findByRole`](https://testing-library.com/docs/dom-testing-library/api-queries/#byrole)
as these enforce accessibility best practices as well. The examples below demonstrate the order of preference. as these enforce accessibility best practices as well. The examples below demonstrate the order of preference.
When writing Vue component unit tests, it can be wise to query children by component, so that the unit test can focus on comprehensive value coverage When writing Vue component unit tests, it can be wise to query children by component, so that the unit test can focus on comprehensive value coverage
......
--- ---
redirect_to: 'https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/' redirect_to: 'https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/'
--- ---
This document was moved to [another location](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/). This document was moved to [another location](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/).
<!-- This redirect file can be deleted after February 1, 2021. --> <!-- This redirect file can be deleted after February 1, 2021. -->
<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page -->
...@@ -49,7 +49,7 @@ prompt, terminal, and command line) of your preference. Here are some suggestion ...@@ -49,7 +49,7 @@ prompt, terminal, and command line) of your preference. Here are some suggestion
- For macOS users: - For macOS users:
- Built-in: [Terminal](https://blog.teamtreehouse.com/introduction-to-the-mac-os-x-command-line). Press <kbd>⌘ command</kbd> + <kbd>space</kbd> and type "terminal" to find it. - Built-in: [Terminal](https://blog.teamtreehouse.com/introduction-to-the-mac-os-x-command-line). Press <kbd>⌘ command</kbd> + <kbd>space</kbd> and type "terminal" to find it.
- [iTerm2](https://www.iterm2.com/), which you can integrate with [zsh](https://git-scm.com/book/id/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh) and [oh my zsh](https://ohmyz.sh/) for color highlighting, among other handy features for Git users. - [iTerm2](https://iterm2.com/), which you can integrate with [zsh](https://git-scm.com/book/id/v2/Appendix-A%3A-Git-in-Other-Environments-Git-in-Zsh) and [oh my zsh](https://ohmyz.sh/) for color highlighting, among other handy features for Git users.
- For Windows users: - For Windows users:
- Built-in: **cmd**. Click the search icon on the bottom navbar on Windows and type "cmd" to find it. - Built-in: **cmd**. Click the search icon on the bottom navbar on Windows and type "cmd" to find it.
- [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/install/installing-windows-powershell?view=powershell-7): a Windows "powered up" shell, from which you can execute a greater number of commands. - [PowerShell](https://docs.microsoft.com/en-us/powershell/scripting/windows-powershell/install/installing-windows-powershell?view=powershell-7): a Windows "powered up" shell, from which you can execute a greater number of commands.
......
...@@ -227,7 +227,7 @@ The storage requirements for Redis are minimal, about 25kB per user. ...@@ -227,7 +227,7 @@ The storage requirements for Redis are minimal, about 25kB per user.
Sidekiq processes the background jobs with a multithreaded process. Sidekiq processes the background jobs with a multithreaded process.
This process starts with the entire Rails stack (200MB+) but it can grow over time due to memory leaks. This process starts with the entire Rails stack (200MB+) but it can grow over time due to memory leaks.
On a very active server (10,000 billable users) the Sidekiq process can use 1GB+ of memory. On a very active server (10,000 billable users) the Sidekiq process can use 1GB+ of memory.
## Prometheus and its exporters ## Prometheus and its exporters
As of Omnibus GitLab 9.0, [Prometheus](https://prometheus.io) and its related As of Omnibus GitLab 9.0, [Prometheus](https://prometheus.io) and its related
......
...@@ -27,7 +27,7 @@ For a real use case, read the blog post [Continuous integration: From Jenkins to ...@@ -27,7 +27,7 @@ For a real use case, read the blog post [Continuous integration: From Jenkins to
Moving from a traditional CI plug-in to a single application for the entire software development Moving from a traditional CI plug-in to a single application for the entire software development
life cycle can decrease hours spent on maintaining toolchains by 10% or more. For more details, see life cycle can decrease hours spent on maintaining toolchains by 10% or more. For more details, see
the ['GitLab vs. Jenkins' comparison page](https://about.gitlab.com/devops-tools/jenkins-vs-gitlab.html). the ['GitLab vs. Jenkins' comparison page](https://about.gitlab.com/devops-tools/jenkins-vs-gitlab/).
NOTE: **Note:** NOTE: **Note:**
This documentation focuses only on how to **configure** a Jenkins *integration* with This documentation focuses only on how to **configure** a Jenkins *integration* with
......
...@@ -232,7 +232,7 @@ Potential resolutions: ...@@ -232,7 +232,7 @@ Potential resolutions:
- If you're using GitLab Core or GitLab Starter, be sure you're using - If you're using GitLab Core or GitLab Starter, be sure you're using
GitLab 13.4 or later. GitLab 13.4 or later.
[Contact GitLab Support](https://about.gitlab.com/support) if none of these reasons apply. [Contact GitLab Support](https://about.gitlab.com/support/) if none of these reasons apply.
#### Fixing synchronization issues #### Fixing synchronization issues
...@@ -245,11 +245,11 @@ resynchronize the information. To do so: ...@@ -245,11 +245,11 @@ resynchronize the information. To do so:
1. For each project, there's a sync button displayed next to the **last activity** date. 1. For each project, there's a sync button displayed next to the **last activity** date.
To perform a *soft resync*, click the button, or complete a *full sync* by shift clicking To perform a *soft resync*, click the button, or complete a *full sync* by shift clicking
the button. For more information, see the button. For more information, see
[Atlassian's documentation](https://confluence.atlassian.com/adminjiracloud/synchronize-an-account-972332890.html). [Atlassian's documentation](https://support.atlassian.com/jira-cloud-administration/docs/synchronize-jira-cloud-to-bitbucket/).
### GitLab for Jira app ### GitLab for Jira app
You can integrate GitLab.com and Jira Cloud using the [GitLab for Jira](https://marketplace.atlassian.com/apps/1221011/gitlab-for-jira) app in the Atlassian Marketplace. You can integrate GitLab.com and Jira Cloud using the [GitLab for Jira](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud) app in the Atlassian Marketplace.
This method is recommended when using GitLab.com and Jira Cloud because data is synchronized in realtime, while the DVCS connector updates data only once per hour. If you are not using both of these environments, use the [Jira DVCS Connector](#jira-dvcs-configuration) method. This method is recommended when using GitLab.com and Jira Cloud because data is synchronized in realtime, while the DVCS connector updates data only once per hour. If you are not using both of these environments, use the [Jira DVCS Connector](#jira-dvcs-configuration) method.
...@@ -257,7 +257,7 @@ This method is recommended when using GitLab.com and Jira Cloud because data is ...@@ -257,7 +257,7 @@ This method is recommended when using GitLab.com and Jira Cloud because data is
For a walkthrough of the integration with GitLab for Jira, watch [Configure GitLab Jira Integration using Marketplace App](https://youtu.be/SwR-g1s1zTo) on YouTube. For a walkthrough of the integration with GitLab for Jira, watch [Configure GitLab Jira Integration using Marketplace App](https://youtu.be/SwR-g1s1zTo) on YouTube.
1. Go to **Jira Settings > Apps > Find new apps**, then search for GitLab. 1. Go to **Jira Settings > Apps > Find new apps**, then search for GitLab.
1. Click **GitLab for Jira**, then click **Get it now**. Or go the [App in the marketplace directly](https://marketplace.atlassian.com/apps/1221011/gitlab-for-jira) 1. Click **GitLab for Jira**, then click **Get it now**. Or go the [App in the marketplace directly](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud)
![Install GitLab App on Jira](img/jira_dev_panel_setup_com_1.png) ![Install GitLab App on Jira](img/jira_dev_panel_setup_com_1.png)
1. After installing, click **Get started** to go to the configurations page. This page is always available under **Jira Settings > Apps > Manage apps**. 1. After installing, click **Get started** to go to the configurations page. This page is always available under **Jira Settings > Apps > Manage apps**.
......
...@@ -13,13 +13,13 @@ GitLab can integrate with [Kerberos](https://web.mit.edu/kerberos/) as an authen ...@@ -13,13 +13,13 @@ GitLab can integrate with [Kerberos](https://web.mit.edu/kerberos/) as an authen
[Kerberos](https://web.mit.edu/kerberos/) is a secure method for authenticating a request for a service in a [Kerberos](https://web.mit.edu/kerberos/) is a secure method for authenticating a request for a service in a
computer network. Kerberos was developed in the Athena Project at the computer network. Kerberos was developed in the Athena Project at the
[Massachusetts Institute of Technology (MIT)](http://web.mit.edu/). The name is taken from Greek [Massachusetts Institute of Technology (MIT)](https://web.mit.edu/). The name is taken from Greek
mythology; Kerberos was a three-headed dog who guarded the gates of Hades. mythology; Kerberos was a three-headed dog who guarded the gates of Hades.
## Use-cases ## Use-cases
- GitLab can be configured to allow your users to sign with their Kerberos credentials. - GitLab can be configured to allow your users to sign with their Kerberos credentials.
- You can use Kerberos to [prevent](http://web.mit.edu/sipb/doc/working/guide/guide/node20.html) anyone from intercepting or eavesdropping on the transmitted password. - You can use Kerberos to [prevent](https://web.mit.edu/sipb/doc/working/guide/guide/node20.html) anyone from intercepting or eavesdropping on the transmitted password.
## Configuration ## Configuration
......
...@@ -64,7 +64,7 @@ Feature.enable(:sourcegraph, Project.find_by_full_path('my_group/my_project')) ...@@ -64,7 +64,7 @@ Feature.enable(:sourcegraph, Project.find_by_full_path('my_group/my_project'))
If you are new to Sourcegraph, head over to the [Sourcegraph installation documentation](https://docs.sourcegraph.com/admin) and get your instance up and running. If you are new to Sourcegraph, head over to the [Sourcegraph installation documentation](https://docs.sourcegraph.com/admin) and get your instance up and running.
If you are using an HTTPS connection to GitLab, you will need to [configure HTTPS](https://docs.sourcegraph.com/admin/http_https_configuration) for your Sourcegraph instance. If you are using an HTTPS connection to GitLab, you will need to [configure HTTPS](https://docs.sourcegraph.com/admin/http_https_configuration) for your Sourcegraph instance.
### Connect your Sourcegraph instance to your GitLab instance ### Connect your Sourcegraph instance to your GitLab instance
......
...@@ -266,12 +266,12 @@ You can exclude specific directories from the backup by adding the environment v ...@@ -266,12 +266,12 @@ You can exclude specific directories from the backup by adding the environment v
- `lfs` (LFS objects) - `lfs` (LFS objects)
- `registry` (Container Registry images) - `registry` (Container Registry images)
- `pages` (Pages content) - `pages` (Pages content)
- `repositories` (Git repositories data) - `repositories` (Git repositories data)
All wikis will be backed up as part of the `repositories` group. Non-existent wikis will be skipped during a backup. All wikis will be backed up as part of the `repositories` group. Non-existent wikis will be skipped during a backup.
NOTE: **Note:** NOTE: **Note:**
When [backing up and restoring Helm Charts](https://docs.gitlab.com/charts/architecture/backup-restore.html), there is an additional option `packages`, which refers to any packages managed by the GitLab [package registry](../user/packages/package_registry/index.md). When [backing up and restoring Helm Charts](https://docs.gitlab.com/charts/architecture/backup-restore.html), there is an additional option `packages`, which refers to any packages managed by the GitLab [package registry](../user/packages/package_registry/index.md).
For more information see [command line arguments](https://docs.gitlab.com/charts/architecture/backup-restore.html#command-line-arguments). For more information see [command line arguments](https://docs.gitlab.com/charts/architecture/backup-restore.html#command-line-arguments).
All wikis are backed up as part of the `repositories` group. Non-existent All wikis are backed up as part of the `repositories` group. Non-existent
......
...@@ -173,7 +173,7 @@ Find more information how to apply and renew at ...@@ -173,7 +173,7 @@ Find more information how to apply and renew at
## GitLab for Open Source subscriptions ## GitLab for Open Source subscriptions
All [GitLab for Open Source](https://about.gitlab.com/solutions/open-source/program/) All [GitLab for Open Source](https://about.gitlab.com/solutions/open-source/join/)
requests, including subscription renewals, must be made by using the application process. requests, including subscription renewals, must be made by using the application process.
If you have any questions, send an email to `opensource@gitlab.com` for assistance. If you have any questions, send an email to `opensource@gitlab.com` for assistance.
......
...@@ -168,7 +168,7 @@ application will be monitored by the WAF automatically. ...@@ -168,7 +168,7 @@ application will be monitored by the WAF automatically.
Now we can make sure that Ingress is running properly with ModSecurity and send Now we can make sure that Ingress is running properly with ModSecurity and send
a request to ensure our application is responding correctly. You must connect to a request to ensure our application is responding correctly. You must connect to
your cluster either using [Cloud Shell](https://cloud.google.com/shell/) or the [Google Cloud SDK](https://cloud.google.com/sdk/install). your cluster either using [Cloud Shell](https://cloud.google.com/shell/) or the [Google Cloud SDK](https://cloud.google.com/sdk/docs/install).
1. After connecting to your cluster, check if the Ingress-NGINX controller is running and ModSecurity is enabled. 1. After connecting to your cluster, check if the Ingress-NGINX controller is running and ModSecurity is enabled.
......
...@@ -143,7 +143,7 @@ The GitLab University curriculum is composed of GitLab videos, screencasts, pres ...@@ -143,7 +143,7 @@ The GitLab University curriculum is composed of GitLab videos, screencasts, pres
### 3.1. DevOps ### 3.1. DevOps
1. [XebiaLabs: DevOps Terminology](https://xebialabs.com/glossary/) 1. [XebiaLabs: DevOps Terminology](https://digital.ai/glossary)
1. [XebiaLabs: Periodic Table of DevOps Tools](https://digital.ai/periodic-table-of-devops-tools) 1. [XebiaLabs: Periodic Table of DevOps Tools](https://digital.ai/periodic-table-of-devops-tools)
1. [Puppet Labs: State of DevOps 2016 - Book](https://puppet.com/resources/report/2016-state-devops-report/) 1. [Puppet Labs: State of DevOps 2016 - Book](https://puppet.com/resources/report/2016-state-devops-report/)
......
...@@ -37,7 +37,7 @@ The table is sorted by: ...@@ -37,7 +37,7 @@ The table is sorted by:
## Use cases ## Use cases
This feature is designed for [development team leaders](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#delaney-development-team-lead) This feature is designed for [development team leaders](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/#delaney-development-team-lead)
and others who want to understand broad code review dynamics, and identify patterns to explain them. and others who want to understand broad code review dynamics, and identify patterns to explain them.
You can use Code Review Analytics to: You can use Code Review Analytics to:
......
...@@ -23,7 +23,7 @@ To access Merge Request Analytics, from your project's menu, go to **Analytics > ...@@ -23,7 +23,7 @@ To access Merge Request Analytics, from your project's menu, go to **Analytics >
## Use cases ## Use cases
This feature is designed for [development team leaders](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#delaney-development-team-lead) This feature is designed for [development team leaders](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/#delaney-development-team-lead)
and others who want to understand broad patterns in code review and productivity. and others who want to understand broad patterns in code review and productivity.
You can use Merge Request Analytics to expose when your team is most and least productive, and You can use Merge Request Analytics to expose when your team is most and least productive, and
......
...@@ -155,7 +155,7 @@ You can use various tools to generate HAR files: ...@@ -155,7 +155,7 @@ You can use various tools to generate HAR files:
- [Fiddler](https://www.telerik.com/fiddler): Web debugging proxy - [Fiddler](https://www.telerik.com/fiddler): Web debugging proxy
- [Insomnia Core](https://insomnia.rest/): API client - [Insomnia Core](https://insomnia.rest/): API client
- [Chrome](https://www.google.com/chrome): Browser - [Chrome](https://www.google.com/chrome/): Browser
- [Firefox](https://www.mozilla.org/en-US/firefox/): Browser - [Firefox](https://www.mozilla.org/en-US/firefox/): Browser
DANGER: **Warning:** DANGER: **Warning:**
......
...@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w ...@@ -9,7 +9,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41203) in GitLab 13.4, only for public projects on GitLab.com. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/41203) in GitLab 13.4, only for public projects on GitLab.com.
As part of [GitLab's role as a CVE Numbering Authority](https://about.gitlab.com/security/cve) As part of [GitLab's role as a CVE Numbering Authority](https://about.gitlab.com/security/cve/)
([CNA](https://cve.mitre.org/cve/cna.html)), you may request ([CNA](https://cve.mitre.org/cve/cna.html)), you may request
[CVE](https://cve.mitre.org/index.html) identifiers from GitLab to track [CVE](https://cve.mitre.org/index.html) identifiers from GitLab to track
vulnerabilities found within your project. vulnerabilities found within your project.
......
...@@ -130,13 +130,13 @@ always take the latest Secret Detection artifact available. ...@@ -130,13 +130,13 @@ always take the latest Secret Detection artifact available.
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4639) in GitLab 13.6. > [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4639) in GitLab 13.6.
Upon detection of a secret, GitLab supports post processing hooks. These can be used to take actions like notifying the cloud service who issued the secret. The cloud provider can confirm the credentials and take remediation actions like revoking or reissuing a new secret and notifying the creator of the secret. Post-processing workflows vary by supported cloud providers. Upon detection of a secret, GitLab supports post processing hooks. These can be used to take actions like notifying the cloud service who issued the secret. The cloud provider can confirm the credentials and take remediation actions like revoking or reissuing a new secret and notifying the creator of the secret. Post-processing workflows vary by supported cloud providers.
GitLab currently supports post-processing for following service providers: GitLab currently supports post-processing for following service providers:
- Amazon Web Services (AWS) - Amazon Web Services (AWS)
Third party cloud and SaaS providers can [express integration interest by filling out this form](https://forms.gle/wWpvrtLRK21Q2WJL9). Learn more about the [technical details of post-processing secrets](https://gitlab.com/groups/gitlab-org/-/epics/4639). Third party cloud and SaaS providers can [express integration interest by filling out this form](https://forms.gle/wWpvrtLRK21Q2WJL9). Learn more about the [technical details of post-processing secrets](https://gitlab.com/groups/gitlab-org/-/epics/4639).
### Customizing settings ### Customizing settings
...@@ -286,14 +286,14 @@ For information on this, see the [general Application Security troubleshooting s ...@@ -286,14 +286,14 @@ For information on this, see the [general Application Security troubleshooting s
### Error: `Couldn't run the gitleaks command: exit status 2` ### Error: `Couldn't run the gitleaks command: exit status 2`
This error is usually caused by the `GIT_DEPTH` value of 50 that is set for all [projects by default](../../../ci/pipelines/settings.md#git-shallow-clone). This error is usually caused by the `GIT_DEPTH` value of 50 that is set for all [projects by default](../../../ci/pipelines/settings.md#git-shallow-clone).
For example, if a pipeline is triggered from a Merge Request containing 60 commits while the `GIT_DEPTH` is set to 50, the Secret Detection job will fail as the clone will not have been deep enough to contain all of the relevant commits. For example, if a pipeline is triggered from a Merge Request containing 60 commits while the `GIT_DEPTH` is set to 50, the Secret Detection job will fail as the clone will not have been deep enough to contain all of the relevant commits.
You can confirm this to be the cause of the error by implementing a [logging level](../../application_security/secret_detection/index.md#logging-level) of `debug`. Once implemented, the logs should look similar to the following example, wherein an "object not found" error can be seen: You can confirm this to be the cause of the error by implementing a [logging level](../../application_security/secret_detection/index.md#logging-level) of `debug`. Once implemented, the logs should look similar to the following example, wherein an "object not found" error can be seen:
```plaintext ```plaintext
ERRO[2020-11-18T18:05:52Z] object not found ERRO[2020-11-18T18:05:52Z] object not found
[ERRO] [secrets] [2020-11-18T18:05:52Z] ▶ Couldn't run the gitleaks command: exit status 2 [ERRO] [secrets] [2020-11-18T18:05:52Z] ▶ Couldn't run the gitleaks command: exit status 2
[ERRO] [secrets] [2020-11-18T18:05:52Z] ▶ Gitleaks analysis failed: exit status 2 [ERRO] [secrets] [2020-11-18T18:05:52Z] ▶ Gitleaks analysis failed: exit status 2
``` ```
......
...@@ -274,13 +274,13 @@ to specify its location. ...@@ -274,13 +274,13 @@ to specify its location.
### Configuring NPM projects ### Configuring NPM projects
You can configure NPM projects by using an [`.npmrc`](https://docs.npmjs.com/configuring-npm/npmrc.html) You can configure NPM projects by using an [`.npmrc`](https://docs.npmjs.com/configuring-npm/npmrc.html/)
file. file.
#### Using private NPM registries #### Using private NPM registries
If you have a private NPM registry you can use the If you have a private NPM registry you can use the
[`registry`](https://docs.npmjs.com/using-npm/config#registry) [`registry`](https://docs.npmjs.com/using-npm/config/#registry)
setting to specify its location. setting to specify its location.
For example: For example:
...@@ -294,7 +294,7 @@ registry = https://npm.example.com ...@@ -294,7 +294,7 @@ registry = https://npm.example.com
You can supply a custom root certificate to complete TLS verification by using the You can supply a custom root certificate to complete TLS verification by using the
`ADDITIONAL_CA_CERT_BUNDLE` [environment variable](#available-variables). `ADDITIONAL_CA_CERT_BUNDLE` [environment variable](#available-variables).
To disable TLS verification you can provide the [`strict-ssl`](https://docs.npmjs.com/using-npm/config#strict-ssl) To disable TLS verification you can provide the [`strict-ssl`](https://docs.npmjs.com/using-npm/config/#strict-ssl)
setting. setting.
For example: For example:
......
...@@ -263,7 +263,7 @@ You can create a spreadsheet template to manage a pattern of consistently repeat ...@@ -263,7 +263,7 @@ You can create a spreadsheet template to manage a pattern of consistently repeat
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> <i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
For an introduction to epic templates, see [GitLab Epics and Epic Template Tip](https://www.youtube.com/watch?v=D74xKFNw8vg). For an introduction to epic templates, see [GitLab Epics and Epic Template Tip](https://www.youtube.com/watch?v=D74xKFNw8vg).
For more on epic templates, see [Epic Templates - Repeatable sets of issues](https://about.gitlab.com/handbook/marketing/product-marketing/getting-started/104/). For more on epic templates, see [Epic Templates - Repeatable sets of issues](https://about.gitlab.com/handbook/marketing/strategic-marketing/getting-started/104/).
## Manage multi-level child epics **(ULTIMATE)** ## Manage multi-level child epics **(ULTIMATE)**
......
...@@ -241,7 +241,7 @@ Users can unlink SAML for a group from their profile page. This can be helpful i ...@@ -241,7 +241,7 @@ Users can unlink SAML for a group from their profile page. This can be helpful i
- Your SAML NameID has changed and so GitLab can no longer find your user. - Your SAML NameID has changed and so GitLab can no longer find your user.
CAUTION: **Warning:** CAUTION: **Warning:**
Unlinking an account removes all roles assigned to that user within the group. Unlinking an account removes all roles assigned to that user within the group.
If a user relinks their account, roles need to be reassigned. If a user relinks their account, roles need to be reassigned.
For example, to unlink the `MyOrg` account, the following **Disconnect** button is available under **Profile > Accounts**: For example, to unlink the `MyOrg` account, the following **Disconnect** button is available under **Profile > Accounts**:
...@@ -274,14 +274,14 @@ To link the SAML `Freelancers` group in the attribute statement example above: ...@@ -274,14 +274,14 @@ To link the SAML `Freelancers` group in the attribute statement example above:
1. Enter `Freelancers` in the `SAML Group Name` field. 1. Enter `Freelancers` in the `SAML Group Name` field.
1. Choose the desired `Access Level`. 1. Choose the desired `Access Level`.
1. **Save** the group link. 1. **Save** the group link.
1. Repeat to add additional group links if desired. 1. Repeat to add additional group links if desired.
![SAML Group Links](img/saml_group_links_v13_6.png) ![SAML Group Links](img/saml_group_links_v13_6.png)
If a user is a member of multiple SAML groups mapped to the same GitLab group, If a user is a member of multiple SAML groups mapped to the same GitLab group,
the user gets the highest access level from the groups. For example, if one group the user gets the highest access level from the groups. For example, if one group
is linked as `Guest` and another `Maintainer`, a user in both groups gets `Maintainer` is linked as `Guest` and another `Maintainer`, a user in both groups gets `Maintainer`
access. access.
## Glossary ## Glossary
......
...@@ -22,7 +22,7 @@ We encourage you to view this document as [rendered by GitLab itself](https://gi ...@@ -22,7 +22,7 @@ We encourage you to view this document as [rendered by GitLab itself](https://gi
GitLab uses "GitLab Flavored Markdown" (GFM). It extends the [CommonMark specification](https://spec.commonmark.org/current/) GitLab uses "GitLab Flavored Markdown" (GFM). It extends the [CommonMark specification](https://spec.commonmark.org/current/)
(which is based on standard Markdown) in several ways to add additional useful functionality. (which is based on standard Markdown) in several ways to add additional useful functionality.
It was inspired by [GitHub Flavored Markdown](https://docs.github.com/en/github/writing-on-github/basic-writing-and-formatting-syntax). It was inspired by [GitHub Flavored Markdown](https://docs.github.com/en/free-pro-team@latest/github/writing-on-github/basic-writing-and-formatting-syntax).
You can use GFM in the following areas: You can use GFM in the following areas:
......
...@@ -70,7 +70,10 @@ so that anyone who can access the project can use the package as a dependency. ...@@ -70,7 +70,10 @@ so that anyone who can access the project can use the package as a dependency.
Prerequisites: Prerequisites:
- A package in a GitLab repository. - A package in a GitLab repository. Composer packages should be versioned based on
the [Composer specification](https://getcomposer.org/doc/04-schema.md#version).
If the version is not valid, for example, it has three dots (`1.0.0.0`), an
error (`Validation failed: Version is invalid`) occurs when you publish.
- A valid `composer.json` file. - A valid `composer.json` file.
- The Packages feature is enabled in a GitLab repository. - The Packages feature is enabled in a GitLab repository.
- The project ID, which is on the project's home page. - The project ID, which is on the project's home page.
......
...@@ -292,7 +292,7 @@ Prerequisites: ...@@ -292,7 +292,7 @@ Prerequisites:
- [Authentication](#authenticate-to-the-package-registry) with the - [Authentication](#authenticate-to-the-package-registry) with the
Package Registry must be configured. Package Registry must be configured.
1. In the project where you want to install the package as a dependency, open 1. In the project where you want to install the package as a dependency, open
`conanfile.txt`. Or, in the root of your project, create a file called `conanfile.txt`. Or, in the root of your project, create a file called
`conanfile.txt`. `conanfile.txt`.
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment