Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-02-26 18:12:12 +00:00
parent 8b2a413032
commit 55a8c39b97
124 changed files with 2011 additions and 416 deletions

View File

@ -795,7 +795,6 @@ lib/gitlab/checks/**
/doc/api/import.md @ashrafkhamis
/doc/api/instance_clusters.md @z_painter
/doc/api/instance_level_ci_variables.md @marcel.amirault
/doc/api/integrations.md @ashrafkhamis
/doc/api/invitations.md @emily.sahlani
/doc/api/issue_links.md @msedlakjakubowski
/doc/api/issues.md @msedlakjakubowski
@ -840,6 +839,7 @@ lib/gitlab/checks/**
/doc/api/project_clusters.md @z_painter
/doc/api/project_forks.md @emily.sahlani
/doc/api/project_import_export.md @ashrafkhamis
/doc/api/project_integrations.md @ashrafkhamis
/doc/api/project_job_token_scopes.md @marcel.amirault
/doc/api/project_level_variables.md @marcel.amirault
/doc/api/project_markdown_uploads.md @msedlakjakubowski
@ -1027,7 +1027,7 @@ lib/gitlab/checks/**
/doc/raketasks/x509_signatures.md @brendan777
/doc/security/ @idurham
/doc/security/hardening_nist_800_53.md @emily.sahlani
/doc/solutions/ @jfullam @brianwald @Darwinjs
/doc/solutions/ @jfullam @Darwinjs @sbrightwell
/doc/solutions/integrations/servicenow.md @ashrafkhamis
/doc/subscriptions/ @lciutacu
/doc/subscriptions/gitlab_com/ @lyspin
@ -1111,8 +1111,6 @@ lib/gitlab/checks/**
/doc/user/group/_index.md @emily.sahlani
/doc/user/group/access_and_permissions.md @emily.sahlani
/doc/user/group/clusters/ @z_painter
/doc/user/group/compliance_frameworks.md @eread
/doc/user/group/compliance_pipelines.md @eread
/doc/user/group/contribution_analytics/ @lciutacu
/doc/user/group/credentials_inventory.md @idurham
/doc/user/group/custom_project_templates.md @brendan777

View File

@ -2,15 +2,8 @@
# Cop supports --autocorrect.
Style/SymbolProc:
Exclude:
- 'app/controllers/profiles_controller.rb'
- 'app/models/ci/pipeline.rb'
- 'app/models/container_repository.rb'
- 'app/models/discussion.rb'
- 'app/models/environment.rb'
- 'app/models/integrations/prometheus.rb'
- 'app/models/members/project_member.rb'
- 'app/models/preloaders/merge_request_diff_preloader.rb'
- 'app/models/release.rb'
- 'app/models/remote_mirror.rb'
- 'app/models/snippet_input_action_collection.rb'
- 'app/policies/group_policy.rb'
@ -95,10 +88,6 @@ Style/SymbolProc:
- 'lib/api/helpers/internal_helpers.rb'
- 'lib/atlassian/jira_connect/serializers/base_entity.rb'
- 'lib/bulk_imports/common/pipelines/entity_finisher.rb'
- 'lib/bulk_imports/ndjson_pipeline.rb'
- 'lib/container_registry/client.rb'
- 'lib/container_registry/gitlab_api_client.rb'
- 'lib/gitlab/analytics/cycle_analytics/stage_events.rb'
- 'lib/gitlab/auth/o_auth/auth_hash.rb'
- 'lib/gitlab/blob_helper.rb'
- 'lib/gitlab/cache/ci/project_pipeline_status.rb'
@ -188,4 +177,3 @@ Style/SymbolProc:
- 'spec/support/shared_examples/models/label_note_shared_examples.rb'
- 'spec/views/layouts/_published_experiments.html.haml_spec.rb'
- 'spec/workers/snippets/schedule_bulk_repository_shard_moves_worker_spec.rb'
- 'tooling/lib/tooling/test_map_generator.rb'

View File

@ -2,6 +2,19 @@
documentation](doc/development/changelog.md) for instructions on adding your own
entry.
## 17.9.1 (2025-02-26)
### Fixed (1 change)
- [Fix instance level dashboard by default severity override](https://gitlab.com/gitlab-org/security/gitlab/-/commit/56d2f940bb6e87b34e4f26ba9a298f28360dd23a) **GitLab Enterprise Edition**
### Security (4 changes)
- [Increase minimum role in SPP to read policy yaml](https://gitlab.com/gitlab-org/security/gitlab/-/commit/593c0a6f70564e9570fb16b25a37298eacf6c644) ([merge request](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/4718))
- [Fix access to read code review analytics in private projects](https://gitlab.com/gitlab-org/security/gitlab/-/commit/0faa526c76e3c523ff6486057c5b5b07e8e4e5d9) ([merge request](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/4794))
- [Escape work item dropdown items and restrict HTML tags](https://gitlab.com/gitlab-org/security/gitlab/-/commit/fc777a98ebd45b30ab95bc0d94a418479d15f09c) ([merge request](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/4788))
- [Use stricter CSP values in the packages dependency proxy](https://gitlab.com/gitlab-org/security/gitlab/-/commit/922d3ad17cf7493a10f8dbf90c0cae8d9d4b063d) ([merge request](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/4787))
## 17.9.0 (2025-02-19)
### Added (202 changes)
@ -1083,6 +1096,15 @@ entry.
- [Quarantine a flaky test](https://gitlab.com/gitlab-org/gitlab/-/commit/c932e35efdc0e3c6f316a3c2d37045e115ce8cd5) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/176452))
- [Finalize migration BackfillRemoteDevelopmentAgentConfigsProjectId](https://gitlab.com/gitlab-org/gitlab/-/commit/da4c63d7aab3685c3fbe9d1e48f68ba2162a0b5e) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/172769))
## 17.8.4 (2025-02-26)
### Security (4 changes)
- [Increase minimum role in SPP to read policy yaml](https://gitlab.com/gitlab-org/security/gitlab/-/commit/9bfcf4a596b965ce73426d68861cec83ee70f19e) ([merge request](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/4716))
- [Fix access to read code review analytics in private projects](https://gitlab.com/gitlab-org/security/gitlab/-/commit/537159f505cad7d23cded01140fbdfd84e9cdfa2) ([merge request](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/4758))
- [Escape work item dropdown items and restrict HTML tags](https://gitlab.com/gitlab-org/security/gitlab/-/commit/5548168c3d4e0ba660ed934f23c332045a640799) ([merge request](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/4784))
- [Use stricter CSP values in the packages dependency proxy](https://gitlab.com/gitlab-org/security/gitlab/-/commit/d491abd511c9c1cb00c928e28dc84cb7ef8e4cd3) ([merge request](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/4764))
## 17.8.3 (2025-02-21)
### Fixed (2 changes)
@ -1574,6 +1596,19 @@ entry.
- [Remove default on `group_saved_replies_flag feature flag](https://gitlab.com/gitlab-org/gitlab/-/commit/75d49fe13646e1e0d3b68233ac4a965c86853917) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/175647))
- [Remove use_actual_plan_in_license_check flag](https://gitlab.com/gitlab-org/gitlab/-/commit/b8c3fe16aedb69c82ff52d1c695d72e933c4b946) ([merge request](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/175649))
## 17.7.6 (2025-02-26)
### Fixed (1 change)
- [Fix failed jobs widget polling issue](https://gitlab.com/gitlab-org/security/gitlab/-/commit/e2154d3d886d82e1f5fe62fb9d234d00e257e784)
### Security (4 changes)
- [Increase minimum role in SPP to read policy yaml](https://gitlab.com/gitlab-org/security/gitlab/-/commit/6d5c2ea1feb6097cb5720650f39b3808554b6a29) ([merge request](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/4717))
- [Fix access to read code review analytics in private projects](https://gitlab.com/gitlab-org/security/gitlab/-/commit/4454c18d19d2d8df92520f4c0fafa24ddbf9fbe4) ([merge request](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/4757))
- [Escape work item dropdown items and restrict HTML tags](https://gitlab.com/gitlab-org/security/gitlab/-/commit/a834b94cf4e967065590f6b78b15c8733d67df30) ([merge request](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/4785))
- [Use stricter CSP values in the packages dependency proxy](https://gitlab.com/gitlab-org/security/gitlab/-/commit/d975b402434b9e17ff2963d9c4c6f438f52545ed) ([merge request](https://gitlab.com/gitlab-org/security/gitlab/-/merge_requests/4765))
## 17.7.5 (2025-02-21)
### Fixed (1 change)

View File

@ -1 +1 @@
afc35fcc49db7d999d74b4f2fcccc2625567bd75
efced52dc4e4f9f202e32dc6239573d4aceb4d4e

View File

@ -58,6 +58,11 @@ export default {
required: false,
default: '',
},
ariaLabelledBy: {
type: String,
required: false,
default: '',
},
},
data() {
return {
@ -158,6 +163,7 @@ export default {
:loading="isDropdownLoading"
:searching="isDropdownSearching"
:toggle-text="toggleText"
:toggle-aria-labelled-by="ariaLabelledBy"
@search="debouncedSearch"
@select="selectEnvironment"
@shown="toggleDropdownShown(true)"

View File

@ -482,16 +482,18 @@ export default {
</gl-alert>
<gl-form-group
:label="$options.i18n.type"
label-for="ci-variable-type"
label-class="!gl-pt-5 -gl-mb-5"
class="gl-border-none"
:class="{
'-gl-mb-5': !hideEnvironmentScope,
'-gl-mb-1': hideEnvironmentScope,
}"
>
<span id="ci-variable-type" class="gl-sr-only">{{ $options.i18n.type }}</span>
<gl-collapsible-listbox
v-model="variable.variableType"
:items="$options.variableOptions"
toggle-aria-labelled-by="ci-variable-type"
block
fluid-width
/>
@ -499,12 +501,12 @@ export default {
<gl-form-group
v-if="!hideEnvironmentScope"
class="-gl-mb-5 gl-border-none"
label-for="ci-variable-env"
label-class="!gl-pt-5 -gl-mb-5"
data-testid="environment-scope"
>
<template #label>
<div class="gl-flex gl-items-center">
<span class="gl-mr-2">
<span id="ci-variable-environments" class="gl-mr-2">
{{ $options.i18n.environments }}
</span>
<span
@ -533,6 +535,7 @@ export default {
</template>
<ci-environments-dropdown
v-if="areScopedVariablesAvailable"
aria-labelled-by="ci-variable-environments"
class="gl-mb-5"
:are-environments-loading="areEnvironmentsLoading"
:environments="environments"
@ -636,8 +639,8 @@ export default {
</gl-form-checkbox>
</gl-form-group>
<gl-form-group
label-for="ci-variable-description"
:label="$options.i18n.description"
label-for="ci-variable-description"
class="-gl-mb-5 gl-border-none"
data-testid="ci-variable-description-label"
:description="$options.i18n.descriptionHelpText"

View File

@ -1,4 +1,4 @@
import { isFunction } from 'lodash';
import { identity, isFunction } from 'lodash';
const defaultAttrs = {
td: { colspan: 1, rowspan: 1, colwidth: null, align: 'left' },
@ -194,10 +194,11 @@ export function preserveUnchanged(configOrRender) {
};
}
export function preserveUnchangedMark({ open, close, ...restConfig }) {
export function preserveUnchangedMark({ open, close, escape = true, ...restConfig }) {
// use a buffer to replace the content of the serialized mark with the sourceMarkdown
// when the mark is unchanged
let bufferStartPos = -1;
let esc;
function startBuffer(state) {
bufferStartPos = state.out.length;
@ -216,6 +217,11 @@ export function preserveUnchangedMark({ open, close, ...restConfig }) {
...restConfig,
// eslint-disable-next-line max-params
open: (state, mark, parent, index) => {
if (!escape) {
esc = state.esc;
state.esc = identity;
}
const same = state.options.changeTracker.get(mark);
if (same) {
@ -227,6 +233,10 @@ export function preserveUnchangedMark({ open, close, ...restConfig }) {
},
// eslint-disable-next-line max-params
close: (state, mark, parent, index) => {
if (!escape) {
state.esc = esc;
}
const { sourceMarkdown } = mark.attrs;
if (bufferStarted()) {

View File

@ -1,5 +1,6 @@
import { pickBy, identity } from 'lodash';
import { preserveUnchanged, openTag } from '../serialization_helpers';
import { escape, quote } from './link';
function getMediaSrc(node, useCanonicalSrc = true) {
const { canonicalSrc, src } = node.attrs;
@ -12,7 +13,7 @@ const image = preserveUnchanged({
render: (state, node) => {
const { alt, title, width, height, isReference, sourceMarkdown, sourceTagName } = node.attrs;
const realSrc = getMediaSrc(node, state.options.useCanonicalSrc);
const realSrc = escape(getMediaSrc(node, state.options.useCanonicalSrc));
// eslint-disable-next-line @gitlab/require-i18n-strings
if (realSrc.startsWith('data:') || realSrc.startsWith('blob:')) return;
@ -22,7 +23,7 @@ const image = preserveUnchanged({
state.write(openTag(sourceTagName, { src: realSrc, ...attrs }));
return;
}
const quotedTitle = title ? ` ${state.quote(title)}` : '';
const quotedTitle = title ? ` ${quote(title)}` : '';
const sourceExpression = isReference ? `[${realSrc}]` : `(${realSrc}${quotedTitle})`;
const sizeAttributes = [];
@ -35,7 +36,7 @@ const image = preserveUnchanged({
const attributes = sizeAttributes.length ? `{${sizeAttributes.join(' ')}}` : '';
state.write(`![${state.esc(alt || '')}]${sourceExpression}${attributes}`);
state.write(`![${escape(alt || '')}]${sourceExpression}${attributes}`);
}
},
inline: true,

View File

@ -25,6 +25,9 @@ const normalizeUrl = (url) => {
}
};
export const escape = (link) => link.replace(/[()"]/g, '\\$&');
export const quote = (title) => `"${title.replace(/"/g, '\\"')}"`;
/**
* This function detects whether a link should be serialized
* as an autolink.
@ -67,6 +70,7 @@ function getLinkHref(mark, useCanonicalSrc = true) {
}
const link = preserveUnchangedMark({
escape: false,
open(state, mark, parent) {
if (isAutoLink(mark, parent)) {
return isBracketAutoLink(mark.attrs.sourceMarkdown) ? '<' : '';
@ -78,11 +82,11 @@ const link = preserveUnchangedMark({
if (href.startsWith('data:') || href.startsWith('blob:')) return '';
const attrs = {
href: state.esc(getLinkHref(mark, state.options.useCanonicalSrc)),
href: escape(getLinkHref(mark, state.options.useCanonicalSrc)),
};
if (title) {
attrs.title = state.esc(title);
attrs.title = title;
}
if (sourceTagName && !sourceMarkdown) return openTag(sourceTagName, attrs);
@ -112,12 +116,12 @@ const link = preserveUnchangedMark({
}
if (isReference) {
return `][${state.esc(getLinkHref(mark, state.options.useCanonicalSrc))}]`;
return `][${escape(getLinkHref(mark, state.options.useCanonicalSrc))}]`;
}
if (isGollumLink) {
const text = getMarkText(mark, parent);
const escapedCanonicalSrc = state.esc(canonicalSrc);
const escapedCanonicalSrc = escape(canonicalSrc);
if (text.toLowerCase() === escapedCanonicalSrc.toLowerCase()) {
return ']]';
@ -126,8 +130,8 @@ const link = preserveUnchangedMark({
return `|${escapedCanonicalSrc}]]`;
}
return `](${state.esc(getLinkHref(mark, state.options.useCanonicalSrc))}${
title ? ` ${state.quote(title)}` : ''
return `](${escape(getLinkHref(mark, state.options.useCanonicalSrc))}${
title ? ` ${quote(title)}` : ''
})`;
},
});

View File

@ -108,11 +108,15 @@ export default {
return escape(suggestion);
},
},
mounted() {
this.renderGFM();
},
updated() {
this.renderGFM();
watch: {
note: {
async handler() {
await this.$nextTick();
this.renderGFM();
},
deep: true,
immediate: true,
},
},
methods: {
...mapActions([

View File

@ -1,16 +1,10 @@
import initCommitActions from '~/projects/commit';
import { initCommitBoxInfo } from '~/projects/commit_box/info';
import { renderHtmlStreams } from '~/streaming/render_html_streams';
import { toPolyfillReadable } from '~/streaming/polyfills';
import { createRapidDiffsApp } from '~/rapid_diffs/app';
initCommitBoxInfo();
initCommitActions();
const streamContainer = document.getElementById('js-stream-container');
if (streamContainer) {
const request = fetch(streamContainer.dataset.diffsStreamUrl);
renderHtmlStreams(
[request.then((response) => toPolyfillReadable(response.body))],
streamContainer,
);
}
const app = createRapidDiffsApp();
app.streamRemainingDiffs();
app.init();

View File

@ -18,7 +18,9 @@ import ZenMode from '~/zen_mode';
import '~/sourcegraph/load';
import DiffStats from '~/diffs/components/diff_stats.vue';
import { initReportAbuse } from '~/projects/report_abuse';
import * as popovers from '~/popovers';
popovers.initPopovers();
initDiffStatsDropdown();
new ZenMode();
addShortcutsExtension(ShortcutsNavigation);

View File

@ -3,6 +3,7 @@ import Vue from 'vue';
import PopoversComponent from './components/popovers.vue';
let app;
let isInitialized = false;
const APP_ELEMENT_ID = 'gl-popovers-app';
@ -32,13 +33,16 @@ const handlePopoverEvent = (rootTarget, e, selector) => {
};
export const initPopovers = () => {
['mouseenter', 'focus', 'click'].forEach((event) => {
document.addEventListener(
event,
(e) => handlePopoverEvent(document, e, '[data-toggle="popover"]'),
true,
);
});
if (!isInitialized) {
['mouseenter', 'focus', 'click'].forEach((event) => {
document.addEventListener(
event,
(e) => handlePopoverEvent(document, e, '[data-toggle="popover"]'),
true,
);
});
isInitialized = true;
}
return getPopoversApp();
};

View File

@ -69,7 +69,7 @@ export class DiffFile extends HTMLElement {
if (clickActionElement) {
const clickAction = clickActionElement.dataset.click;
this.adapters.forEach((adapter) =>
adapter.clicks?.[clickAction]?.call?.(this.adapterContext, event),
adapter.clicks?.[clickAction]?.call?.(this.adapterContext, event, clickActionElement),
);
}
this.trigger(events.CLICK, event);

View File

@ -1,44 +1,37 @@
import { getLines } from '~/rapid_diffs/expand_lines/get_lines';
import { DiffLineRow } from '~/rapid_diffs/expand_lines/diff_line_row';
const getLineNumber = (el) => parseInt(el.dataset.linenumber, 10);
const collectLineData = (element) => {
const buttons = element.querySelectorAll('[data-linenumber]');
const lineNumbers = Array.from(buttons).map(getLineNumber);
const previousEl = element.previousElementSibling;
const prevNewLine = previousEl?.querySelector('[data-linenumber]:last-child');
const prevNewLineNumber = prevNewLine ? getLineNumber(prevNewLine) : 0;
return [...lineNumbers, prevNewLineNumber];
};
const viewersMap = {
text_inline: 'text',
text_parallel: 'parallel',
const getSurroundingLines = (hunkHeaderRow) => {
const wrapperElements = Array.from(hunkHeaderRow.parentElement.children);
const rowIndex = wrapperElements.indexOf(hunkHeaderRow);
const lineBefore = wrapperElements.slice(0, rowIndex).findLast((el) => 'hunkLines' in el.dataset);
const lineAfter = wrapperElements
.slice(rowIndex, wrapperElements.length)
.find((el) => 'hunkLines' in el.dataset);
return [lineBefore, lineAfter].map((lineRow) => (lineRow ? new DiffLineRow(lineRow) : null));
};
export const ExpandLinesAdapter = {
clicks: {
async expandLines(event) {
const { target } = event;
const { expandPrevLine, expandNextLine } = target.dataset;
if (!expandPrevLine && !expandNextLine) return;
const parent = target.closest('tr');
if (parent.dataset.loading) return;
async expandLines(event, button) {
const { expandDirection } = button.dataset;
const hunkHeaderRow = button.closest('tr');
parent.dataset.loading = true;
if (hunkHeaderRow.dataset.loading) return;
hunkHeaderRow.dataset.loading = expandDirection;
button.setAttribute('disabled', 'disabled');
const { blobDiffPath } = this.data;
const { diffLinesPath } = this.data;
const lines = await getLines({
expandPrevLine,
lineData: collectLineData(parent),
blobDiffPath,
view: viewersMap[this.viewer],
expandDirection,
surroundingLines: getSurroundingLines(hunkHeaderRow),
diffLinesPath,
view: this.viewer === 'text_parallel' ? 'parallel' : undefined,
});
const method = expandPrevLine ? 'beforebegin' : 'afterend';
// eslint-disable-next-line no-unsanitized/method
parent.insertAdjacentHTML(method, lines);
parent.remove();
hunkHeaderRow.insertAdjacentHTML('afterend', lines);
hunkHeaderRow.remove();
},
},
};

View File

@ -0,0 +1,20 @@
export class DiffLineRow {
constructor(row) {
this.row = row;
}
#getLineNumber(position) {
const { lineNumber } = this.row.querySelector(
`[data-position="${position}"] [data-line-number]`,
).dataset;
return parseInt(lineNumber, 10);
}
get oldLineNumber() {
return this.#getLineNumber('old');
}
get newLineNumber() {
return this.#getLineNumber('new');
}
}

View File

@ -1,35 +1,68 @@
/**
* @typedef {import('./diff_line_row').DiffLineRow} DiffLineRow
*/
import axios from '~/lib/utils/axios_utils';
const UNFOLD_COUNT = 20;
// eslint-disable-next-line max-params
const getRequestParams = (expandPrevLine, oldLineNumber, newLineNumber, prevNewLineNumber) => {
const offset = newLineNumber - oldLineNumber;
let since;
let to;
let unfold = true;
if (!expandPrevLine) {
const lineNumber = newLineNumber + 1;
since = lineNumber;
to = lineNumber + UNFOLD_COUNT;
} else {
const lineNumber = newLineNumber - 1;
since = lineNumber - UNFOLD_COUNT;
to = lineNumber;
// make sure we aren't loading more than we need
if (since <= prevNewLineNumber + 1) {
since = prevNewLineNumber + 1;
unfold = false;
}
/**
* @typedef {'up' | 'down' | 'both'} ExpandDirection
* 'up' -
* 'down' -
* 'both' -
*/
/**
* @typedef {Object} RequestParams
* @property {boolean} unfold - Adds hunk header (contains expand buttons) to the returned HTML
* @property {number} since - Starting new line number for the line range
* @property {number} to - Ending new line number for the line range
* @property {boolean} bottom - Positions diff hunk header either before or after the lines
* @property {number} offset - The difference between new and old line numbers
* @property {number} [closest_line_number] - The next new line number near the existing diff hunk header
* 'closest_line_number' - this param helps backend understand which expand buttons should be shown: / or
*/
/**
* @param {ExpandDirection} expandDirection
* @param {[DiffLineRow, DiffLineRow]} surroundingLines
* @returns {RequestParams}
*/
const getRequestParams = (expandDirection, [lineBefore, lineAfter]) => {
switch (expandDirection) {
case 'both':
return {
unfold: false,
since: lineBefore.newLineNumber + 1,
to: lineAfter.newLineNumber - 1,
bottom: false,
offset: lineBefore.newLineNumber - lineBefore.oldLineNumber,
};
case 'up':
return {
unfold: true,
since: Math.max(lineAfter.newLineNumber - UNFOLD_COUNT - 1, 1),
to: lineAfter.newLineNumber - 1,
closest_line_number: lineBefore ? lineBefore.newLineNumber : 0,
offset: lineAfter.newLineNumber - lineAfter.oldLineNumber,
bottom: false,
};
case 'down':
return {
unfold: true,
since: lineBefore.newLineNumber + 1,
to: lineBefore.newLineNumber + UNFOLD_COUNT + 1,
closest_line_number: lineAfter ? lineAfter.newLineNumber : 0,
offset: lineBefore.newLineNumber - lineBefore.oldLineNumber,
bottom: true,
};
default:
// eslint-disable-next-line @gitlab/require-i18n-strings
throw new Error('Invalid expand option provided');
}
return { since, to, bottom: !expandPrevLine, offset, unfold };
};
export const getLines = async ({ expandPrevLine, lineData, blobDiffPath, view }) => {
const params = getRequestParams(expandPrevLine, ...lineData);
const { data: lines } = await axios.get(blobDiffPath, { params: { ...params, view } });
export const getLines = async ({ expandDirection, surroundingLines, diffLinesPath, view }) => {
const params = getRequestParams(expandDirection, surroundingLines);
const { data: lines } = await axios.get(diffLinesPath, { params: { ...params, view } });
return lines;
};

View File

@ -80,7 +80,7 @@ export default {
false;
this.commitMessage = data.project.mergeRequest.defaultMergeCommitMessage;
this.squashBeforeMerge = data.project.mergeRequest.squashOnMerge;
this.isSquashReadOnly = data.project.squashReadOnly;
this.isSquashReadOnly = data.project.mergeRequest.squashReadOnly;
this.squashCommitMessage = data.project.mergeRequest.defaultSquashCommitMessage;
}

View File

@ -4,8 +4,8 @@ fragment ReadyToMerge on Project {
id
onlyAllowMergeIfPipelineSucceeds
mergeRequestsFfOnlyEnabled
squashReadOnly
mergeRequest(iid: $iid) {
...ReadyToMergeMergeRequest
squashReadOnly
}
}

View File

@ -13,6 +13,7 @@ export const initProjectSelects = () => {
document.querySelectorAll(SELECTOR).forEach((el) => {
const {
label,
description,
inputName,
inputId,
groupId,
@ -34,6 +35,7 @@ export const initProjectSelects = () => {
props: {
label,
hasHtmlLabel,
description,
inputName,
inputId,
groupId,

View File

@ -30,6 +30,11 @@ export default {
type: String,
required: true,
},
description: {
type: String,
required: false,
default: '',
},
hasHtmlLabel: {
type: Boolean,
required: false,
@ -168,6 +173,7 @@ export default {
<template>
<entity-selector
:label="label"
:description="description"
:input-name="inputName"
:input-id="inputId"
:initial-selection="initialSelection"

View File

@ -1,6 +1,6 @@
<script>
import { GlTokenSelector, GlAlert } from '@gitlab/ui';
import { debounce } from 'lodash';
import { debounce, escape } from 'lodash';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { isNumeric } from '~/lib/utils/number_utils';
@ -208,11 +208,13 @@ export default {
});
},
formatResults(input) {
const escapedInput = escape(input);
if (!this.searchTerm) {
return input;
return escapedInput;
}
return highlighter(`<span class="gl-text-default">${input}</span>`, this.searchTerm);
return highlighter(`<span class="gl-text-default">${escapedInput}</span>`, this.searchTerm);
},
unsetError() {
this.error = '';
@ -233,6 +235,7 @@ export default {
noMatchesFoundMessage: I18N_WORK_ITEM_NO_MATCHES_FOUND,
addInputPlaceholder: I18N_WORK_ITEM_SEARCH_INPUT_PLACEHOLDER,
},
safeHtmlConfig: { ADD_TAGS: ['strong', 'span'] },
};
</script>
<template>
@ -262,10 +265,13 @@ export default {
<template #dropdown-item-content="{ dropdownItem }">
<div class="gl-flex">
<div
v-safe-html="formatResults(dropdownItem.iid)"
v-safe-html:[$options.safeHtmlConfig]="formatResults(dropdownItem.iid)"
class="gl-mr-4 gl-text-sm gl-text-subtle"
></div>
<div v-safe-html="formatResults(dropdownItem.title)" class="gl-truncate"></div>
<div
v-safe-html:[$options.safeHtmlConfig]="formatResults(dropdownItem.title)"
class="gl-truncate"
></div>
</div>
</template>
<template #no-results-content>

View File

@ -26,6 +26,8 @@
}
.rd-hunk-header {
// this is used when a hunk header doesn't have any text, only expand buttons
min-height: calc(1em * $code-line-height);
border-top: 1px solid var(--rd-hunk-header-border-color, $gray-100);
border-bottom: 1px solid var(--rd-hunk-header-border-color, $gray-100);
background-color: var(--rd-hunk-header-background-color, $gray-50);
@ -40,6 +42,18 @@
}
}
.rd-hunk-header[data-loading=both] [data-visible-when=loading],
.rd-hunk-header[data-loading=up] [data-expand-direction=up] [data-visible-when=loading],
.rd-hunk-header[data-loading=down] [data-expand-direction=down] [data-visible-when=loading] {
display: block;
}
.rd-hunk-header[data-loading=both] [data-visible-when=idle],
.rd-hunk-header[data-loading=up] [data-expand-direction=up] [data-visible-when=idle],
.rd-hunk-header[data-loading=down] [data-expand-direction=down] [data-visible-when=idle] {
display: none;
}
.rd-hunk-header-parallel,
.rd-hunk-lines-parallel, {
grid-template-columns: 50px 1fr 50px 1fr;
@ -62,7 +76,12 @@
.rd-expand-lines-button {
@include common.diff-expansion($gray-100, $gray-700, $gray-200, $gray-800);
display: block;
display: flex;
justify-content: center;
align-items: center;
// whitespace inside button increases the minimum size of the row
// this causes jumps when the icons change from idle to loading
font-size: 0;
border: 0;
background-color: var(--rd-expand-lines-button-background-color, $gray-100);
@ -75,6 +94,10 @@
}
}
.rd-expand-lines-button [data-visible-when=loading] {
display: none;
}
.rd-line-number {
padding: 0 10px 0 5px;
text-align: right;

View File

@ -18,7 +18,7 @@ module RapidDiffs
params = tree_join(@diff_file.content_sha, @diff_file.file_path)
{
viewer: viewer_component.viewer_name,
blob_diff_path: project_blob_diff_path(project, params)
diff_lines_path: project_blob_diff_lines_path(project, params)
}
end

View File

@ -1,3 +1,6 @@
- @directions.each do |direction|
%button.rd-expand-lines-button{ type: "button", data: { click: 'expandLines' } }
= helpers.sprite_icon(icon_name(direction))
%button.rd-expand-lines-button{ type: "button", data: { click: 'expandLines', expand_direction: direction } }
%span{ data: { visible_when: 'idle' } }
= helpers.sprite_icon(icon_name(direction))
%span{ data: { visible_when: 'loading' } }
= helpers.gl_loading_icon(size: 'sm', inline: true)

View File

@ -5,7 +5,7 @@
- if @diff_hunk.lines
- @diff_hunk.lines.each do |line|
%tr.rd-hunk-lines.rd-hunk-lines-inline{ data: { testid: testid } }
%tr.rd-hunk-lines.rd-hunk-lines-inline{ data: { testid: 'hunk-lines-inline', hunk_lines: true } }
= render RapidDiffs::Viewers::Text::LineNumberComponent.new(file_hash: @file_hash, file_path: @file_path, line: line, position: :old)
= render RapidDiffs::Viewers::Text::LineNumberComponent.new(file_hash: @file_hash, file_path: @file_path, line: line, position: :new, border: :right)
= render RapidDiffs::Viewers::Text::LineContentComponent.new(line: line, position: nil)

View File

@ -11,10 +11,6 @@ module RapidDiffs
@file_hash = file_hash
@file_path = file_path
end
def testid
'hunk-lines-inline'
end
end
end
end

View File

@ -1,5 +1,5 @@
- if visible?
%td.rd-line-number{ id: id, class: border_class, data: { legacy_id: legacy_id, change: change_type } }
%td.rd-line-number{ id: id, class: border_class, data: { legacy_id: legacy_id, change: change_type, position: @position } }
= link_to '', "##{id}", { class: 'rd-line-link', data: { line_number: line_number }, aria: { label: s_('Line number %{number}').html_safe % { number: line_number } } }
- else
%td.rd-line-number{ class: border_class, data: { change: change_type } }

View File

@ -5,7 +5,7 @@
%td.rd-hunk-header-content{ data: { position: index == 0 ? :old : :new }, tabindex: '-1' }= @diff_hunk.header.text
- @diff_hunk.parallel_lines.each do |pair|
%tr.rd-hunk-lines.rd-hunk-lines-parallel{ data: { testid: testid } }
%tr.rd-hunk-lines.rd-hunk-lines-parallel{ data: { testid: 'hunk-lines-parallel', hunk_lines: true } }
- sides(pair).each do |side|
- line, position = side.values_at(:line, :position)
= render RapidDiffs::Viewers::Text::LineNumberComponent.new(file_hash: @file_hash, file_path: @file_path, **side)

View File

@ -26,10 +26,6 @@ module RapidDiffs
}
]
end
def testid
'hunk-lines-parallel'
end
end
end
end

View File

@ -105,7 +105,8 @@ class Clusters::ClustersController < ::Clusters::BaseController
response = Clusters::Migration::CreateService.new(
cluster.cluster,
current_user: current_user,
configuration_project_id: migrate_params[:configuration_project_id]
configuration_project_id: migrate_params[:configuration_project_id],
agent_name: migrate_params[:agent_name]
).execute
if response.success?
@ -120,7 +121,7 @@ class Clusters::ClustersController < ::Clusters::BaseController
private
def migrate_params
params.permit(:configuration_project_id)
params.require(:cluster_migration).permit(:configuration_project_id, :agent_name)
end
def ensure_feature_enabled!

View File

@ -0,0 +1,28 @@
# frozen_string_literal: true
module EventForward
class EventForwardController < BaseActionController
def forward
process_events
head :ok
end
private
def process_events
payload = Gitlab::Json.parse(request.raw_post)
tracker = Gitlab::Tracking.tracker
payload['data'].each do |event|
tracker.emit_event_payload(event)
end
logger.info("Enqueued events for forwarding. Count: #{payload['data'].size}")
end
def logger
@logger ||= EventForward::Logger.build
end
end
end

View File

@ -0,0 +1,9 @@
# frozen_string_literal: true
module EventForward
class Logger < ::Gitlab::JsonLogger
def self.file_name_noext
'event_collection'
end
end
end

View File

@ -15,9 +15,7 @@ class ProfilesController < Profiles::ApplicationController
:reset_static_object_token, :update_username]
def reset_incoming_email_token
Users::UpdateService.new(current_user, user: @user).execute! do |user|
user.reset_incoming_email_token!
end
Users::UpdateService.new(current_user, user: @user).execute!(&:reset_incoming_email_token!)
flash[:notice] = s_("Profiles|Incoming email token was successfully reset")
@ -37,9 +35,7 @@ class ProfilesController < Profiles::ApplicationController
end
def reset_static_object_token
Users::UpdateService.new(current_user, user: @user).execute! do |user|
user.reset_static_object_token!
end
Users::UpdateService.new(current_user, user: @user).execute!(&:reset_static_object_token!)
redirect_to user_settings_personal_access_tokens_path,
notice: s_('Profiles|Static object token was successfully reset')

View File

@ -161,6 +161,7 @@ class Projects::CommitController < Projects::ApplicationController
return render_404 unless ::Feature.enabled?(:rapid_diffs, current_user, type: :wip)
streaming_offset = 5
@reload_stream_url = diffs_stream_url(@commit)
@stream_url = diffs_stream_url(@commit, streaming_offset, diff_view)
@diffs_slice = @commit.first_diffs_slice(streaming_offset, commit_diff_options)

View File

@ -0,0 +1,22 @@
# frozen_string_literal: true
module Resolvers
module Repositories
class CommitResolver < BaseResolver
type Types::Repositories::CommitType, null: true
argument :ref,
GraphQL::Types::String,
required: true,
description: "Commit reference (SHA, branch name, or tag name)."
calls_gitaly!
alias_method :repository, :object
def resolve(ref:)
repository.commit(ref)
end
end
end
end

View File

@ -11,6 +11,10 @@ module Types
field :branch_names, [GraphQL::Types::String], null: true, calls_gitaly: true,
complexity: 170, description: 'Names of branches available in this repository that match the search pattern.',
resolver: Resolvers::RepositoryBranchNamesResolver
field :commit, Types::Repositories::CommitType, null: true,
calls_gitaly: true,
description: 'Commit from the repository.',
resolver: Resolvers::Repositories::CommitResolver
field :disk_path, GraphQL::Types::String,
description: 'Shows a disk path of the repository.',
null: true,

View File

@ -101,6 +101,17 @@ module ClustersHelper
can?(user, :admin_cluster, cluster)
end
def migration_alert_config(migration)
return unless migration
status = migration.agent_install_status.to_sym
config = migration_alert_configs[status]
return config unless config && status == :error && migration.agent_install_message.present?
config.merge(details: migration.agent_install_message)
end
private
def default_branch_name(clusterable)
@ -110,4 +121,23 @@ module ClustersHelper
def clusterable_project_path(clusterable)
clusterable.full_path if clusterable.is_a?(Project)
end
def migration_alert_configs
{
in_progress: {
variant: :info,
message: s_('ClusterIntegration|Installing agent in progress.')
},
success: {
variant: :success,
message: s_('ClusterIntegration|The agent connection is set up.')
},
error: {
variant: :warning,
title: s_('ClusterIntegration|Agent setup failed'),
message: s_('ClusterIntegration|The agent was not installed in the cluster.'),
show_help: true
}
}.freeze
end
end

View File

@ -4,6 +4,8 @@ module Clusters
class AgentMigration < ApplicationRecord
self.table_name = 'cluster_agent_migrations'
attr_accessor :agent_name
belongs_to :cluster, optional: false, class_name: 'Clusters::Cluster'
belongs_to :project, optional: false, class_name: '::Project'
belongs_to :agent, optional: false, class_name: 'Clusters::Agent'

View File

@ -608,7 +608,7 @@ class Commit
def first_diffs_slice(limit, diff_options = {})
diff_options[:max_files] = limit
diffs(diff_options)
diffs(diff_options).diff_files
end
private

View File

@ -9,7 +9,7 @@ module CachedCommit
end
end
# We don't save these, because they would need a table or a serialised
# We don't save these, because they would need a table or a serialized
# field. They aren't used anywhere, so just pretend the commit has no parents.
def parent_ids
[]

View File

@ -220,7 +220,7 @@ class ContainerRepository < ApplicationRecord
def delete_tags!
return unless has_tags?
digests = tags.map { |tag| tag.digest }.compact.to_set
digests = tags.map(&:digest).compact.to_set
digests.map { |digest| delete_tag(digest) }.all?
end

View File

@ -53,7 +53,7 @@ class Discussion
notes = model_class.where(discussion_id: discussion_ids).fresh
notes = notes.inc_note_diff_file if preload_note_diff_file
grouped_notes = notes.group_by { |n| n.discussion_id }
grouped_notes = notes.group_by(&:discussion_id)
grouped_notes.transform_values { |notes| Discussion.build(notes, context_noteable) }
end

View File

@ -93,9 +93,7 @@ module Integrations
def prometheus_available?
return false unless project
project.all_clusters.enabled.eager_load(:integration_prometheus).any? do |cluster|
cluster.integration_prometheus_available?
end
project.all_clusters.enabled.eager_load(:integration_prometheus).any?(&:integration_prometheus_available?)
end
def allow_local_api_url?

View File

@ -27,9 +27,7 @@ class ProjectMember < Member
ProjectMember.transaction do
members = ProjectMember.where(source_id: project_ids)
members.each do |member|
member.destroy
end
members.each(&:destroy)
end
true

View File

@ -5,8 +5,6 @@ module Packages
class PackageRevision < ApplicationRecord
include ShaAttribute
REVISION_LENGTH_MAX = 40
sha_attribute :revision
belongs_to :package, class_name: 'Packages::Conan::Package', inverse_of: :conan_package_revisions
@ -17,8 +15,8 @@ module Packages
has_many :file_metadata, inverse_of: :package_revision, class_name: 'Packages::Conan::FileMetadatum'
validates :package, :package_reference, :project, presence: true
validates :revision, presence: true, bytesize: { maximum: -> { REVISION_LENGTH_MAX } },
uniqueness: { scope: [:package_id, :package_reference_id] }
validates :revision, presence: true, uniqueness: { scope: [:package_id, :package_reference_id] },
format: { with: ::Gitlab::Regex.conan_revision_regex_v2 }
end
end
end

View File

@ -5,8 +5,6 @@ module Packages
class RecipeRevision < ApplicationRecord
include ShaAttribute
REVISION_LENGTH_MAX = 40
sha_attribute :revision
belongs_to :package, class_name: 'Packages::Conan::Package', inverse_of: :conan_recipe_revisions
@ -17,8 +15,8 @@ module Packages
has_many :file_metadata, inverse_of: :recipe_revision, class_name: 'Packages::Conan::FileMetadatum'
validates :package, :project, presence: true
validates :revision, presence: true, bytesize: { maximum: -> { REVISION_LENGTH_MAX } },
uniqueness: { scope: :package_id }
validates :revision, presence: true,
uniqueness: { scope: :package_id }, format: { with: ::Gitlab::Regex.conan_revision_regex_v2 }
end
end
end

View File

@ -14,7 +14,7 @@ module Preloaders
def preload_all
merge_request_diffs = MergeRequestDiff.latest_diff_for_merge_requests(@merge_requests)
cache = merge_request_diffs.index_by { |diff| diff.merge_request_id }
cache = merge_request_diffs.index_by(&:merge_request_id)
@merge_requests.each do |merge_request|
merge_request_diff = cache[merge_request.id]

View File

@ -152,7 +152,7 @@ class Release < ApplicationRecord
end
def milestone_titles
self.milestones.order_by_dates_and_title.map { |m| m.title }.join(', ')
self.milestones.order_by_dates_and_title.map(&:title).join(', ')
end
def to_hook_data(action)

View File

@ -65,6 +65,10 @@ module Clusters
}
end
def agent_migration_for_display
cluster.agent_migration || Clusters::AgentMigration.new(cluster: cluster)
end
private
def image_path(path)

View File

@ -3,13 +3,14 @@
module Clusters
module Migration
class CreateService
attr_reader :cluster, :clusterable, :current_user, :configuration_project
attr_reader :cluster, :clusterable, :current_user, :configuration_project, :agent_name
def initialize(cluster, current_user:, configuration_project_id:)
def initialize(cluster, current_user:, configuration_project_id:, agent_name:)
@cluster = cluster
@clusterable = cluster.clusterable
@current_user = current_user
@configuration_project = find_configuration_project(configuration_project_id)
@agent_name = agent_name
end
def execute
@ -27,7 +28,8 @@ module Clusters
migration = Clusters::AgentMigration.new(
cluster: cluster,
agent: agent,
project: configuration_project
project: configuration_project,
agent_name: agent_name
)
if migration.save
@ -41,11 +43,11 @@ module Clusters
def validate_inputs
message = if !feature_enabled?
'Feature disabled'
_('Feature disabled')
elsif !current_user.can?(:admin_cluster, cluster)
'Unauthorized'
_('Unauthorized')
elsif configuration_project.nil?
'Invalid configuration project'
s_('ClusterIntegration|Invalid configuration project')
end
error_response(message: message) if message
@ -74,10 +76,6 @@ module Clusters
clusterable.root_ancestor.all_projects.find_by_id(project_id)
end
def agent_name
cluster.name.first(63).parameterize
end
def feature_enabled?
Feature.enabled?(:cluster_agent_migrations, clusterable)
end

View File

@ -1,12 +1,72 @@
- if can_admin_cluster?(current_user, @cluster)
.settings.expanded.border-0.m-0
- cluster_migration = @cluster.agent_migration_for_display
%h4.gl-mt-0= s_('ClusterIntegration|Migrate to GitLab Agent for Kubernetes')
- tag_pair_agent_docs = tag_pair(link_to('', help_page_path('user/clusters/agent/_index.md'), target: '_blank', rel: 'noopener noreferrer'), :agent_docs_link_start, :agent_docs_link_end)
- tag_pair_install_docs = tag_pair(link_to('', help_page_path('user/clusters/agent/install/_index.md'), target: '_blank', rel: 'noopener noreferrer'), :install_docs_link_start, :install_docs_link_end)
%p
= safe_format(s_('ClusterIntegration|The %{agent_docs_link_start}GitLab Agent for Kubernetes %{agent_docs_link_end} offers improved security, reliability, and functionality. Follow the steps below to create a new agent and migrate your existing certificate-based integration. The process is automated, but you still need to %{install_docs_link_start}install the agent%{install_docs_link_end} in your cluster.') , tag_pair_agent_docs, tag_pair_install_docs)
= link_to s_('ClusterIntegration|How do I migrate to the GitLab agent?'), help_page_path('user/infrastructure/clusters/migrate_to_gitlab_agent.md'), target: '_blank', rel: 'noopener noreferrer'
%h5= s_('ClusterIntegration|Step 1. Connect the agent')
- if (config = migration_alert_config(cluster_migration))
= render Pajamas::AlertComponent.new(title: config[:title],
variant: config[:variant],
alert_options: { class: 'gl-mb-5' }) do |c|
= c.with_body do
= config[:message]
- if config[:details].present?
= config[:details]
- if config[:show_help]
- c.with_actions do
= link_to s_('ClusterIntegration|Learn more about migrating to GitLab Agent'),
help_page_path('user/infrastructure/clusters/migrate_to_gitlab_agent.md'),
target: '_blank',
rel: 'noopener noreferrer'
- agent = cluster_migration&.agent
- project = cluster_migration&.project
- if agent.present?
%p.gl-font-bold.gl-mb-2
= s_('ClusterIntegration|Project name')
%p
= s_('ClusterIntegration|Migrate this cluster to use the GitLab agent for Kubernetes')
.settings-content#migrate-section
.sub-section.form-group
%h4
= s_('ClusterIntegration|Migrate to the GitLab agent for Kubernetes')
%p
= s_("ClusterIntegration|This cluster integration is deprecated. To continue using this Kubernetes cluster with GitLab, you must install the agent.")
= render Pajamas::ButtonComponent.new(method: :post, href: clusterable.create_cluster_migration_path(@cluster)) do
= s_('ClusterIntegration|Install agent')
= link_to project.full_name, project_path(project)
%p.gl-font-bold.gl-mb-2
= s_('ClusterIntegration|Agent name')
%p
- agent_link_name = "#{agent.name}##{agent.id}"
= link_to agent_link_name, project_cluster_agent_path(project, agent.name)
- else
- group_id = @cluster.group.id if @cluster.group_type?
- if @cluster.project_type?
- group_id = @cluster.project.group.id if @cluster.project.group
- user_id = @cluster.project.namespace.owner_id unless group_id
= gitlab_ui_form_for cluster_migration, url: clusterable.create_cluster_migration_path(@cluster), html: { class: 'fieldset-form' }, data: { testid: 'cluster-migration-form' }, method: :post do |f|
.form-group{ class: 'md:gl-w-1/2' }
.js-vue-project-select{ data: { label: s_('ClusterIntegration|Project name'),
description: s_('ClusterIntegration|Select a project for the GitLab Agent.'),
input_name: 'cluster_migration[configuration_project_id]',
input_id: 'cluster_migration_configuration_project_id',
order_by: 'last_activity_at',
group_id: group_id,
user_id: user_id,
with_shared: true.to_s,
include_subgroups: true.to_s,
membership: true.to_s,
selected: @cluster.management_project_id } }
.form-group.-gl-mt-2{ class: 'md:gl-w-1/2' }
= f.label :agent_name, s_('ClusterIntegration|Agent name'), class: 'label-bold'
= f.text_field :agent_name, name: 'cluster_migration[agent_name]', class: 'form-control gl-form-input', placeholder: s_('ClusterIntegration|New agent name')
.form-text.gl-text-subtle
= s_('ClusterIntegration|Enter a unique name for your new GitLab Agent. This name will be used to identify the agent in your project.')
= f.submit s_('ClusterIntegration|Create agent and migrate'), pajamas_button: true

View File

@ -2,4 +2,5 @@
- if Feature.enabled?(:cluster_agent_migrations, clusterable) && can_admin_cluster?(current_user, @cluster)
= gl_tab_link_to clusterable.cluster_path(@cluster.id, params: { tab: 'migrate' }), { item_active: active } do
= sprite_icon('warning', css_class: 'gl-mr-2')
= s_('ClusterIntegration|Migrate')

View File

@ -32,4 +32,4 @@
= link_to(_('Learn about signing commits'), help_page_path('user/project/repository/signed_commits/_index.md'), class: 'gl-link gl-block gl-mt-3')
= gl_badge_tag(label, { variant: variant, icon: icon, href: '#' }, { class: 'signature-badge gl-inline-flex gl-ml-4 gl-align-middle', role: 'button', tabindex: 0, data: { toggle: 'popover', html: 'true', placement: 'bottom', title: title, content: content } })
= gl_badge_tag(label, { variant: variant, icon: icon, href: '#' }, { class: 'signature-badge gl-inline-flex gl-ml-4 gl-align-middle', role: 'button', tabindex: 0, data: { toggle: 'popover', html: 'true', triggers: 'click blur', placement: 'bottom', title: title, content: content} })

View File

@ -11,7 +11,5 @@
.container-fluid{ class: [container_class] }
= render "commit_box"
= render "ci_menu"
.code{ class: user_color_scheme }
= render RapidDiffs::DiffFileComponent.with_collection(@diffs_slice.diff_files, parallel_view: diff_view == :parallel)
- if @stream_url
#js-stream-container{ data: { diffs_stream_url: @stream_url } }
- args = { diffs_slice: @diffs_slice, reload_stream_url: @reload_stream_url, stream_url: @stream_url, show_whitespace: @show_whitespace_default, diff_view: @diff_view, update_user_endpoint: @update_current_user_path, metadata_endpoint: @endpoint_metadata_url }
= render ::RapidDiffs::AppComponent.new(**args)

View File

@ -27,8 +27,11 @@ module ResourceAccessTokens
.select(1)
.where('"personal_access_tokens"."user_id" = "users"."id"')
.and(
PersonalAccessToken.expired_before(cut_off).or(PersonalAccessToken.revoked_before(cut_off))
.invert_where
PersonalAccessToken.active
.or(
PersonalAccessToken.expired_before(cut_off).or(PersonalAccessToken.revoked_before(cut_off))
.invert_where
)
)
)

View File

@ -242,6 +242,8 @@ InitializerConnections.raise_if_new_database_connection do
post '/track_namespace_visits' => 'users/namespace_visits#create'
get '/external_redirect' => 'external_redirect/external_redirect#index'
post '/collect_events', to: 'event_forward/event_forward#forward', as: :event_forwarding
end
# End of the /-/ scope.

View File

@ -0,0 +1,24 @@
- title: "Coverage-guided fuzz testing is deprecated"
removal_milestone: "19.0"
announcement_milestone: "18.0"
breaking_change: true
window: 1
reporter: mikeeddington
stage: application security testing
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/517841
impact: high
scope: project
resolution_role: Owner
manual_task: false
body: | # (required) Don't change this line.
Coverage-guided fuzz testing is deprecated and will not be supported
from GitLab 18.0. The feature will be completely removed in GitLab 19.0.
Coverage-guided fuzz testing integrated several open-source fuzzers into GitLab.
If you are impacted, you can integrate your open-source fuzzers as standalone applications,
or migrate to another security feature like [GitLab Advanced SAST](https://docs.gitlab.com/ee/user/application_security/sast/gitlab_advanced_sast.html).
end_of_support_milestone: 18.0
tiers: [Ultimate]
documentation_url: https://docs.gitlab.com/ee/user/application_security/coverage_fuzzing/
image_url:
video_url:

View File

@ -0,0 +1,24 @@
# frozen_string_literal: true
class NewFkForWorkItemTypeCustomFieldsWorkItemTypeId < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
milestone '17.10'
NEW_CONSTRAINT_NAME = 'fk_work_item_type_custom_fields_on_work_item_type_id'
def up
add_concurrent_foreign_key :work_item_type_custom_fields,
:work_item_types,
column: :work_item_type_id,
name: NEW_CONSTRAINT_NAME
end
def down
with_lock_retries do
remove_foreign_key_if_exists :work_item_type_custom_fields,
:work_item_types,
column: :work_item_type_id,
name: NEW_CONSTRAINT_NAME
end
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
class DropOldFkForWorkItemTypeCustomFieldsWorkItemTypeId < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
milestone '17.10'
OLD_CONSTRAINT_NAME = 'fk_9447fad7b4'
def up
with_lock_retries do
remove_foreign_key_if_exists :work_item_type_custom_fields,
:work_item_types,
column: :work_item_type_id,
on_delete: :cascade,
name: OLD_CONSTRAINT_NAME
end
end
def down
add_concurrent_foreign_key :work_item_type_custom_fields,
:work_item_types,
column: :work_item_type_id,
target_column: :correct_id,
on_delete: :cascade
end
end

View File

@ -0,0 +1,24 @@
# frozen_string_literal: true
class NewFkForWorkItemTypeUserPreferencesWorkItemTypeId < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
milestone '17.10'
NEW_CONSTRAINT_NAME = 'fk_work_item_type_user_preferences_on_work_item_type_id'
def up
add_concurrent_foreign_key :work_item_type_user_preferences,
:work_item_types,
column: :work_item_type_id,
name: NEW_CONSTRAINT_NAME
end
def down
with_lock_retries do
remove_foreign_key_if_exists :work_item_type_user_preferences,
:work_item_types,
column: :work_item_type_id,
name: NEW_CONSTRAINT_NAME
end
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
class DropOldFkForWorkItemTypeUserPreferencesWorkItemTypeId < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
milestone '17.10'
OLD_CONSTRAINT_NAME = 'fk_79e0353950'
def up
with_lock_retries do
remove_foreign_key_if_exists :work_item_type_user_preferences,
:work_item_types,
column: :work_item_type_id,
on_delete: :cascade,
name: OLD_CONSTRAINT_NAME
end
end
def down
add_concurrent_foreign_key :work_item_type_user_preferences,
:work_item_types,
column: :work_item_type_id,
target_column: :correct_id,
on_delete: :cascade
end
end

View File

@ -0,0 +1 @@
844ab7d792599f4f2e3da9ad2bc4a182b9d15947ca703ad00f31e4602261cd3f

View File

@ -0,0 +1 @@
50efa17bf234df2e972eeb81b4d9897b496655e79162bc6d78c9c99b7a39c259

View File

@ -0,0 +1 @@
d5b47a465e11070c8a35712609a787f695e4236d6596503ff17a32c5c1bf51d1

View File

@ -0,0 +1 @@
e4f05e6255bed30ce5a19679fd9b5bb0652f5ef302dcdec629532be11b1c9599

View File

@ -39627,9 +39627,6 @@ ALTER TABLE ONLY topics
ALTER TABLE ONLY work_item_text_field_values
ADD CONSTRAINT fk_79c719630f FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY work_item_type_user_preferences
ADD CONSTRAINT fk_79e0353950 FOREIGN KEY (work_item_type_id) REFERENCES work_item_types(correct_id) ON DELETE CASCADE;
ALTER TABLE ONLY packages_maven_metadata
ADD CONSTRAINT fk_7a170ee0a3 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
@ -39807,9 +39804,6 @@ ALTER TABLE ONLY todos
ALTER TABLE ONLY packages_debian_group_architectures
ADD CONSTRAINT fk_92714bcab1 FOREIGN KEY (group_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY work_item_type_custom_fields
ADD CONSTRAINT fk_9447fad7b4 FOREIGN KEY (work_item_type_id) REFERENCES work_item_types(correct_id) ON DELETE CASCADE;
ALTER TABLE ONLY workspaces_agent_configs
ADD CONSTRAINT fk_94660551c8 FOREIGN KEY (cluster_agent_id) REFERENCES cluster_agents(id) ON DELETE CASCADE;
@ -42729,6 +42723,12 @@ ALTER TABLE ONLY work_item_related_link_restrictions
ALTER TABLE ONLY work_item_related_link_restrictions
ADD CONSTRAINT fk_work_item_related_link_restrictions_target_type_id FOREIGN KEY (target_type_id) REFERENCES work_item_types(id) ON UPDATE CASCADE ON DELETE CASCADE;
ALTER TABLE ONLY work_item_type_custom_fields
ADD CONSTRAINT fk_work_item_type_custom_fields_on_work_item_type_id FOREIGN KEY (work_item_type_id) REFERENCES work_item_types(id) ON DELETE CASCADE;
ALTER TABLE ONLY work_item_type_user_preferences
ADD CONSTRAINT fk_work_item_type_user_preferences_on_work_item_type_id FOREIGN KEY (work_item_type_id) REFERENCES work_item_types(id) ON DELETE CASCADE;
ALTER TABLE ONLY work_item_widget_definitions
ADD CONSTRAINT fk_work_item_widget_definitions_work_item_type_id FOREIGN KEY (work_item_type_id) REFERENCES work_item_types(id) ON UPDATE CASCADE ON DELETE CASCADE;

View File

@ -74,6 +74,7 @@ Azure
B-tree
backfilling
backfills
backoff
backport
backported
backporting
@ -182,9 +183,10 @@ Coinbase
colocate
colocated
colocating
Colorama
Command Palette
commit's
committer's
Command Palette
CommonMark
compilable
composable
@ -252,6 +254,7 @@ deduplicated
deduplicates
deduplicating
deduplication
Deepin
delegators
deliverables
denormalization
@ -378,6 +381,7 @@ Flutterwave
Flycheck
focusable
Forgerock
Forky
formatters
Fortanix
Fortinet
@ -515,6 +519,7 @@ kaniko
Karma
Kata
KCachegrind
keepalive
Kerberos
KEV
Keycloak
@ -549,6 +554,7 @@ Lemmy
libFuzzer
Libgcrypt
Libravatar
LinuxMint
liveness
LLM
LLMs
@ -567,6 +573,7 @@ Lookbook
lookups
loopback
LSP
Lts
Lua
Lucene
Lucidchart
@ -650,6 +657,7 @@ nosniff
noteable
noteables
npm
NTFSSecurity
NuGet
nullability
nullable
@ -664,7 +672,6 @@ offboarding
offboards
OIDs
OKRs
OKRs
Okta
OLM
OmniAuth
@ -681,6 +688,7 @@ OSs
OTel
outdent
Overcommit
Packagecloud
Packagist
packfile
packfiles
@ -1069,6 +1077,7 @@ triaged
triages
triaging
Trivy
Trixie
Truststore
truthy
Twilio
@ -1080,6 +1089,11 @@ Ubuntu
Udemy
UI
UIDs
ulimit
Ulyana
Ulyssa
Uma
Una
unapplied
unapprove
unapproved
@ -1234,7 +1248,9 @@ worktree
worktrees
Worldline
Xcode
Xenial
Xeon
Xerus
XPath
Yandex
YouTrack

View File

@ -204,7 +204,7 @@ The following metrics are available:
| `gitlab_rack_attack_throttle_limit` | Gauge | 17.6 | Reports the maximum number of requests that a client can make before Rack Attack throttles them. | `event_name` |
| `gitlab_rack_attack_throttle_period_seconds` | Gauge | 17.6 | Reports the duration over which requests for a client are counted before Rack Attack throttles them. | `event_name` |
| `gitlab_application_rate_limiter_throttle_utilization_ratio` | Histogram | 17.6 | Utilization ratio of a throttle in GitLab Application Rate Limiter. | `throttle_key`, `peek`, `feature_category` |
| `search_zoekt_task_processing_queue_size` | Gauge | 17.9 | Number of tasks waiting to be processed by Zoekt. | |
| `search_zoekt_task_processing_queue_size` | Gauge | 17.9 | Number of tasks waiting to be processed by Zoekt. | `node_name` |
## Metrics controlled by a feature flag

View File

@ -36350,6 +36350,18 @@ Returns [`String`](#string).
| ---- | ---- | ----------- |
| <a id="repositorycodeownerspathref"></a>`ref` | [`String`](#string) | Name of the ref. |
##### `Repository.commit`
Commit from the repository.
Returns [`Commit`](#commit).
###### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="repositorycommitref"></a>`ref` | [`String!`](#string) | Commit reference (SHA, branch name, or tag name). |
##### `Repository.paginatedTree`
Paginated tree of the repository.

View File

@ -36,132 +36,132 @@ Predefined variables become available at three different phases of pipeline exec
## Predefined variables
| Variable | Availability | Description |
|-------------------------------------------------|--------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `CHAT_CHANNEL` | Pipeline | The Source chat channel that triggered the [ChatOps](../chatops/_index.md) command. |
| `CHAT_INPUT` | Pipeline | The additional arguments passed with the [ChatOps](../chatops/_index.md) command. |
| `CHAT_USER_ID` | Pipeline | The chat service's user ID of the user who triggered the [ChatOps](../chatops/_index.md) command. |
| `CI` | Pre-pipeline | Available for all jobs executed in CI/CD. `true` when available. |
| `CI_API_V4_URL` | Pre-pipeline | The GitLab API v4 root URL. |
| `CI_API_GRAPHQL_URL` | Pre-pipeline | The GitLab API GraphQL root URL. Introduced in GitLab 15.11. |
| `CI_BUILDS_DIR` | Job-only | The top-level directory where builds are executed. |
| `CI_COMMIT_AUTHOR` | Pre-pipeline | The author of the commit in `Name <email>` format. |
| `CI_COMMIT_BEFORE_SHA` | Pre-pipeline | The previous latest commit present on a branch or tag. Is always `0000000000000000000000000000000000000000` for merge request pipelines, the first commit in pipelines for branches or tags, or when manually running a pipeline. |
| `CI_COMMIT_BRANCH` | Pre-pipeline | The commit branch name. Available in branch pipelines, including pipelines for the default branch. Not available in merge request pipelines or tag pipelines. |
| `CI_COMMIT_DESCRIPTION` | Pre-pipeline | The description of the commit. If the title is shorter than 100 characters, the message without the first line. |
| `CI_COMMIT_MESSAGE` | Pre-pipeline | The full commit message. |
| `CI_COMMIT_REF_NAME` | Pre-pipeline | The branch or tag name for which project is built. |
| `CI_COMMIT_REF_PROTECTED` | Pre-pipeline | `true` if the job is running for a protected reference, `false` otherwise. |
| `CI_COMMIT_REF_SLUG` | Pre-pipeline | `CI_COMMIT_REF_NAME` in lowercase, shortened to 63 bytes, and with everything except `0-9` and `a-z` replaced with `-`. No leading / trailing `-`. Use in URLs, host names and domain names. |
| `CI_COMMIT_SHA` | Pre-pipeline | The commit revision the project is built for. |
| `CI_COMMIT_SHORT_SHA` | Pre-pipeline | The first eight characters of `CI_COMMIT_SHA`. |
| `CI_COMMIT_TAG` | Pre-pipeline | The commit tag name. Available only in pipelines for tags. |
| `CI_COMMIT_TAG_MESSAGE` | Pre-pipeline | The commit tag message. Available only in pipelines for tags. Introduced in GitLab 15.5. |
| `CI_COMMIT_TIMESTAMP` | Pre-pipeline | The timestamp of the commit in the [ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A) format. For example, `2022-01-31T16:47:55Z`. [UTC by default](../../administration/timezone.md). |
| `CI_COMMIT_TITLE` | Pre-pipeline | The title of the commit. The full first line of the message. |
| `CI_CONCURRENT_ID` | Job-only | The unique ID of build execution in a single executor. |
| `CI_CONCURRENT_PROJECT_ID` | Job-only | The unique ID of build execution in a single executor and project. |
| `CI_CONFIG_PATH` | Pre-pipeline | The path to the CI/CD configuration file. Defaults to `.gitlab-ci.yml`. |
| `CI_DEBUG_TRACE` | Pipeline | `true` if [debug logging (tracing)](_index.md#enable-debug-logging) is enabled. |
| `CI_DEBUG_SERVICES` | Pipeline | `true` if [service container logging](../services/_index.md#capturing-service-container-logs) is enabled. Introduced in GitLab 15.7. Requires GitLab Runner 15.7. |
| `CI_DEFAULT_BRANCH` | Pre-pipeline | The name of the project's default branch. |
| `CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX` | Pre-pipeline | The direct group image prefix for pulling images through the Dependency Proxy. |
| `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX` | Pre-pipeline | The top-level group image prefix for pulling images through the Dependency Proxy. |
| `CI_DEPENDENCY_PROXY_PASSWORD` | Pipeline | The password to pull images through the Dependency Proxy. |
| `CI_DEPENDENCY_PROXY_SERVER` | Pre-pipeline | The server for logging in to the Dependency Proxy. This variable is equivalent to `$CI_SERVER_HOST:$CI_SERVER_PORT`. |
| `CI_DEPENDENCY_PROXY_USER` | Pipeline | The username to pull images through the Dependency Proxy. |
| `CI_DEPLOY_FREEZE` | Pre-pipeline | Only available if the pipeline runs during a [deploy freeze window](../../user/project/releases/_index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze). `true` when available. |
| `CI_DEPLOY_PASSWORD` | Job-only | The authentication password of the [GitLab Deploy Token](../../user/project/deploy_tokens/_index.md#gitlab-deploy-token), if the project has one. |
| `CI_DEPLOY_USER` | Job-only | The authentication username of the [GitLab Deploy Token](../../user/project/deploy_tokens/_index.md#gitlab-deploy-token), if the project has one. |
| `CI_DISPOSABLE_ENVIRONMENT` | Pipeline | Only available if the job is executed in a disposable environment (something that is created only for this job and disposed of/destroyed after the execution - all executors except `shell` and `ssh`). `true` when available. |
| `CI_ENVIRONMENT_NAME` | Pipeline | The name of the environment for this job. Available if [`environment:name`](../yaml/_index.md#environmentname) is set. |
| `CI_ENVIRONMENT_SLUG` | Pipeline | The simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, and so on. Available if [`environment:name`](../yaml/_index.md#environmentname) is set. The slug is [truncated to 24 characters](https://gitlab.com/gitlab-org/gitlab/-/issues/20941). A random suffix is automatically added to [uppercase environment names](https://gitlab.com/gitlab-org/gitlab/-/issues/415526). |
| `CI_ENVIRONMENT_URL` | Pipeline | The URL of the environment for this job. Available if [`environment:url`](../yaml/_index.md#environmenturl) is set. |
| `CI_ENVIRONMENT_ACTION` | Pipeline | The action annotation specified for this job's environment. Available if [`environment:action`](../yaml/_index.md#environmentaction) is set. Can be `start`, `prepare`, or `stop`. |
| `CI_ENVIRONMENT_TIER` | Pipeline | The [deployment tier of the environment](../environments/_index.md#deployment-tier-of-environments) for this job. |
| `CI_GITLAB_FIPS_MODE` | Pre-pipeline | Only available if [FIPS mode](../../development/fips_gitlab.md) is enabled in the GitLab instance. `true` when available. |
| `CI_HAS_OPEN_REQUIREMENTS` | Pipeline | Only available if the pipeline's project has an open [requirement](../../user/project/requirements/_index.md). `true` when available. |
| `CI_JOB_ID` | Job-only | The internal ID of the job, unique across all jobs in the GitLab instance. |
| `CI_JOB_IMAGE` | Pipeline | The name of the Docker image running the job. |
| `CI_JOB_MANUAL` | Pipeline | Only available if the job was started manually. `true` when available. |
| `CI_JOB_NAME` | Pipeline | The name of the job. |
| `CI_JOB_NAME_SLUG` | Pipeline | `CI_JOB_NAME` in lowercase, shortened to 63 bytes, and with everything except `0-9` and `a-z` replaced with `-`. No leading / trailing `-`. Use in paths. Introduced in GitLab 15.4. |
| `CI_JOB_STAGE` | Pipeline | The name of the job's stage. |
| `CI_JOB_STATUS` | Job-only | The status of the job as each runner stage is executed. Use with [`after_script`](../yaml/_index.md#after_script). Can be `success`, `failed`, or `canceled`. |
| `CI_JOB_TIMEOUT` | Job-only | The job timeout, in seconds. Introduced in GitLab 15.7. Requires GitLab Runner 15.7. |
| `CI_JOB_TOKEN` | Job-only | A token to authenticate with [certain API endpoints](../jobs/ci_job_token.md). The token is valid as long as the job is running. |
| `CI_JOB_URL` | Job-only | The job details URL. |
| `CI_JOB_STARTED_AT` | Job-only | The date and time when a job started, in [ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A) format. For example, `2022-01-31T16:47:55Z`. [UTC by default](../../administration/timezone.md). |
| `CI_KUBERNETES_ACTIVE` | Pre-pipeline | Only available if the pipeline has a Kubernetes cluster available for deployments. `true` when available. |
| `CI_NODE_INDEX` | Pipeline | The index of the job in the job set. Only available if the job uses [`parallel`](../yaml/_index.md#parallel). |
| `CI_NODE_TOTAL` | Pipeline | The total number of instances of this job running in parallel. Set to `1` if the job does not use [`parallel`](../yaml/_index.md#parallel). |
| `CI_OPEN_MERGE_REQUESTS` | Pre-pipeline | A comma-separated list of up to four merge requests that use the current branch and project as the merge request source. Only available in branch and merge request pipelines if the branch has an associated merge request. For example, `gitlab-org/gitlab!333,gitlab-org/gitlab-foss!11`. |
| `CI_PAGES_DOMAIN` | Pre-pipeline | The instance's domain that hosts GitLab Pages, not including the namespace subdomain. To use the full hostname, use `CI_PAGES_HOSTNAME` instead. |
| `CI_PAGES_HOSTNAME` | Job-only | The full hostname of the Pages deployment. |
| `CI_PAGES_URL` | Job-only | The URL for a GitLab Pages site. Always a subdomain of `CI_PAGES_DOMAIN`. In GitLab 17.9 and later, the value includes the `path_prefix` when one is specified. |
| `CI_PIPELINE_ID` | Job-only | The instance-level ID of the current pipeline. This ID is unique across all projects on the GitLab instance. |
| `CI_PIPELINE_IID` | Pipeline | The project-level IID (internal ID) of the current pipeline. This ID is unique only in the current project. |
| `CI_PIPELINE_SOURCE` | Pre-pipeline | How the pipeline was triggered. The value can be one of the [pipeline sources](../jobs/job_rules.md#ci_pipeline_source-predefined-variable). |
| `CI_PIPELINE_TRIGGERED` | Pipeline | `true` if the job was [triggered](../triggers/_index.md). |
| `CI_PIPELINE_URL` | Job-only | The URL for the pipeline details. |
| `CI_PIPELINE_CREATED_AT` | Pre-pipeline | The date and time when the pipeline was created, in [ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A) format. For example, `2022-01-31T16:47:55Z`. [UTC by default](../../administration/timezone.md). |
| `CI_PIPELINE_NAME` | Pre-pipeline | The pipeline name defined in [`workflow:name`](../yaml/_index.md#workflowname). Introduced in GitLab 16.3. |
| `CI_PIPELINE_SCHEDULE_DESCRIPTION` | Pre-pipeline | The description of the pipeline schedule. Only available in scheduled pipelines. Introduced in GitLab 17.8. |
| `CI_PROJECT_DIR` | Job-only | The full path the repository is cloned to, and where the job runs from. If the GitLab Runner `builds_dir` parameter is set, this variable is set relative to the value of `builds_dir`. For more information, see the [Advanced GitLab Runner configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). |
| `CI_PROJECT_ID` | Pre-pipeline | The ID of the current project. This ID is unique across all projects on the GitLab instance. |
| `CI_PROJECT_NAME` | Pre-pipeline | The name of the directory for the project. For example if the project URL is `gitlab.example.com/group-name/project-1`, `CI_PROJECT_NAME` is `project-1`. |
| `CI_PROJECT_NAMESPACE` | Pre-pipeline | The project namespace (username or group name) of the job. |
| `CI_PROJECT_NAMESPACE_ID` | Pre-pipeline | The project namespace ID of the job. Introduced in GitLab 15.7. |
| `CI_PROJECT_PATH_SLUG` | Pre-pipeline | `$CI_PROJECT_PATH` in lowercase with characters that are not `a-z` or `0-9` replaced with `-` and shortened to 63 bytes. Use in URLs and domain names. |
| `CI_PROJECT_PATH` | Pre-pipeline | The project namespace with the project name included. |
| `CI_PROJECT_REPOSITORY_LANGUAGES` | Pre-pipeline | A comma-separated, lowercase list of the languages used in the repository. For example `ruby,javascript,html,css`. The maximum number of languages is limited to 5. An issue [proposes to increase the limit](https://gitlab.com/gitlab-org/gitlab/-/issues/368925). |
| `CI_PROJECT_ROOT_NAMESPACE` | Pre-pipeline | The root project namespace (username or group name) of the job. For example, if `CI_PROJECT_NAMESPACE` is `root-group/child-group/grandchild-group`, `CI_PROJECT_ROOT_NAMESPACE` is `root-group`. |
| `CI_PROJECT_TITLE` | Pre-pipeline | The human-readable project name as displayed in the GitLab web interface. |
| `CI_PROJECT_DESCRIPTION` | Pre-pipeline | The project description as displayed in the GitLab web interface. Introduced in GitLab 15.1. |
| `CI_PROJECT_URL` | Pre-pipeline | The HTTP(S) address of the project. |
| `CI_PROJECT_VISIBILITY` | Pre-pipeline | The project visibility. Can be `internal`, `private`, or `public`. |
| `CI_PROJECT_CLASSIFICATION_LABEL` | Pre-pipeline | The project [external authorization classification label](../../administration/settings/external_authorization.md). |
| `CI_REGISTRY` | Pre-pipeline | Address of the [container registry](../../user/packages/container_registry/_index.md) server, formatted as `<host>[:<port>]`. For example: `registry.gitlab.example.com`. Only available if the container registry is enabled for the GitLab instance. |
| Variable | Availability | Description |
|-------------------------------------------------|--------------|-------------|
| `CHAT_CHANNEL` | Pipeline | The Source chat channel that triggered the [ChatOps](../chatops/_index.md) command. |
| `CHAT_INPUT` | Pipeline | The additional arguments passed with the [ChatOps](../chatops/_index.md) command. |
| `CHAT_USER_ID` | Pipeline | The chat service's user ID of the user who triggered the [ChatOps](../chatops/_index.md) command. |
| `CI` | Pre-pipeline | Available for all jobs executed in CI/CD. `true` when available. |
| `CI_API_V4_URL` | Pre-pipeline | The GitLab API v4 root URL. |
| `CI_API_GRAPHQL_URL` | Pre-pipeline | The GitLab API GraphQL root URL. Introduced in GitLab 15.11. |
| `CI_BUILDS_DIR` | Job-only | The top-level directory where builds are executed. |
| `CI_COMMIT_AUTHOR` | Pre-pipeline | The author of the commit in `Name <email>` format. |
| `CI_COMMIT_BEFORE_SHA` | Pre-pipeline | The previous latest commit present on a branch or tag. Is always `0000000000000000000000000000000000000000` for merge request pipelines, the first commit in pipelines for branches or tags, or when manually running a pipeline. |
| `CI_COMMIT_BRANCH` | Pre-pipeline | The commit branch name. Available in branch pipelines, including pipelines for the default branch. Not available in merge request pipelines or tag pipelines. |
| `CI_COMMIT_DESCRIPTION` | Pre-pipeline | The description of the commit. If the title is shorter than 100 characters, the message without the first line. |
| `CI_COMMIT_MESSAGE` | Pre-pipeline | The full commit message. |
| `CI_COMMIT_REF_NAME` | Pre-pipeline | The branch or tag name for which project is built. |
| `CI_COMMIT_REF_PROTECTED` | Pre-pipeline | `true` if the job is running for a protected reference, `false` otherwise. |
| `CI_COMMIT_REF_SLUG` | Pre-pipeline | `CI_COMMIT_REF_NAME` in lowercase, shortened to 63 bytes, and with everything except `0-9` and `a-z` replaced with `-`. No leading / trailing `-`. Use in URLs, host names and domain names. |
| `CI_COMMIT_SHA` | Pre-pipeline | The commit revision the project is built for. |
| `CI_COMMIT_SHORT_SHA` | Pre-pipeline | The first eight characters of `CI_COMMIT_SHA`. |
| `CI_COMMIT_TAG` | Pre-pipeline | The commit tag name. Available only in pipelines for tags. |
| `CI_COMMIT_TAG_MESSAGE` | Pre-pipeline | The commit tag message. Available only in pipelines for tags. Introduced in GitLab 15.5. |
| `CI_COMMIT_TIMESTAMP` | Pre-pipeline | The timestamp of the commit in the [ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A) format. For example, `2022-01-31T16:47:55Z`. [UTC by default](../../administration/timezone.md). |
| `CI_COMMIT_TITLE` | Pre-pipeline | The title of the commit. The full first line of the message. |
| `CI_CONCURRENT_ID` | Job-only | The unique ID of build execution in a single executor. |
| `CI_CONCURRENT_PROJECT_ID` | Job-only | The unique ID of build execution in a single executor and project. |
| `CI_CONFIG_PATH` | Pre-pipeline | The path to the CI/CD configuration file. Defaults to `.gitlab-ci.yml`. |
| `CI_DEBUG_TRACE` | Pipeline | `true` if [debug logging (tracing)](_index.md#enable-debug-logging) is enabled. |
| `CI_DEBUG_SERVICES` | Pipeline | `true` if [service container logging](../services/_index.md#capturing-service-container-logs) is enabled. Introduced in GitLab 15.7. Requires GitLab Runner 15.7. |
| `CI_DEFAULT_BRANCH` | Pre-pipeline | The name of the project's default branch. |
| `CI_DEPENDENCY_PROXY_DIRECT_GROUP_IMAGE_PREFIX` | Pre-pipeline | The direct group image prefix for pulling images through the Dependency Proxy. |
| `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX` | Pre-pipeline | The top-level group image prefix for pulling images through the Dependency Proxy. |
| `CI_DEPENDENCY_PROXY_PASSWORD` | Pipeline | The password to pull images through the Dependency Proxy. |
| `CI_DEPENDENCY_PROXY_SERVER` | Pre-pipeline | The server for logging in to the Dependency Proxy. This variable is equivalent to `$CI_SERVER_HOST:$CI_SERVER_PORT`. |
| `CI_DEPENDENCY_PROXY_USER` | Pipeline | The username to pull images through the Dependency Proxy. |
| `CI_DEPLOY_FREEZE` | Pre-pipeline | Only available if the pipeline runs during a [deploy freeze window](../../user/project/releases/_index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze). `true` when available. |
| `CI_DEPLOY_PASSWORD` | Job-only | The authentication password of the [GitLab Deploy Token](../../user/project/deploy_tokens/_index.md#gitlab-deploy-token), if the project has one. |
| `CI_DEPLOY_USER` | Job-only | The authentication username of the [GitLab Deploy Token](../../user/project/deploy_tokens/_index.md#gitlab-deploy-token), if the project has one. |
| `CI_DISPOSABLE_ENVIRONMENT` | Pipeline | Only available if the job is executed in a disposable environment (something that is created only for this job and disposed of/destroyed after the execution - all executors except `shell` and `ssh`). `true` when available. |
| `CI_ENVIRONMENT_NAME` | Pipeline | The name of the environment for this job. Available if [`environment:name`](../yaml/_index.md#environmentname) is set. |
| `CI_ENVIRONMENT_SLUG` | Pipeline | The simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, and so on. Available if [`environment:name`](../yaml/_index.md#environmentname) is set. The slug is [truncated to 24 characters](https://gitlab.com/gitlab-org/gitlab/-/issues/20941). A random suffix is automatically added to [uppercase environment names](https://gitlab.com/gitlab-org/gitlab/-/issues/415526). |
| `CI_ENVIRONMENT_URL` | Pipeline | The URL of the environment for this job. Available if [`environment:url`](../yaml/_index.md#environmenturl) is set. |
| `CI_ENVIRONMENT_ACTION` | Pipeline | The action annotation specified for this job's environment. Available if [`environment:action`](../yaml/_index.md#environmentaction) is set. Can be `start`, `prepare`, or `stop`. |
| `CI_ENVIRONMENT_TIER` | Pipeline | The [deployment tier of the environment](../environments/_index.md#deployment-tier-of-environments) for this job. |
| `CI_GITLAB_FIPS_MODE` | Pre-pipeline | Only available if [FIPS mode](../../development/fips_gitlab.md) is enabled in the GitLab instance. `true` when available. |
| `CI_HAS_OPEN_REQUIREMENTS` | Pipeline | Only available if the pipeline's project has an open [requirement](../../user/project/requirements/_index.md). `true` when available. |
| `CI_JOB_ID` | Job-only | The internal ID of the job, unique across all jobs in the GitLab instance. |
| `CI_JOB_IMAGE` | Pipeline | The name of the Docker image running the job. |
| `CI_JOB_MANUAL` | Pipeline | Only available if the job was started manually. `true` when available. |
| `CI_JOB_NAME` | Pipeline | The name of the job. |
| `CI_JOB_NAME_SLUG` | Pipeline | `CI_JOB_NAME` in lowercase, shortened to 63 bytes, and with everything except `0-9` and `a-z` replaced with `-`. No leading / trailing `-`. Use in paths. Introduced in GitLab 15.4. |
| `CI_JOB_STAGE` | Pipeline | The name of the job's stage. |
| `CI_JOB_STATUS` | Job-only | The status of the job as each runner stage is executed. Use with [`after_script`](../yaml/_index.md#after_script). Can be `success`, `failed`, or `canceled`. |
| `CI_JOB_TIMEOUT` | Job-only | The job timeout, in seconds. Introduced in GitLab 15.7. Requires GitLab Runner 15.7. |
| `CI_JOB_TOKEN` | Job-only | A token to authenticate with [certain API endpoints](../jobs/ci_job_token.md). The token is valid as long as the job is running. |
| `CI_JOB_URL` | Job-only | The job details URL. |
| `CI_JOB_STARTED_AT` | Job-only | The date and time when a job started, in [ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A) format. For example, `2022-01-31T16:47:55Z`. [UTC by default](../../administration/timezone.md). |
| `CI_KUBERNETES_ACTIVE` | Pre-pipeline | Only available if the pipeline has a Kubernetes cluster available for deployments. `true` when available. |
| `CI_NODE_INDEX` | Pipeline | The index of the job in the job set. Only available if the job uses [`parallel`](../yaml/_index.md#parallel). |
| `CI_NODE_TOTAL` | Pipeline | The total number of instances of this job running in parallel. Set to `1` if the job does not use [`parallel`](../yaml/_index.md#parallel). |
| `CI_OPEN_MERGE_REQUESTS` | Pre-pipeline | A comma-separated list of up to four merge requests that use the current branch and project as the merge request source. Only available in branch and merge request pipelines if the branch has an associated merge request. For example, `gitlab-org/gitlab!333,gitlab-org/gitlab-foss!11`. |
| `CI_PAGES_DOMAIN` | Pre-pipeline | The instance's domain that hosts GitLab Pages, not including the namespace subdomain. To use the full hostname, use `CI_PAGES_HOSTNAME` instead. |
| `CI_PAGES_HOSTNAME` | Job-only | The full hostname of the Pages deployment. |
| `CI_PAGES_URL` | Job-only | The URL for a GitLab Pages site. Always a subdomain of `CI_PAGES_DOMAIN`. In GitLab 17.9 and later, the value includes the `path_prefix` when one is specified. |
| `CI_PIPELINE_ID` | Job-only | The instance-level ID of the current pipeline. This ID is unique across all projects on the GitLab instance. |
| `CI_PIPELINE_IID` | Pipeline | The project-level IID (internal ID) of the current pipeline. This ID is unique only in the current project. |
| `CI_PIPELINE_SOURCE` | Pre-pipeline | How the pipeline was triggered. The value can be one of the [pipeline sources](../jobs/job_rules.md#ci_pipeline_source-predefined-variable). |
| `CI_PIPELINE_TRIGGERED` | Pipeline | `true` if the job was [triggered](../triggers/_index.md). |
| `CI_PIPELINE_URL` | Job-only | The URL for the pipeline details. |
| `CI_PIPELINE_CREATED_AT` | Pre-pipeline | The date and time when the pipeline was created, in [ISO 8601](https://www.rfc-editor.org/rfc/rfc3339#appendix-A) format. For example, `2022-01-31T16:47:55Z`. [UTC by default](../../administration/timezone.md). |
| `CI_PIPELINE_NAME` | Pre-pipeline | The pipeline name defined in [`workflow:name`](../yaml/_index.md#workflowname). Introduced in GitLab 16.3. |
| `CI_PIPELINE_SCHEDULE_DESCRIPTION` | Pre-pipeline | The description of the pipeline schedule. Only available in scheduled pipelines. Introduced in GitLab 17.8. |
| `CI_PROJECT_DIR` | Job-only | The full path the repository is cloned to, and where the job runs from. If the GitLab Runner `builds_dir` parameter is set, this variable is set relative to the value of `builds_dir`. For more information, see the [Advanced GitLab Runner configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). |
| `CI_PROJECT_ID` | Pre-pipeline | The ID of the current project. This ID is unique across all projects on the GitLab instance. |
| `CI_PROJECT_NAME` | Pre-pipeline | The name of the directory for the project. For example if the project URL is `gitlab.example.com/group-name/project-1`, `CI_PROJECT_NAME` is `project-1`. |
| `CI_PROJECT_NAMESPACE` | Pre-pipeline | The project namespace (username or group name) of the job. |
| `CI_PROJECT_NAMESPACE_ID` | Pre-pipeline | The project namespace ID of the job. Introduced in GitLab 15.7. |
| `CI_PROJECT_PATH_SLUG` | Pre-pipeline | `$CI_PROJECT_PATH` in lowercase with characters that are not `a-z` or `0-9` replaced with `-` and shortened to 63 bytes. Use in URLs and domain names. |
| `CI_PROJECT_PATH` | Pre-pipeline | The project namespace with the project name included. |
| `CI_PROJECT_REPOSITORY_LANGUAGES` | Pre-pipeline | A comma-separated, lowercase list of the languages used in the repository. For example `ruby,javascript,html,css`. The maximum number of languages is limited to 5. An issue [proposes to increase the limit](https://gitlab.com/gitlab-org/gitlab/-/issues/368925). |
| `CI_PROJECT_ROOT_NAMESPACE` | Pre-pipeline | The root project namespace (username or group name) of the job. For example, if `CI_PROJECT_NAMESPACE` is `root-group/child-group/grandchild-group`, `CI_PROJECT_ROOT_NAMESPACE` is `root-group`. |
| `CI_PROJECT_TITLE` | Pre-pipeline | The human-readable project name as displayed in the GitLab web interface. |
| `CI_PROJECT_DESCRIPTION` | Pre-pipeline | The project description as displayed in the GitLab web interface. Introduced in GitLab 15.1. |
| `CI_PROJECT_URL` | Pre-pipeline | The HTTP(S) address of the project. |
| `CI_PROJECT_VISIBILITY` | Pre-pipeline | The project visibility. Can be `internal`, `private`, or `public`. |
| `CI_PROJECT_CLASSIFICATION_LABEL` | Pre-pipeline | The project [external authorization classification label](../../administration/settings/external_authorization.md). |
| `CI_REGISTRY` | Pre-pipeline | Address of the [container registry](../../user/packages/container_registry/_index.md) server, formatted as `<host>[:<port>]`. For example: `registry.gitlab.example.com`. Only available if the container registry is enabled for the GitLab instance. |
| `CI_REGISTRY_IMAGE` | Pre-pipeline | Base address for the container registry to push, pull, or tag project's images, formatted as `<host>[:<port>]/<project_full_path>`. For example: `registry.gitlab.example.com/my_group/my_project`. Image names must follow the [container registry naming convention](../../user/packages/container_registry/_index.md#naming-convention-for-your-container-images). Only available if the container registry is enabled for the project. |
| `CI_REGISTRY_PASSWORD` | Job-only | The password to push containers to the GitLab project's container registry. Only available if the container registry is enabled for the project. This password value is the same as the `CI_JOB_TOKEN` and is valid only as long as the job is running. Use the `CI_DEPLOY_PASSWORD` for long-lived access to the registry |
| `CI_REGISTRY_USER` | Job-only | The username to push containers to the project's GitLab container registry. Only available if the container registry is enabled for the project. |
| `CI_RELEASE_DESCRIPTION` | Pipeline | The description of the release. Available only on pipelines for tags. Description length is limited to first 1024 characters. Introduced in GitLab 15.5. |
| `CI_REPOSITORY_URL` | Job-only | The full path to Git clone (HTTP) the repository with a [CI/CD job token](../jobs/ci_job_token.md), in the format `https://gitlab-ci-token:$CI_JOB_TOKEN@gitlab.example.com/my-group/my-project.git`. |
| `CI_RUNNER_DESCRIPTION` | Job-only | The description of the runner. |
| `CI_RUNNER_EXECUTABLE_ARCH` | Job-only | The OS/architecture of the GitLab Runner executable. Might not be the same as the environment of the executor. |
| `CI_RUNNER_ID` | Job-only | The unique ID of the runner being used. |
| `CI_RUNNER_REVISION` | Job-only | The revision of the runner running the job. |
| `CI_RUNNER_SHORT_TOKEN` | Job-only | The runner's unique ID, used to authenticate new job requests. The token contains a prefix, and the first 17 characters are used. |
| `CI_RUNNER_TAGS` | Job-only | A JSON array of runner tags. For example `["tag_1", "tag_2"]`. |
| `CI_RUNNER_VERSION` | Job-only | The version of the GitLab Runner running the job. |
| `CI_SERVER_FQDN` | Pre-pipeline | The fully qualified domain name (FQDN) of the instance. For example `gitlab.example.com:8080`. Introduced in GitLab 16.10. |
| `CI_SERVER_HOST` | Pre-pipeline | The host of the GitLab instance URL, without protocol or port. For example `gitlab.example.com`. |
| `CI_SERVER_NAME` | Pre-pipeline | The name of CI/CD server that coordinates jobs. |
| `CI_SERVER_PORT` | Pre-pipeline | The port of the GitLab instance URL, without host or protocol. For example `8080`. |
| `CI_SERVER_PROTOCOL` | Pre-pipeline | The protocol of the GitLab instance URL, without host or port. For example `https`. |
| `CI_SERVER_SHELL_SSH_HOST` | Pre-pipeline | The SSH host of the GitLab instance, used for access to Git repositories through SSH. For example `gitlab.com`. Introduced in GitLab 15.11. |
| `CI_SERVER_SHELL_SSH_PORT` | Pre-pipeline | The SSH port of the GitLab instance, used for access to Git repositories through SSH. For example `22`. Introduced in GitLab 15.11. |
| `CI_SERVER_REVISION` | Pre-pipeline | GitLab revision that schedules jobs. |
| `CI_SERVER_TLS_CA_FILE` | Pipeline | File containing the TLS CA certificate to verify the GitLab server when `tls-ca-file` set in [runner settings](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). |
| `CI_SERVER_TLS_CERT_FILE` | Pipeline | File containing the TLS certificate to verify the GitLab server when `tls-cert-file` set in [runner settings](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). |
| `CI_SERVER_TLS_KEY_FILE` | Pipeline | File containing the TLS key to verify the GitLab server when `tls-key-file` set in [runner settings](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). |
| `CI_SERVER_URL` | Pre-pipeline | The base URL of the GitLab instance, including protocol and port. For example `https://gitlab.example.com:8080`. |
| `CI_SERVER_VERSION_MAJOR` | Pre-pipeline | The major version of the GitLab instance. For example, if the GitLab version is `17.2.1`, the `CI_SERVER_VERSION_MAJOR` is `17`. |
| `CI_SERVER_VERSION_MINOR` | Pre-pipeline | The minor version of the GitLab instance. For example, if the GitLab version is `17.2.1`, the `CI_SERVER_VERSION_MINOR` is `2`. |
| `CI_SERVER_VERSION_PATCH` | Pre-pipeline | The patch version of the GitLab instance. For example, if the GitLab version is `17.2.1`, the `CI_SERVER_VERSION_PATCH` is `1`. |
| `CI_SERVER_VERSION` | Pre-pipeline | The full version of the GitLab instance. |
| `CI_SERVER` | Job-only | Available for all jobs executed in CI/CD. `yes` when available. |
| `CI_SHARED_ENVIRONMENT` | Pipeline | Only available if the job is executed in a shared environment (something that is persisted across CI/CD invocations, like the `shell` or `ssh` executor). `true` when available. |
| `CI_TEMPLATE_REGISTRY_HOST` | Pre-pipeline | The host of the registry used by CI/CD templates. Defaults to `registry.gitlab.com`. Introduced in GitLab 15.3. |
| `CI_TRIGGER_SHORT_TOKEN` | Job-only | First 4 characters of the [trigger token](../triggers/_index.md#create-a-pipeline-trigger-token) of the current job. Only available if the pipeline was [triggered with a trigger token](../triggers/_index.md). For example, for a trigger token of `glptt-1234567890abcdefghij`, `CI_TRIGGER_SHORT_TOKEN` would be `1234`. Introduced in GitLab 17.0. <!-- gitleaks:allow --> |
| `GITLAB_CI` | Pre-pipeline | Available for all jobs executed in CI/CD. `true` when available. |
| `GITLAB_FEATURES` | Pre-pipeline | The comma-separated list of licensed features available for the GitLab instance and license. |
| `GITLAB_USER_EMAIL` | Pipeline | The email of the user who started the pipeline, unless the job is a manual job. In manual jobs, the value is the email of the user who started the job. |
| `GITLAB_USER_ID` | Pipeline | The numeric ID of the user who started the pipeline, unless the job is a manual job. In manual jobs, the value is the ID of the user who started the job. |
| `GITLAB_USER_LOGIN` | Pipeline | The unique username of the user who started the pipeline, unless the job is a manual job. In manual jobs, the value is the username of the user who started the job. |
| `GITLAB_USER_NAME` | Pipeline | The display name (user-defined **Full name** in the profile settings) of the user who started the pipeline, unless the job is a manual job. In manual jobs, the value is the name of the user who started the job. |
| `KUBECONFIG` | Pipeline | The path to the `kubeconfig` file with contexts for every shared agent connection. Only available when a [GitLab agent is authorized to access the project](../../user/clusters/agent/ci_cd_workflow.md#authorize-the-agent). |
| `TRIGGER_PAYLOAD` | Pipeline | The webhook payload. Only available when a pipeline is [triggered with a webhook](../triggers/_index.md#access-webhook-payload). |
| `CI_REGISTRY_PASSWORD` | Job-only | The password to push containers to the GitLab project's container registry. Only available if the container registry is enabled for the project. This password value is the same as the `CI_JOB_TOKEN` and is valid only as long as the job is running. Use the `CI_DEPLOY_PASSWORD` for long-lived access to the registry |
| `CI_REGISTRY_USER` | Job-only | The username to push containers to the project's GitLab container registry. Only available if the container registry is enabled for the project. |
| `CI_RELEASE_DESCRIPTION` | Pipeline | The description of the release. Available only on pipelines for tags. Description length is limited to first 1024 characters. Introduced in GitLab 15.5. |
| `CI_REPOSITORY_URL` | Job-only | The full path to Git clone (HTTP) the repository with a [CI/CD job token](../jobs/ci_job_token.md), in the format `https://gitlab-ci-token:$CI_JOB_TOKEN@gitlab.example.com/my-group/my-project.git`. |
| `CI_RUNNER_DESCRIPTION` | Job-only | The description of the runner. |
| `CI_RUNNER_EXECUTABLE_ARCH` | Job-only | The OS/architecture of the GitLab Runner executable. Might not be the same as the environment of the executor. |
| `CI_RUNNER_ID` | Job-only | The unique ID of the runner being used. |
| `CI_RUNNER_REVISION` | Job-only | The revision of the runner running the job. |
| `CI_RUNNER_SHORT_TOKEN` | Job-only | The runner's unique ID, used to authenticate new job requests. The token contains a prefix, and the first 17 characters are used. |
| `CI_RUNNER_TAGS` | Job-only | A JSON array of runner tags. For example `["tag_1", "tag_2"]`. |
| `CI_RUNNER_VERSION` | Job-only | The version of the GitLab Runner running the job. |
| `CI_SERVER_FQDN` | Pre-pipeline | The fully qualified domain name (FQDN) of the instance. For example `gitlab.example.com:8080`. Introduced in GitLab 16.10. |
| `CI_SERVER_HOST` | Pre-pipeline | The host of the GitLab instance URL, without protocol or port. For example `gitlab.example.com`. |
| `CI_SERVER_NAME` | Pre-pipeline | The name of CI/CD server that coordinates jobs. |
| `CI_SERVER_PORT` | Pre-pipeline | The port of the GitLab instance URL, without host or protocol. For example `8080`. |
| `CI_SERVER_PROTOCOL` | Pre-pipeline | The protocol of the GitLab instance URL, without host or port. For example `https`. |
| `CI_SERVER_SHELL_SSH_HOST` | Pre-pipeline | The SSH host of the GitLab instance, used for access to Git repositories through SSH. For example `gitlab.com`. Introduced in GitLab 15.11. |
| `CI_SERVER_SHELL_SSH_PORT` | Pre-pipeline | The SSH port of the GitLab instance, used for access to Git repositories through SSH. For example `22`. Introduced in GitLab 15.11. |
| `CI_SERVER_REVISION` | Pre-pipeline | GitLab revision that schedules jobs. |
| `CI_SERVER_TLS_CA_FILE` | Pipeline | File containing the TLS CA certificate to verify the GitLab server when `tls-ca-file` set in [runner settings](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). |
| `CI_SERVER_TLS_CERT_FILE` | Pipeline | File containing the TLS certificate to verify the GitLab server when `tls-cert-file` set in [runner settings](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). |
| `CI_SERVER_TLS_KEY_FILE` | Pipeline | File containing the TLS key to verify the GitLab server when `tls-key-file` set in [runner settings](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section). |
| `CI_SERVER_URL` | Pre-pipeline | The base URL of the GitLab instance, including protocol and port. For example `https://gitlab.example.com:8080`. |
| `CI_SERVER_VERSION_MAJOR` | Pre-pipeline | The major version of the GitLab instance. For example, if the GitLab version is `17.2.1`, the `CI_SERVER_VERSION_MAJOR` is `17`. |
| `CI_SERVER_VERSION_MINOR` | Pre-pipeline | The minor version of the GitLab instance. For example, if the GitLab version is `17.2.1`, the `CI_SERVER_VERSION_MINOR` is `2`. |
| `CI_SERVER_VERSION_PATCH` | Pre-pipeline | The patch version of the GitLab instance. For example, if the GitLab version is `17.2.1`, the `CI_SERVER_VERSION_PATCH` is `1`. |
| `CI_SERVER_VERSION` | Pre-pipeline | The full version of the GitLab instance. |
| `CI_SERVER` | Job-only | Available for all jobs executed in CI/CD. `yes` when available. |
| `CI_SHARED_ENVIRONMENT` | Pipeline | Only available if the job is executed in a shared environment (something that is persisted across CI/CD invocations, like the `shell` or `ssh` executor). `true` when available. |
| `CI_TEMPLATE_REGISTRY_HOST` | Pre-pipeline | The host of the registry used by CI/CD templates. Defaults to `registry.gitlab.com`. Introduced in GitLab 15.3. |
| `CI_TRIGGER_SHORT_TOKEN` | Job-only | First 4 characters of the [trigger token](../triggers/_index.md#create-a-pipeline-trigger-token) of the current job. Only available if the pipeline was [triggered with a trigger token](../triggers/_index.md). For example, for a trigger token of `glptt-1234567890abcdefghij`, `CI_TRIGGER_SHORT_TOKEN` would be `1234`. Introduced in GitLab 17.0. <!-- gitleaks:allow --> |
| `GITLAB_CI` | Pre-pipeline | Available for all jobs executed in CI/CD. `true` when available. |
| `GITLAB_FEATURES` | Pre-pipeline | The comma-separated list of licensed features available for the GitLab instance and license. |
| `GITLAB_USER_EMAIL` | Pipeline | The email of the user who started the pipeline, unless the job is a manual job. In manual jobs, the value is the email of the user who started the job. |
| `GITLAB_USER_ID` | Pipeline | The numeric ID of the user who started the pipeline, unless the job is a manual job. In manual jobs, the value is the ID of the user who started the job. |
| `GITLAB_USER_LOGIN` | Pipeline | The unique username of the user who started the pipeline, unless the job is a manual job. In manual jobs, the value is the username of the user who started the job. |
| `GITLAB_USER_NAME` | Pipeline | The display name (user-defined **Full name** in the profile settings) of the user who started the pipeline, unless the job is a manual job. In manual jobs, the value is the name of the user who started the job. |
| `KUBECONFIG` | Pipeline | The path to the `kubeconfig` file with contexts for every shared agent connection. Only available when a [GitLab agent is authorized to access the project](../../user/clusters/agent/ci_cd_workflow.md#authorize-the-agent). |
| `TRIGGER_PAYLOAD` | Pipeline | The webhook payload. Only available when a pipeline is [triggered with a webhook](../triggers/_index.md#access-webhook-payload). |
## Predefined variables for merge request pipelines

Binary file not shown.

Before

Width:  |  Height:  |  Size: 11 KiB

View File

@ -261,9 +261,22 @@ was merged into your branch. In that case, you must revert the changes on the re
### Revert remote changes without altering history
To undo changes in the remote repository, you can create a new commit with the changes you
want to undo. This process preserves the history and provides a clear timeline and development structure.
want to undo. This process preserves the history and provides a clear timeline and development structure:
![Use revert to keep branch flowing](img/revert_v14_0.png)
```mermaid
%%{init: { "fontFamily": "GitLab Sans" }}%%
flowchart LR
REMOTE["REMOTE"] --> A(A)
A --> B(B)
B --> C(C)
C --> negB("-B")
negB --> D(D)
B:::crossed
classDef crossed stroke:#000,stroke-width:3px,color:#000,stroke-dasharray: 5 5
negB -.->|reverts| B
```
To revert changes introduced in a specific commit `B`:

View File

@ -126,6 +126,28 @@ For details, see the [migration guide](https://docs.gitlab.com/user/group/compli
<div class="deprecation breaking-change" data-milestone="19.0">
### Coverage-guided fuzz testing is deprecated
<div class="deprecation-notes">
- Announced in GitLab <span class="milestone">18.0</span>
- End of Support in GitLab <span class="milestone">18.0</span>
- Removal in GitLab <span class="milestone">19.0</span> ([breaking change](https://docs.gitlab.com/update/terminology/#breaking-change))
- To discuss this change or learn more, see the [deprecation issue](https://gitlab.com/gitlab-org/gitlab/-/issues/517841).
</div>
Coverage-guided fuzz testing is deprecated and will not be supported
from GitLab 18.0. The feature will be completely removed in GitLab 19.0.
Coverage-guided fuzz testing integrated several open-source fuzzers into GitLab.
If you are impacted, you can integrate your open-source fuzzers as standalone applications,
or migrate to another security feature like [GitLab Advanced SAST](https://docs.gitlab.com/ee/user/application_security/sast/gitlab_advanced_sast.html).
</div>
<div class="deprecation breaking-change" data-milestone="19.0">
### GitLab Self-Managed certificate-based integration with Kubernetes
<div class="deprecation-notes">

View File

@ -395,6 +395,7 @@ granularly per policy, you can set a "policy scope" in each policy.
Prerequisites:
- You must have the Owner role or [custom role](../../custom_roles.md) with the`manage_security_policy_link` permission to link to the security policy project. For more information, see [separation of duties](#separation-of-duties).
- You must have at least the Reporter role or [custom role](../../custom_roles.md) with the `manage_security_policy_link` permission to the project you want to assign as the security policy project. For more information, see [separation of duties](#separation-of-duties).
To link a group, subgroup, or project to a security policy project:

View File

@ -17,7 +17,6 @@ title: GLQL fields
- [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/14767) in GitLab 17.4 [with a flag](../../administration/feature_flags.md) named `glql_integration`. Disabled by default.
- Enabled on GitLab.com in GitLab 17.4 for a subset of groups and projects.
- `iteration` and `cadence` fields [introduced](https://gitlab.com/gitlab-org/gitlab-query-language/gitlab-query-language/-/issues/74) in GitLab 17.6.
{{< /history >}}
@ -40,6 +39,14 @@ This page lists fields available to use as filters when querying issues or work
## Type
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/81) in GitLab 17.8.
{{< /history >}}
**Description**: The type of object to query: one of the work item types or merge requests.
**Field name**: `type`
**Allowed operators**: `=`, `in`
@ -80,6 +87,14 @@ This page lists fields available to use as filters when querying issues or work
## Approved by user
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/81) in GitLab 17.8.
{{< /history >}}
**Description**: Query merge requests by one or more users who approved the merge request.
**Field name**: `approver`
**Allowed operators**: `=`, `!=`
@ -105,6 +120,8 @@ This page lists fields available to use as filters when querying issues or work
## Assignees
**Description**: Query issues or merge requests by one or more users who are assigned to the issue or merge request.
**Field name**: `assignee`
**Allowed operators**: `=`, `in`, `!=`
@ -124,6 +141,10 @@ This page lists fields available to use as filters when querying issues or work
- Work item types like `Task` or `Objective`
- `MergeRequest`
**Additional details:**
- `List` values and the `in` operator are not supported for `MergeRequest` types.
**Examples**:
- List all issues where assignee is `@johndoe`:
@ -156,12 +177,10 @@ This page lists fields available to use as filters when querying issues or work
type = MergeRequest and assignee = @johndoe
```
**Additional details:**
- `List` values and the `in` operator are not supported for `MergeRequest` types.
## Author
**Description**: Query issues or merge request by their author.
**Field name**: `author`
**Allowed operators**: `=`, `in`, `!=`
@ -215,6 +234,14 @@ This page lists fields available to use as filters when querying issues or work
## Cadence
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-haskell/-/issues/74) in GitLab 17.6.
{{< /history >}}
**Description**: Query issues by the [cadence](../group/iterations/_index.md#iteration-cadences) that the issue's iteration is a part of.
**Field name**: `cadence`
**Allowed operators**: `=`, `in`, `!=`
@ -241,7 +268,7 @@ This page lists fields available to use as filters when querying issues or work
- List all issues with iteration that are a part of cadence ID `123456`:
```plaintext
cadences = 123456
cadence = 123456
```
- List all issues with iterations that are a part of any cadences `123` or `456`:
@ -252,6 +279,8 @@ This page lists fields available to use as filters when querying issues or work
## Closed at
**Description**: Query issues or merge requests by the date when they were closed.
**Field name**: `closed`
**Allowed operators**: `=`, `>`, `<`
@ -295,6 +324,8 @@ This page lists fields available to use as filters when querying issues or work
## Confidential
**Description**: Query issues by their visibility to project members.
**Field name**: `confidential`
**Allowed operators**: `=`, `!=`
@ -330,6 +361,8 @@ This page lists fields available to use as filters when querying issues or work
## Created at
**Description**: Query issues or merge requests by the date when they were created.
**Field name**: `created`
**Allowed operators**: `=`, `>`, `<`
@ -374,6 +407,14 @@ This page lists fields available to use as filters when querying issues or work
## Deployed at
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/81) in GitLab 17.8.
{{< /history >}}
**Description**: Query merge requests by the date when they were deployed.
**Field name**: `deployed`
**Allowed operators**: `=`, `>`, `<`
@ -408,6 +449,14 @@ This page lists fields available to use as filters when querying issues or work
## Draft
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/81) in GitLab 17.8.
{{< /history >}}
**Description**: Query merge requests by their draft status.
**Field name**: `draft`
**Allowed operators**: `=`, `!=`
@ -436,6 +485,8 @@ This page lists fields available to use as filters when querying issues or work
## Due date
**Description**: Query issues by the date when they are due.
**Field name**: `due`
**Allowed operators**: `=`, `>`, `<`
@ -485,6 +536,14 @@ This page lists fields available to use as filters when querying issues or work
## Environment
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/81) in GitLab 17.8.
{{< /history >}}
**Description**: Query merge requests by the environment to which they have been deployed.
**Field name**: `environment`
**Allowed operators**: `=`
@ -505,6 +564,14 @@ This page lists fields available to use as filters when querying issues or work
## Group
{{< history >}}
- [Changed](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/106) in GitLab 17.10: Group queries no longer search the entire hierarchy by default.
{{< /history >}}
**Description**: Query issues or merge requests within all projects in a given group.
**Field name**: `group`
**Allowed operators**: `=`
@ -526,6 +593,8 @@ This page lists fields available to use as filters when querying issues or work
- If omitted when using inside a GLQL view in a group object (like an epic), `group` is assumed to
be the current group.
- Using the `group` field queries all objects in that group, all its subgroups, and child projects.
- By default, issues or merge requests are searched only in direct descendant projects in a group.
To query in the entire hierarchy of a project use the [`includeSubgroups` field](#include-subgroups).
**Examples**:
@ -543,6 +612,8 @@ This page lists fields available to use as filters when querying issues or work
## Health status
**Description**: Query issues by their health status.
**Field name**: `health`
**Allowed operators**: `=`
@ -575,6 +646,14 @@ This page lists fields available to use as filters when querying issues or work
## ID
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/92) in GitLab 17.8.
{{< /history >}}
**Description**: Query issues or merge requests by their IDs.
**Field name**: `id`
**Allowed operators**: `=`, `in`
@ -612,8 +691,62 @@ This page lists fields available to use as filters when querying issues or work
type = MergeRequest and id in (1, 2, 3)
```
## Include subgroups
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/106) in GitLab 17.10.
{{< /history >}}
**Description**: Query within the entire hierarchy of a group.
**Field name**: `includeSubgroups`
**Allowed operators**: `=`, `!=`
**Allowed value types**:
- `Boolean` (either of `true` or `false`)
**Allowed in columns of a GLQL view**: Yes
**Supported for object types**:
- `Issue`
- Work item types like `Task` or `Objective`
- `MergeRequest`
**Additional details**:
- This field can only be used with the `group` field.
- The value of this field defaults to `false`.
**Examples**:
- List issues in any project that is a direct child of the `gitlab-org` group:
```plaintext
group = "gitlab-org" and includeSubgroups = false
```
- List issues in any project within the entire hierarchy of the `gitlab-org` group:
```plaintext
group = "gitlab-org" and includeSubgroups = true
```
## Iteration
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-haskell/-/issues/74) in GitLab 17.6.
- Support for iteration value types [introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/79) in GitLab 17.8.
{{< /history >}}
**Description**: Query issues by their associated [iteration](../group/iterations/_index.md).
**Field name**: `iteration`
**Allowed operators**: `=`, `in`, `!=`
@ -672,6 +805,14 @@ This page lists fields available to use as filters when querying issues or work
## Labels
{{< history >}}
- Support for label value types [introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/79) in GitLab 17.8.
{{< /history >}}
**Description**: Query issues or merge requests by their associated labels.
**Field name**: `label`
**Allowed operators**: `=`, `in`, `!=`
@ -742,6 +883,14 @@ This page lists fields available to use as filters when querying issues or work
## Merged at
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/81) in GitLab 17.8.
{{< /history >}}
**Description**: Query merge requests by the date when they were merged.
**Field name**: `merged`
**Allowed operators**: `=`, `>`, `<`
@ -776,6 +925,14 @@ This page lists fields available to use as filters when querying issues or work
## Merged by user
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/81) in GitLab 17.8.
{{< /history >}}
**Description**: Query merge requests by the user that merged the merge request.
**Field name**: `merger`
**Allowed operators**: `=`
@ -801,6 +958,14 @@ This page lists fields available to use as filters when querying issues or work
## Milestone
{{< history >}}
- Support for milestone value types [introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/77) in GitLab 17.8.
{{< /history >}}
**Description**: Query issues or merge requests by their associated milestone.
**Field name**: `milestone`
**Allowed operators**: `=`, `in`, `!=`
@ -860,6 +1025,8 @@ This page lists fields available to use as filters when querying issues or work
## Project
**Description**: Query issues or merge requests within a particular project.
**Field name**: `project`
**Allowed operators**: `=`
@ -890,6 +1057,8 @@ This page lists fields available to use as filters when querying issues or work
## Reviewers
**Description**: Query merge requests that were reviewed by one or more users.
**Field name**: `reviewer`
**Allowed operators**: `=`, `!=`
@ -915,6 +1084,14 @@ This page lists fields available to use as filters when querying issues or work
## State
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab-query-language/glql-rust/-/merge_requests/96) in GitLab 17.8.
{{< /history >}}
**Description**: The state of this issue or merge request.
**Field name**: `state`
**Allowed operators**: `=`
@ -965,6 +1142,8 @@ This page lists fields available to use as filters when querying issues or work
## Updated at
**Description**: Query issues or merge requests by when they were last updated.
**Field name**: `updated`
**Allowed operators**: `=`, `>`, `<`
@ -1009,6 +1188,8 @@ This page lists fields available to use as filters when querying issues or work
## Weight
**Description**: Query issues by their weight.
**Field name**: `weight`
**Allowed operators**: `=`, `!=`

View File

@ -13,14 +13,20 @@ title: Create users
{{< /details >}}
User accounts form the foundation of GitLab collaboration. Every person who needs access to your GitLab
projects requires an account. User accounts control access permissions, track contributions, and maintain
security across your instance.
You can create user accounts in GitLab in different ways:
- Direct users to create their own account.
- Create accounts for other users manually.
- Configure authentication integrations.
- Create users through the Rails console.
- Self-registration for teams who value autonomy
- Admin-driven creation for controlled onboarding
- Authentication integration for enterprise environments
- Console access for automation and bulk operations
If you want to automate user creation, you should use the [users API endpoint](../../../api/users.md#create-a-user).
You can also use the [users API endpoint](../../../api/users.md#create-a-user) to automatically create users.
Choose the right method based on your organization's size, security requirements, and workflows.
## Create users on sign-in page

View File

@ -93,7 +93,7 @@ module BulkImports
if sub_relation.is_a?(Array)
sub_relation
.map { |entry| deep_transform_relation!(entry, sub_relation_key, sub_relation_definition, &block) }
.tap { |entry| entry.compact! }
.tap(&:compact!)
.presence
else
deep_transform_relation!(sub_relation, sub_relation_key, sub_relation_definition, &block)

View File

@ -30,15 +30,11 @@ module ContainerRegistry
}.freeze
def self.supports_tag_delete?
with_dummy_client(return_value_if_disabled: false) do |client|
client.supports_tag_delete?
end
with_dummy_client(return_value_if_disabled: false, &:supports_tag_delete?)
end
def self.registry_info
with_dummy_client do |client|
client.registry_info
end
with_dummy_client(&:registry_info)
end
def registry_info

View File

@ -27,9 +27,7 @@ module ContainerRegistry
UnsuccessfulResponseError = Class.new(StandardError)
def self.supports_gitlab_api?
with_dummy_client(return_value_if_disabled: false) do |client|
client.supports_gitlab_api?
end
with_dummy_client(return_value_if_disabled: false, &:supports_gitlab_api?)
end
def self.deduplicated_size(path)

View File

@ -61,7 +61,7 @@ module Gitlab
# hash for defining ActiveRecord enum: identifier => number
def self.to_enum
enum_mapping.transform_keys { |k| k.identifier }
enum_mapping.transform_keys(&:identifier)
end
def self.pairing_rules

View File

@ -110,7 +110,7 @@ module Gitlab
end
def expand_directions
return [:both] if (1...MAX_EXPANDABLE_LINES).cover?(line_count_between)
return [:both] if (1..MAX_EXPANDABLE_LINES).cover?(line_count_between)
directions = []
directions << :down if @previous_line_pos&.positive?
@ -123,7 +123,8 @@ module Gitlab
def line_count_between
return 0 if invalid_pos?(@previous_line_pos) || invalid_pos?(@next_line_pos)
@next_line_pos - @previous_line_pos
# 1..3 -> lines in between: 1
@next_line_pos - @previous_line_pos - 1
end
def invalid_pos?(pos)

View File

@ -33,6 +33,12 @@ module Gitlab
increment_total_events_counter
end
def emit_event_payload(payload)
# Using #input as the tracker doesn't have an option to track using a json object
# https://snowplow.github.io/snowplow-ruby-tracker/SnowplowTracker/Emitter.html#input-instance_method
emitter.input(payload)
end
def options(group)
additional_features = Feature.enabled?(:additional_snowplow_tracking, group, type: :ops)
{
@ -77,7 +83,14 @@ module Gitlab
end
def emitter
emitter_options = {
@emitter ||= SnowplowTracker::AsyncEmitter.new(
endpoint: hostname,
options: emitter_options
)
end
def emitter_options
options = {
protocol: protocol,
on_success: method(:increment_successful_events_emissions),
on_failure: method(:failure_callback)
@ -86,15 +99,12 @@ module Gitlab
if Feature.enabled?(:snowplow_tracking_post_method, :instance, type: :gitlab_com_derisk)
# By default, Snowplow uses `get` method with buffer_size set to `1`.
# However, setting method to `post` changes default buffer_size to `10`
emitter_options[:method] = 'post'
options[:method] = 'post'
buffer_size = Feature.enabled?(:snowplow_buffer_events, :instance, type: :gitlab_com_derisk) ? 10 : 1
emitter_options[:buffer_size] = buffer_size
options[:buffer_size] = buffer_size
end
SnowplowTracker::AsyncEmitter.new(
endpoint: hostname,
options: emitter_options
)
options
end
def failure_callback(success_count, failures)

View File

@ -13579,6 +13579,12 @@ msgstr ""
msgid "ClusterIntegration|Advanced options on this Kubernetes clusters integration"
msgstr ""
msgid "ClusterIntegration|Agent name"
msgstr ""
msgid "ClusterIntegration|Agent setup failed"
msgstr ""
msgid "ClusterIntegration|Allow GitLab to manage namespaces and service accounts for this cluster."
msgstr ""
@ -13657,6 +13663,9 @@ msgstr ""
msgid "ClusterIntegration|Create a Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|Create agent and migrate"
msgstr ""
msgid "ClusterIntegration|Deploy each environment to its own namespace. Otherwise, environments within a project share a project-wide namespace. Note that anyone who can trigger a deployment of a namespace can read its secrets. If modified, existing environments will use their current namespaces until the cluster cache is cleared."
msgstr ""
@ -13672,6 +13681,9 @@ msgstr ""
msgid "ClusterIntegration|Enable this setting if using role-based access control (RBAC)."
msgstr ""
msgid "ClusterIntegration|Enter a unique name for your new GitLab Agent. This name will be used to identify the agent in your project."
msgstr ""
msgid "ClusterIntegration|Enter details about your cluster. %{linkStart}How do I use a certificate to connect to my cluster?%{linkEnd}"
msgstr ""
@ -13714,10 +13726,13 @@ msgstr ""
msgid "ClusterIntegration|HTTP Error"
msgstr ""
msgid "ClusterIntegration|How do I migrate to the GitLab agent?"
msgstr ""
msgid "ClusterIntegration|If you do not wish to delete all associated GitLab resources, you can simply remove the integration."
msgstr ""
msgid "ClusterIntegration|Install agent"
msgid "ClusterIntegration|Installing agent in progress."
msgstr ""
msgid "ClusterIntegration|Instance cluster"
@ -13729,6 +13744,9 @@ msgstr ""
msgid "ClusterIntegration|Integration enabled"
msgstr ""
msgid "ClusterIntegration|Invalid configuration project"
msgstr ""
msgid "ClusterIntegration|Kubernetes cluster is being created..."
msgstr ""
@ -13747,6 +13765,9 @@ msgstr ""
msgid "ClusterIntegration|Learn more about instance Kubernetes clusters"
msgstr ""
msgid "ClusterIntegration|Learn more about migrating to GitLab Agent"
msgstr ""
msgid "ClusterIntegration|Make sure your API endpoint is correct"
msgstr ""
@ -13756,10 +13777,7 @@ msgstr ""
msgid "ClusterIntegration|Migrate"
msgstr ""
msgid "ClusterIntegration|Migrate this cluster to use the GitLab agent for Kubernetes"
msgstr ""
msgid "ClusterIntegration|Migrate to the GitLab agent for Kubernetes"
msgid "ClusterIntegration|Migrate to GitLab Agent for Kubernetes"
msgstr ""
msgid "ClusterIntegration|Migrating cluster - failed: \"%{error}\""
@ -13771,12 +13789,18 @@ msgstr ""
msgid "ClusterIntegration|Namespace per environment"
msgstr ""
msgid "ClusterIntegration|New agent name"
msgstr ""
msgid "ClusterIntegration|Node calculations use the Kubernetes Metrics API. Make sure your cluster has metrics installed"
msgstr ""
msgid "ClusterIntegration|Project cluster"
msgstr ""
msgid "ClusterIntegration|Project name"
msgstr ""
msgid "ClusterIntegration|Project namespace (optional, unique)"
msgstr ""
@ -13813,6 +13837,9 @@ msgstr ""
msgid "ClusterIntegration|See and edit the details for your Kubernetes cluster"
msgstr ""
msgid "ClusterIntegration|Select a project for the GitLab Agent."
msgstr ""
msgid "ClusterIntegration|Service Token"
msgstr ""
@ -13831,12 +13858,24 @@ msgstr ""
msgid "ClusterIntegration|Specifying a domain will allow you to use Auto Review Apps and Auto Deploy stages for %{linkStart}Auto DevOps.%{linkEnd} The domain should have a wildcard DNS configured matching the domain. "
msgstr ""
msgid "ClusterIntegration|Step 1. Connect the agent"
msgstr ""
msgid "ClusterIntegration|The %{agent_docs_link_start}GitLab Agent for Kubernetes %{agent_docs_link_end} offers improved security, reliability, and functionality. Follow the steps below to create a new agent and migrate your existing certificate-based integration. The process is automated, but you still need to %{install_docs_link_start}install the agent%{install_docs_link_end} in your cluster."
msgstr ""
msgid "ClusterIntegration|The Kubernetes certificate used to authenticate to the cluster."
msgstr ""
msgid "ClusterIntegration|The URL used to access the Kubernetes API."
msgstr ""
msgid "ClusterIntegration|The agent connection is set up."
msgstr ""
msgid "ClusterIntegration|The agent was not installed in the cluster."
msgstr ""
msgid "ClusterIntegration|The certificate-based Kubernetes integration is deprecated and will be removed in the future. You should %{linkStart}migrate to the GitLab agent for Kubernetes%{linkEnd}. For more information, see the %{deprecationLinkStart}deprecation epic%{deprecationLinkEnd}, or contact GitLab support."
msgstr ""
@ -13855,9 +13894,6 @@ msgstr ""
msgid "ClusterIntegration|There was an HTTP error when connecting to your cluster."
msgstr ""
msgid "ClusterIntegration|This cluster integration is deprecated. To continue using this Kubernetes cluster with GitLab, you must install the agent."
msgstr ""
msgid "ClusterIntegration|This is necessary if your integration has become out of sync. The cache is repopulated during the next CI job that requires namespace and service accounts."
msgstr ""
@ -61722,6 +61758,9 @@ msgstr ""
msgid "Unauthenticated web rate limit period in seconds"
msgstr ""
msgid "Unauthorized"
msgstr ""
msgid "Unauthorized to access the cluster agent in this project"
msgstr ""

View File

@ -2,7 +2,7 @@
require 'yaml'
class Database
module Database
class QueryAnalyzers
attr_reader :analyzers

View File

@ -9,3 +9,5 @@ MultiplePartitionScanDetector:
# These fingerprints can be found in the auto_explain pipeline artifacts.
# Example:
# - c2cfe803a497101b
JSONBScanDetector:
todos:

View File

@ -3,7 +3,7 @@
require 'json'
require 'zlib'
class Database
module Database
class QueryAnalyzers
class Base
attr_accessor :output

View File

@ -0,0 +1,46 @@
# frozen_string_literal: true
require_relative 'base'
module Database
class QueryAnalyzers
class JSONBScanDetector < Database::QueryAnalyzers::Base
JSONB_MATCH_OPERATOR_EXPRESSION = /<@|@>/
def initialize(*args)
super
output[:bad_queries] = []
end
def analyze(query)
super
return if config['todos']&.include?(query['fingerprint'])
output[:bad_queries] << query if has_operator_in_where?(query['query'])
end
def save!
return if output[:bad_queries].empty?
Zlib::GzipWriter.open(output_path("jsonb_column_scans.ndjson")) do |file|
output[:bad_queries].each do |query|
file.puts(JSON.generate(query))
end
end
end
private
def has_operator_in_where?(query)
return false unless query.match?(JSONB_MATCH_OPERATOR_EXPRESSION)
clauses = query.split(/\sWHERE\s|\sJOIN\s/)
return false if clauses.length < 2
clauses[1..].each do |c|
return true if c.include?('::jsonb')
end
end
end
end
end

View File

@ -2,7 +2,7 @@
require_relative 'base'
class Database
module Database
class QueryAnalyzers
class MultiplePartitionScanDetector < Database::QueryAnalyzers::Base
def analyze(query)

View File

@ -17,8 +17,8 @@ RSpec.describe RapidDiffs::DiffFileComponent, type: :component, feature_category
it "renders server data" do
render_component
diff_path = "/#{namespace.to_param}/#{project.to_param}/-/blob/#{diff_file.content_sha}/#{diff_file.file_path}/diff"
expect(web_component['data-blob-diff-path']).to eq(diff_path)
diff_path = "/#{namespace.to_param}/#{project.to_param}/-/blob/#{diff_file.content_sha}/#{diff_file.file_path}"
expect(web_component['data-diff-lines-path']).to eq("#{diff_path}/diff_lines")
end
context "when is text diff" do

View File

@ -6,21 +6,27 @@ RSpec.describe RapidDiffs::Viewers::Text::ExpandLinesComponent, type: :component
it "renders expand up" do
render_component([:up])
expect(page).to have_selector('button svg use[href$="#expand-up"]')
expect(page).to have_selector('[data-expand-direction="up"]')
end
it "renders expand down" do
render_component([:down])
expect(page).to have_selector('button svg use[href$="#expand-down"]')
expect(page).to have_selector('[data-expand-direction="down"]')
end
it "renders expand up and down" do
render_component([:down, :up])
expect(page).to have_selector('button svg use[href$="#expand-up"]')
expect(page).to have_selector('button svg use[href$="#expand-down"]')
expect(page).to have_selector('[data-expand-direction="up"]')
expect(page).to have_selector('[data-expand-direction="down"]')
end
it "renders expand both" do
render_component([:both])
expect(page).to have_selector('button svg use[href$="#expand"]')
expect(page).to have_selector('[data-expand-direction="both"]')
end
def render_component(directions)

View File

@ -90,6 +90,16 @@ RSpec.describe RapidDiffs::Viewers::Text::InlineHunkComponent, type: :component,
expect(page).to have_selector('button svg use[href$="#expand"]')
end
it "renders testid" do
render_component
expect(page).to have_selector("[data-testid='hunk-lines-inline']")
end
it "renders data-hunk-lines" do
render_component
expect(page).to have_selector("[data-hunk-lines]")
end
def render_component(diff_hunk = hunk)
render_inline(
described_class.new(
@ -99,9 +109,4 @@ RSpec.describe RapidDiffs::Viewers::Text::InlineHunkComponent, type: :component,
)
)
end
it "renders testid" do
render_component
expect(page).to have_selector("[data-testid='hunk-lines-inline']")
end
end

View File

@ -33,6 +33,7 @@ RSpec.describe RapidDiffs::Viewers::Text::LineNumberComponent, type: :component,
expect(link[:'data-line-number']).to eq(old_line.old_pos.to_s)
expect(td[:id]).to eq(old_line.id(diff_file.file_hash, :old))
expect(td[:'data-legacy-id']).to eq(diff_file.line_code(old_line))
expect(page).to have_selector('[data-position="old"]')
end
it "renders link for added line on right side" do
@ -41,6 +42,7 @@ RSpec.describe RapidDiffs::Viewers::Text::LineNumberComponent, type: :component,
expect(link[:'data-line-number']).to eq(new_line.new_pos.to_s)
expect(td[:id]).to eq(new_line.id(diff_file.file_hash, :new))
expect(td[:'data-legacy-id']).to eq(diff_file.line_code(new_line))
expect(page).to have_selector('[data-position="new"]')
end
def render_component(line:, position: nil)

View File

@ -90,6 +90,16 @@ RSpec.describe RapidDiffs::Viewers::Text::ParallelHunkComponent, type: :componen
expect(page).to have_selector('button svg use[href$="#expand"]')
end
it "renders testid" do
render_component
expect(page).to have_selector("[data-testid='hunk-lines-parallel']")
end
it "renders data-hunk-lines" do
render_component
expect(page).to have_selector("[data-hunk-lines]")
end
def render_component(diff_hunk = hunk)
render_inline(
described_class.new(
@ -99,9 +109,4 @@ RSpec.describe RapidDiffs::Viewers::Text::ParallelHunkComponent, type: :componen
)
)
end
it "renders testid" do
render_component
expect(page).to have_selector("[data-testid='hunk-lines-parallel']")
end
end

View File

@ -212,7 +212,10 @@ RSpec.describe Admin::ClustersController, feature_category: :deployment_manageme
def go
post :migrate,
params: {
configuration_project_id: configuration_project.id,
cluster_migration: {
configuration_project_id: configuration_project.id,
agent_name: 'new-agent'
},
id: cluster
}
end
@ -226,6 +229,7 @@ RSpec.describe Admin::ClustersController, feature_category: :deployment_manageme
Clusters::Migration::CreateService,
an_object_having_attributes(class: cluster.class, id: cluster.id),
current_user: admin,
agent_name: 'new-agent',
configuration_project_id: configuration_project.id.to_s
) do |service|
expect(service).to receive(:execute).and_call_original

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe EventForward::Logger, feature_category: :product_analytics do
subject(:logger) { described_class.new('/dev/null') }
it_behaves_like 'a json logger', {}
describe '#file_name_noext' do
it 'returns log file name without extension' do
expect(described_class.file_name_noext).to eq('event_collection')
end
end
end

View File

@ -257,8 +257,11 @@ RSpec.describe Groups::ClustersController, feature_category: :deployment_managem
def go
post :migrate,
params: {
cluster_migration: {
configuration_project_id: configuration_project.id,
agent_name: 'new-agent'
},
group_id: group,
configuration_project_id: configuration_project.id,
id: cluster
}
end
@ -272,6 +275,7 @@ RSpec.describe Groups::ClustersController, feature_category: :deployment_managem
Clusters::Migration::CreateService,
an_object_having_attributes(class: cluster.class, id: cluster.id),
current_user: user,
agent_name: 'new-agent',
configuration_project_id: configuration_project.id.to_s
) do |service|
expect(service).to receive(:execute).and_call_original
@ -300,6 +304,7 @@ RSpec.describe Groups::ClustersController, feature_category: :deployment_managem
describe 'security' do
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { expect { go }.to be_allowed_for(:admin) }
it('is denied for admin when admin mode is disabled') { expect { go }.to be_denied_for(:admin) }
it { expect { go }.to be_allowed_for(:owner).of(group) }
it { expect { go }.to be_allowed_for(:maintainer).of(group) }

View File

@ -278,9 +278,12 @@ RSpec.describe Projects::ClustersController, feature_category: :deployment_manag
def go
post :migrate,
params: {
cluster_migration: {
configuration_project_id: project.id,
agent_name: 'new-agent'
},
namespace_id: project.namespace,
project_id: project,
configuration_project_id: project.id,
id: cluster
}
end
@ -294,6 +297,7 @@ RSpec.describe Projects::ClustersController, feature_category: :deployment_manag
Clusters::Migration::CreateService,
an_object_having_attributes(class: cluster.class, id: cluster.id),
current_user: user,
agent_name: 'new-agent',
configuration_project_id: project.id.to_s
) do |service|
expect(service).to receive(:execute).and_call_original
@ -322,6 +326,7 @@ RSpec.describe Projects::ClustersController, feature_category: :deployment_manag
describe 'security' do
it('is allowed for admin when admin mode is enabled', :enable_admin_mode) { expect { go }.to be_allowed_for(:admin) }
it('is denied for admin when admin mode is disabled') { expect { go }.to be_denied_for(:admin) }
it { expect { go }.to be_allowed_for(:owner).of(project) }
it { expect { go }.to be_allowed_for(:maintainer).of(project) }

View File

@ -8,6 +8,7 @@ FactoryBot.define do
before(:create) do |migration|
migration.project = migration.agent.project
migration.agent_name = migration.agent.name
end
agent_install_status { :pending }

View File

@ -99,10 +99,79 @@ RSpec.describe 'Clusterable > Show page', feature_category: :deployment_manageme
end
end
shared_examples 'migration tab' do
describe 'migration tab' do
before do
stub_feature_flags(cluster_agent_migrations: true)
visit cluster_path
click_link 'Migrate'
end
it 'shows the migration form when no agent exists' do
expect(page).to have_content('Migrate to GitLab Agent for Kubernetes')
expect(page).to have_selector('.js-vue-project-select')
expect(page).to have_field('Agent name')
expect(page).to have_button('Create agent and migrate')
end
context 'when agent exists' do
let!(:agent) { create(:cluster_agent) }
let!(:cluster_migration) do
create(:cluster_agent_migration, cluster: cluster, agent: agent, agent_install_status: :success)
end
before do
visit cluster_path
click_link 'Migrate'
end
it 'shows agent information' do
expect(page).to have_content('The agent connection is set up')
expect(page).to have_content("#{agent.name}##{agent.id}")
expect(page).to have_content(cluster_migration.project.full_name)
end
end
context 'with different installation states' do
let!(:cluster_migration) { create(:cluster_agent_migration, cluster: cluster) }
it 'shows in_progress state' do
cluster_migration.update!(agent_install_status: :in_progress)
visit cluster_path
click_link 'Migrate'
expect(page).to have_content('Installing agent in progress')
end
it 'shows error state' do
cluster_migration.update!(agent_install_status: :error, agent_install_message: 'Failed to install')
visit cluster_path
click_link 'Migrate'
expect(page).to have_content('Agent setup failed')
expect(page).to have_content('Failed to install')
end
end
describe 'creating an agent', :js do
it 'creates agent successfully' do
within_testid('cluster-migration-form') do
select_from_project_select
fill_in 'Agent name', with: 'test-agent'
click_button 'Create agent and migrate'
end
expect(page).to have_content('Migrating cluster - initiated')
end
end
end
end
context 'when clusterable is a project' do
let(:clusterable) { create(:project) }
let(:cluster_path) { project_cluster_path(clusterable, cluster) }
let(:cluster) { create(:cluster, :provided_by_gcp, :project, projects: [clusterable]) }
let!(:configuration_project) { clusterable }
before do
clusterable.add_maintainer(current_user)
@ -117,12 +186,15 @@ RSpec.describe 'Clusterable > Show page', feature_category: :deployment_manageme
it_behaves_like 'editing a user-provided cluster' do
let(:cluster) { create(:cluster, :provided_by_user, :project, projects: [clusterable]) }
end
it_behaves_like 'migration tab'
end
context 'when clusterable is a group' do
let(:clusterable) { create(:group) }
let(:cluster_path) { group_cluster_path(clusterable, cluster) }
let(:cluster) { create(:cluster, :provided_by_gcp, :group, groups: [clusterable]) }
let!(:configuration_project) { create(:project, group: clusterable) }
before do
clusterable.add_maintainer(current_user)
@ -137,15 +209,20 @@ RSpec.describe 'Clusterable > Show page', feature_category: :deployment_manageme
it_behaves_like 'editing a user-provided cluster' do
let(:cluster) { create(:cluster, :provided_by_user, :group, groups: [clusterable]) }
end
it_behaves_like 'migration tab'
end
context 'when clusterable is an instance' do
let(:current_user) { create(:admin) }
let(:cluster_path) { admin_cluster_path(cluster) }
let(:cluster) { create(:cluster, :provided_by_gcp, :instance) }
let!(:configuration_project) { create(:project) }
before do
enable_admin_mode!(current_user)
configuration_project.add_owner(current_user)
enable_admin_mode!(current_user)
end
it_behaves_like 'show page' do
@ -157,6 +234,8 @@ RSpec.describe 'Clusterable > Show page', feature_category: :deployment_manageme
it_behaves_like 'editing a user-provided cluster' do
let(:cluster) { create(:cluster, :provided_by_user, :instance) }
end
it_behaves_like 'migration tab'
end
private
@ -168,4 +247,10 @@ RSpec.describe 'Clusterable > Show page', feature_category: :deployment_manageme
expect(page).to have_content('Remove Kubernetes cluster integration')
end
end
def select_from_project_select
click_button('Search for project')
wait_for_requests
find('.gl-new-dropdown-item').click
end
end

Some files were not shown because too many files have changed in this diff Show More