Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2025-04-14 09:12:26 +00:00
parent ab621c63b7
commit c799d8a4fb
55 changed files with 767 additions and 163 deletions

View File

@ -17,11 +17,6 @@ include:
.build-cng-env:
image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}-slim-bookworm
stage: prepare
needs:
# We need this job because we need its `cached-assets-hash.txt` artifact, so that we can pass the assets image tag to the downstream CNG pipeline.
# TODO: refactor to pass assets hash as environment variable to not download all of the actual assets needlessly
- pipeline: $PARENT_PIPELINE_ID
job: compile-production-assets
variables:
BUILD_ENV: build.env
CNG_PROJECT_PATH: "${CI_PROJECT_NAMESPACE}/$[[ inputs.cng_path ]]"
@ -32,7 +27,6 @@ include:
- install_gitlab_gem
script:
- 'ruby -r./scripts/trigger-build.rb -e "puts Trigger.variables_for_env_file(Trigger::CNG.new.variables)" > $BUILD_ENV'
- echo "GITLAB_ASSETS_TAG=$(assets_image_tag)" >> $BUILD_ENV
- echo -e "section_start:`date +%s`:cng_var_setup_log[collapsed=true]\r\e[0KCNG Variables Script Log Output"
- cat $CNG_VAR_SETUP_LOG_FILE
- echo -e "section_end:`date +%s`:cng_var_setup_log\r\e[0K"
@ -58,6 +52,7 @@ include:
GITLAB_VERSION: "${GITLAB_VERSION}"
GITLAB_TAG: "${GITLAB_TAG}"
GITLAB_ASSETS_TAG: "${GITLAB_ASSETS_TAG}"
COMPILE_ASSETS: "${COMPILE_ASSETS}"
CE_PIPELINE: "${CE_PIPELINE}" # Based on https://docs.gitlab.com/ee/ci/jobs/job_control.html#check-if-a-variable-exists, `if: '$CE_PIPELINE'` will evaluate to `false` when this variable is empty
EE_PIPELINE: "${EE_PIPELINE}" # Based on https://docs.gitlab.com/ee/ci/jobs/job_control.html#check-if-a-variable-exists, `if: '$EE_PIPELINE'` will evaluate to `false` when this variable is empty
GITLAB_ELASTICSEARCH_INDEXER_VERSION: "${GITLAB_ELASTICSEARCH_INDEXER_VERSION}"

View File

@ -43,10 +43,14 @@ compile-production-assets:
- $GLCI_PRODUCTION_ASSETS_RUNNER_OPTIONAL
variables:
GLCI_BUILD_ASSETS_IMAGE: "true"
GLCI_ASSETS_TAG_ENV_FILE_PATH: "assets-tag-env.env"
ARCH: linux/amd64,linux/arm64
before_script:
- !reference [.compile-assets-base, before_script]
- !reference [.buildx-setup, before_script]
after_script:
- source scripts/utils.sh
- echo "GLCI_ASSETS_IMAGE_TAG=$(assets_image_tag)" > $GLCI_ASSETS_TAG_ENV_FILE_PATH
artifacts:
name: webpack-report
expire_in: 31d
@ -58,6 +62,8 @@ compile-production-assets:
- public/assets/
- "${WEBPACK_COMPILE_LOG_PATH}"
when: always
reports:
dotenv: $GLCI_ASSETS_TAG_ENV_FILE_PATH
compile-production-assets as-if-foss:
extends:

View File

@ -91,7 +91,6 @@ trigger-omnibus:
USE_SPECIFIED_RUBY_VERSION: "true"
RUBY_VERSION: $FULL_RUBY_VERSION
BUILD_ON_ALL_OS: $OMNIBUS_GITLAB_BUILD_ON_ALL_OS
SKIP_QA_TEST: "true" # Deprecated: It'll be removed once rolling out `inputs.skip_qa_test`.
ee: $EE
trigger:
project: gitlab-org/build/omnibus-gitlab-mirror

View File

@ -35,6 +35,7 @@
DYNAMIC_PIPELINE_YML: "${CI_PROJECT_DIR}/qa/tmp/test-on-omnibus-pipeline.yml" # yml files are generated by generate_e2e_pipelines task in qa/tasks/ci.rake
PARENT_PIPELINE_ID: $CI_PIPELINE_ID # This is needed by trigger-omnibus-env and build-cng-env jobs
QA_EXPORT_TEST_METRICS: "true" # Export test metrics directly to influxdb by default
GLCI_ASSETS_IMAGE_TAG: $GLCI_ASSETS_IMAGE_TAG
inherit:
variables: false
trigger:

View File

@ -8,6 +8,8 @@ start-release-environments-security-pipeline:
# as they cannot be overridden. See this issue for more context:
#
# https://gitlab.com/gitlab-org/gitlab/-/issues/387183
needs:
- compile-production-assets
inherit:
variables:
- RUBY_VERSION_DEFAULT
@ -18,8 +20,8 @@ start-release-environments-security-pipeline:
# They need to be explicitly passed on to the child pipeline.
# https://docs.gitlab.com/ci/pipelines/downstream_pipelines/#pass-yaml-defined-cicd-variables
variables:
# This is needed by `release-environments-build-cng-env` (`.gitlab/ci/release-environments/security.gitlab-ci.yml`).
PARENT_PIPELINE_ID: $CI_PIPELINE_ID
# used by build-cng-env to pass assets image tag to downstream CNG build pipeline
GLCI_ASSETS_IMAGE_TAG: $GLCI_ASSETS_IMAGE_TAG
trigger:
strategy: depend
include:

View File

@ -1,5 +1,5 @@
<script>
import { GlForm, GlFormInput, GlFormGroup, GlModal } from '@gitlab/ui';
import { GlForm, GlFormInput, GlFormInputGroup, GlFormGroup, GlModal } from '@gitlab/ui';
import { debounce } from 'lodash';
import axios from '~/lib/utils/axios_utils';
import { createAlert } from '~/alert';
@ -9,12 +9,15 @@ import {
WORK_ITEM_CREATE_ENTITY_MODAL_TARGET_BRANCH,
} from '~/work_items/constants';
import { visitUrl } from '~/lib/utils/url_utility';
import toast from '~/vue_shared/plugins/global_toast';
import { createBranchMRApiPathHelper } from '~/work_items/utils';
import { helpPagePath } from '~/helpers/help_page_helper';
import {
findInvalidBranchNameCharacters,
humanizeBranchValidationErrors,
} from '~/lib/utils/text_utility';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import getProjectRootRef from '~/work_items/graphql/get_project_root_ref.query.graphql';
import { s__, __ } from '~/locale';
import confidentialMergeRequestState from '~/confidential_merge_request/state';
@ -24,9 +27,11 @@ export default {
components: {
GlForm,
GlFormInput,
GlFormInputGroup,
GlFormGroup,
GlModal,
ProjectFormGroup,
ModalCopyButton,
},
i18n: {
sourceLabel: __('Source (branch or tag)'),
@ -344,6 +349,9 @@ export default {
this.invalidForm = false;
});
},
copyToClipboard() {
toast(__('Copied branch name.'));
},
},
WORK_ITEM_CREATE_ENTITY_MODAL_TARGET_SOURCE,
WORK_ITEM_CREATE_ENTITY_MODAL_TARGET_BRANCH,
@ -405,7 +413,7 @@ export default {
"
:state="branchName ? !invalidBranch : false"
>
<gl-form-input
<gl-form-input-group
id="branch-name-id"
v-model.trim="branchName"
data-testid="target-name"
@ -415,7 +423,16 @@ export default {
name="branch-name"
type="text"
@input="checkValidity($event, $options.WORK_ITEM_CREATE_ENTITY_MODAL_TARGET_BRANCH)"
/>
>
<template #append>
<modal-copy-button
:text="branchName"
:title="__('Copy to clipboard')"
:modal-id="$options.createMRModalId"
@success="copyToClipboard"
/>
</template>
</gl-form-input-group>
</gl-form-group>
</gl-form>
</gl-modal>

View File

@ -31,6 +31,12 @@
flex: 1 0;
}
// override .code styles because we can't apply .code directly on the diff file code class
// because diff files are unaware of the current user
.rd-app-code-theme.code {
background: transparent !important;
}
.rd-app-diffs-list {
transition: opacity 0.2s;
}

View File

@ -11,6 +11,7 @@
}
.rd-diff-file-header {
@apply gl-text-default;
position: sticky;
// 1px offset to hide top border
top: calc(var(--rd-app-sticky-top, 1px) - 1px);

View File

@ -3,8 +3,9 @@
}
.rd-no-preview-important {
background-color: $gl-feedback-warning-background-color;
color: $gl-feedback-warning-text-color;
// warning feedback background color looks over saturated in dark mode, we need to force a muted palette
background-color: light-dark(var(--gl-feedback-warning-background-color), #453522);
color: var(--gl-feedback-warning-text-color);
}
.rd-no-preview-paragraph {

View File

@ -1,7 +1,7 @@
@use 'highlight/common';
@use 'constants';
.rd-text-view-root {
background-color: var(--code-background, $gl-color-neutral-0);
font-family: $monospace-font;
line-height: constants.$code-line-height;
font-size: constants.$code-font-size;
@ -28,10 +28,10 @@
.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, var(--gl-border-color-default));
border-bottom: 1px solid var(--rd-hunk-header-border-color, var(--gl-border-color-default));
background-color: var(--rd-hunk-header-background-color, $gray-50);
color: var(--rd-hunk-header-color, $gray-400);
border-top: 1px solid var(--diff-expansion-background-color, var(--gl-border-color-default));
border-bottom: 1px solid var(--diff-expansion-background-color, var(--gl-border-color-default));
background-color: var(--code-diff-hunk-header-background-color, $gray-50);
color: var(--code-diff-hunk-header-color, $gray-400);
&:first-child {
border-top: 0;
@ -74,8 +74,6 @@
}
.rd-expand-lines-button {
@include common.diff-expansion($gray-100, $gray-700, $gray-200, $gray-800);
display: flex;
justify-content: center;
align-items: center;
@ -84,13 +82,13 @@
font-size: 0;
border: 0;
background-color: var(--rd-expand-lines-button-background-color, $gray-100);
color: var(--rd-expand-lines-button-color, var(--gl-text-color-subtle));
background-color: var(--code-diff-expand-button-background-color, $gray-100);
color: var(--code-diff-expand-button-color, var(--gl-text-color-subtle));
&:hover,
&:focus {
background-color: var(--rd-expand-lines-button-hover-background-color, $gray-200);
color: var(--rd-expand-lines-button-hover-color, $gray-800);
background-color:var(--code-diff-expand-button-hover-background-color, $gray-200);
color: var(--code-diff-expand-button-hover-color, $gray-800);
}
}
@ -101,41 +99,48 @@
.rd-line-number {
padding: 0 10px 0 5px;
text-align: right;
background-color: var(--rd-line-number-background-color, $white);
&:hover:not(:empty) {
@include common.line-number-hover;
}
background-color: var(--code-line-nubmer-background-color, $white);
// override content border
&:first-child {
margin-left: -1px;
border-left: 1px solid var(--rd-line-number-adjacent-border-color, rgba(0, 0, 0, 0.125));
border-left: 1px solid rgba(0, 0, 0, 0.125);
border-left: 1px solid light-dark(rgba(0, 0, 0, 0.125), var(--gl-border-color-default));
}
}
.rd-line-number:where([data-change=removed]) {
background-color: var(--rd-line-number-removed-background-color, $line-number-old);
// Do not use nesting here to allow quick jump to code based on the selector
.rd-line-number:hover:not(:empty) {
background-color: var(--code-line-nubmer-hover-background-color, $gl-color-purple-100);
border-color: var(--code-line-nubmer-hover-border-color, $gl-color-purple-200);
}
.rd-line-number:where([data-change=added]) {
background-color: var(--rd-line-number-added-background-color, $line-number-new);
.rd-line-number:hover:not(:empty) .rd-line-link {
color: var(--code-line-nubmer-hover-color, $gl-color-neutral-600);
}
.rd-line-number[data-change=removed] {
background-color: var(--diff-deletion-color, var(--code-old-diff-line-number-background-color, $line-number-old));
}
.rd-line-number[data-change=added] {
background-color: var(--diff-addition-color, var(--code-new-diff-line-number-background-color, $line-number-new));
}
.rd-line-number-border-right,
.rd-line-number-border-both {
border-right: 1px solid var(--rd-line-number-adjacent-border-color, rgba(0, 0, 0, 0.125));
border-right: 1px solid rgba(0, 0, 0, 0.125);
}
.rd-line-number-border-both {
border-left: 1px solid var(--rd-line-number-adjacent-border-color, rgba(0, 0, 0, 0.125));
border-left: 1px solid rgba(0, 0, 0, 0.125);
}
.rd-line-link {
display: block;
&, &:hover {
color: var(--rd-line-link-color, $gray-400);
color: var(--code-line-nubmer-color, $gray-400);
}
&::before {
@ -162,21 +167,21 @@
}
}
.rd-line-content:where([data-change=removed]) {
background-color: var(--rd-line-content-removed-background-color, $line-removed);
.rd-line-content[data-change=removed] {
background-color: var(--diff-deletion-color, var(--code-old-diff-background-color, $line-removed));
&::before {
content: "-";
color: var(--rd-line-content-removed-pseudo-color, scale-color($line-number-old, $red: -30%, $green: -30%, $blue: -30%));
color: var(--code-old-diff-sign-color, scale-color($line-number-old, $red: -30%, $green: -30%, $blue: -30%));
}
}
.rd-line-content:where([data-change=added]) {
background-color: var(--rd-line-content-added-background-color, $line-added);
.rd-line-content[data-change=added] {
background-color: var(--diff-addition-color, var(--code-new-diff-background-color, $line-added));
&::before {
content: "+";
color: var(--rd-line-content-added-pseudo-color, scale-color($line-number-new, $red: -30%, $green: -30%, $blue: -30%));
color: var(--code-new-diff-sign-color, scale-color($line-number-new, $red: -30%, $green: -30%, $blue: -30%));
}
}

View File

@ -843,11 +843,11 @@ h4 {
}
.idiff.deletion {
background: $line-removed-dark;
background: var(--code-old-inline-diff-background-color, $line-removed-dark);
}
.idiff.addition {
background: $line-added-dark;
background: var(--code-new-inline-diff-background-color, $line-added-dark);
}
/**

View File

@ -79,6 +79,10 @@ $white-gc-bg: #eaf2f5;
}
@mixin white-base {
--diff-expansion-background-color: #{$gl-color-neutral-100};
--code-background: #{$gl-color-neutral-0};
// Line numbers
.file-line-blame {
@include line-link($gl-color-neutral-1000, 'git');
@ -137,8 +141,6 @@ $white-gc-bg: #eaf2f5;
}
&.diff-grid-row {
--diff-expansion-background-color: #{$gl-color-neutral-100};
&.expansion {
&.match .diff-td {
color: $gl-color-neutral-400;

View File

@ -128,6 +128,36 @@ $dark-il: #de935f;
}
.code.dark {
--diff-expansion-background-color: #{$gl-color-neutral-600};
--code-line-nubmer-background-color: #{$dark-main-bg};
--code-line-nubmer-color: #{$dark-line-num-color};
--code-line-nubmer-hover-background-color: #{$gl-color-purple-800};
--code-line-nubmer-hover-border-color: #{$gl-color-purple-700};
--code-line-nubmer-hover-color: #{$gl-color-purple-50};
--code-old-diff-line-number-background-color: #{$dark-old-bg};
--code-old-diff-sign-color: #{$dark-line-num-color-old};
--code-old-diff-background-color: #{$dark-old-bg};
--code-old-diff-border-color: #{$dark-border};
--code-old-diff-color: #{$dark-line-num-color-old};
--code-old-inline-diff-background-color: #{$dark-old-idiff};
--code-new-diff-line-number-background-color: #{$dark-new-bg};
--code-new-diff-sign-color: #{$dark-line-num-color-new};
--code-new-diff-background-color: #{$dark-new-bg};
--code-new-diff-border-color: #{$dark-border};
--code-new-diff-color: #{$dark-line-num-color-new};
--code-new-inline-diff-background-color: #{$dark-new-idiff};
--code-diff-hunk-header-background-color: #{$dark-diff-match-color};
--code-diff-hunk-header-color: #{$dark-diff-match-bg};
--code-diff-expand-button-background-color: #{$gl-color-neutral-600};
--code-diff-expand-button-color: #{$gl-color-neutral-200};
--code-diff-expand-button-hover-background-color: #{$gl-color-neutral-300};
--code-diff-expand-button-hover-color: #{$gl-color-neutral-0};
// Highlight.js theme overrides (https://gitlab.com/gitlab-org/gitlab/-/issues/365167)
// We should be able to remove the overrides once the upstream issue is fixed (https://github.com/sourcegraph/sourcegraph/issues/23251)
@include hljs-override('title\\.class', $dark-nc);
@ -165,6 +195,7 @@ $dark-il: #de935f;
&,
pre.code,
.line_holder .line_content {
--code-background: #{$dark-main-bg};
background-color: $dark-main-bg;
color: $dark-line-color;
}
@ -187,8 +218,6 @@ $dark-il: #de935f;
}
&.diff-grid-row {
--diff-expansion-background-color: #{$gl-color-neutral-600};
@include dark-diff-expansion-line;
}

View File

@ -99,6 +99,38 @@ $monokai-gh: #75715e;
}
.code.monokai {
--diff-expansion-background-color: #{$gl-color-neutral-600};
--code-background: #{$monokai-bg};
--code-line-nubmer-background-color: #{$monokai-bg};
--code-line-nubmer-color: #{$monokai-line-num-color};
--code-line-nubmer-hover-background-color: #{$gl-color-purple-800};
--code-line-nubmer-hover-border-color: #{$gl-color-purple-700};
--code-line-nubmer-hover-color: #{$gl-color-purple-50};
--code-old-diff-line-number-background-color: #{$monokai-old-bg};
--code-old-diff-sign-color: #{$monokai-line-num-color-old};
--code-old-diff-background-color: #{$monokai-old-bg};
--code-old-diff-border-color: #{$monokai-diff-border};
--code-old-diff-color: #{$monokai-line-num-color-old};
--code-old-inline-diff-background-color: #{$monokai-old-idiff};
--code-new-diff-line-number-background-color: #{$monokai-new-bg};
--code-new-diff-sign-color: #{$monokai-line-num-color-new};
--code-new-diff-background-color: #{$monokai-new-bg};
--code-new-diff-border-color: #{$monokai-diff-border};
--code-new-diff-color: #{$monokai-line-num-color-new};
--code-new-inline-diff-background-color: #{$monokai-new-idiff};
--code-diff-hunk-header-background-color: #{$dark-diff-match-color};
--code-diff-hunk-header-color: #{$dark-diff-match-bg};
--code-diff-expand-button-background-color: #{$gl-color-neutral-600};
--code-diff-expand-button-color: #{$gl-color-neutral-200};
--code-diff-expand-button-hover-background-color: #{$gl-color-neutral-300};
--code-diff-expand-button-hover-color: #{$gl-color-neutral-0};
// Highlight.js theme overrides (https://gitlab.com/gitlab-org/gitlab/-/issues/365167)
// We should be able to remove the overrides once the upstream issue is fixed (https://github.com/sourcegraph/sourcegraph/issues/23251)
@include hljs-override('string', $monokai-s);
@ -178,8 +210,6 @@ $monokai-gh: #75715e;
}
&.diff-grid-row {
--diff-expansion-background-color: #{$gl-color-neutral-600};
@include dark-diff-expansion-line;
}

View File

@ -19,6 +19,23 @@ $none-code-mark: #d3e3f4;
}
.code.none {
--diff-expansion-background-color: #{$gl-color-neutral-100};
--code-background: #{$gl-color-neutral-0};
--code-line-nubmer-background-color: #{$gl-color-neutral-10};
--code-line-nubmer-color: #{$gl-color-alpha-dark-24};
--code-old-diff-line-number-background-color: #{$gl-color-neutral-50};
--code-old-diff-sign-color: #{$gl-color-neutral-800};
--code-old-diff-background-color: #{$gl-color-neutral-50};
--code-old-inline-diff-background-color: #{rgba(0,0,0,0.1)};
--code-new-diff-line-number-background-color: #{$gl-color-neutral-50};
--code-new-diff-sign-color: #{$gl-color-neutral-800};
--code-new-diff-background-color: #{$gl-color-neutral-50};
--code-new-inline-diff-background-color: #{rgba(0,0,0,0.1)};
// Highlight.js theme overrides (https://gitlab.com/gitlab-org/gitlab/-/issues/365167)
// We should be able to remove the overrides once the upstream issue is fixed (https://github.com/sourcegraph/sourcegraph/issues/23251)
&.blob-viewer {
@ -76,10 +93,6 @@ $none-code-mark: #d3e3f4;
@include match-line;
}
&.diff-grid-row {
--diff-expansion-background-color: #{$gl-color-neutral-100};
}
.line-coverage {
@include line-coverage-border-color($gl-color-green-500, $gl-color-orange-500);
}

View File

@ -102,6 +102,38 @@ $solarized-dark-il: #2aa198;
}
.code.solarized-dark {
--diff-expansion-background-color: #{lighten($solarized-dark-pre-bg, 10%)};
--code-background: #{$solarized-dark-pre-bg};
--code-line-nubmer-background-color: #{$solarized-dark-line-bg};
--code-line-nubmer-color: #{$solarized-dark-line-color};
--code-line-nubmer-hover-background-color: #{$gl-color-purple-800};
--code-line-nubmer-hover-border-color: #{$gl-color-purple-700};
--code-line-nubmer-hover-color: #{$gl-color-purple-50};
--code-old-diff-line-number-background-color: #{$solarized-dark-old-bg};
--code-old-diff-sign-color: #{$solarized-dark-line-color-old};
--code-old-diff-background-color: #{$solarized-dark-old-bg};
--code-old-diff-border-color: #{$solarized-dark-border};
--code-old-diff-color: #{$solarized-dark-line-color-old};
--code-old-inline-diff-background-color: #{$solarized-dark-old-idiff};
--code-new-diff-line-number-background-color: #{$solarized-dark-new-bg};
--code-new-diff-sign-color: #{$solarized-dark-line-color-new};
--code-new-diff-background-color: #{$solarized-dark-new-bg};
--code-new-diff-border-color: #{$solarized-dark-border};
--code-new-diff-color: #{$solarized-dark-line-color-new};
--code-new-inline-diff-background-color: #{$solarized-dark-new-idiff};
--code-diff-hunk-header-background-color: #{$dark-diff-match-color};
--code-diff-hunk-header-color: #{$dark-diff-match-bg};
--code-diff-expand-button-background-color: #{lighten($solarized-dark-pre-bg, 10%)};
--code-diff-expand-button-color: #{$gl-color-neutral-200};
--code-diff-expand-button-hover-background-color: #{lighten($solarized-dark-pre-bg, 20%)};
--code-diff-expand-button-hover-color: #{$gl-color-neutral-0};
// Highlight.js theme overrides (https://gitlab.com/gitlab-org/gitlab/-/issues/365167)
// We should be able to remove the overrides once the upstream issue is fixed (https://github.com/sourcegraph/sourcegraph/issues/23251)
@include hljs-override('string', $solarized-dark-s);
@ -181,8 +213,6 @@ $solarized-dark-il: #2aa198;
}
&.diff-grid-row {
--diff-expansion-background-color: #{lighten($solarized-dark-pre-bg, 10%)};
@include dark-diff-expansion-line;
}

View File

@ -109,6 +109,30 @@ $solarized-light-il: #2aa198;
}
.code.solarized-light {
--diff-expansion-background-color: #{$gl-color-neutral-100};
--code-background: #{$solarized-light-pre-bg};
--code-line-nubmer-background-color: #{$solarized-light-line-bg};
--code-line-nubmer-color: #{$solarized-light-line-color};
--code-old-diff-line-number-background-color: #{$solarized-light-old-bg};
--code-old-diff-sign-color: #{$solarized-light-line-color-old};
--code-old-diff-background-color: #{$solarized-light-old-bg};
--code-old-diff-border-color: #{$solarized-light-border};
--code-old-diff-color: #{$solarized-light-line-color-old};
--code-old-inline-diff-background-color: #{$solarized-light-old-idiff};
--code-new-diff-line-number-background-color: #{$solarized-light-new-bg};
--code-new-diff-sign-color: #{$solarized-light-line-color-new};
--code-new-diff-background-color: #{$solarized-light-new-bg};
--code-new-diff-border-color: #{$solarized-light-border};
--code-new-diff-color: #{$solarized-light-line-color-new};
--code-new-inline-diff-background-color: #{$solarized-light-new-idiff};
--code-diff-hunk-header-background-color: #{$solarized-light-matchline-bg};
--code-diff-hunk-header-color: #{$gl-color-alpha-dark-24};
// Highlight.js theme overrides (https://gitlab.com/gitlab-org/gitlab/-/issues/365167)
// We should be able to remove the overrides once the upstream issue is fixed (https://github.com/sourcegraph/sourcegraph/issues/23251)
@include hljs-override('keyword', $solarized-light-k);
@ -165,10 +189,6 @@ $solarized-light-il: #2aa198;
@include match-line;
}
&.diff-grid-row {
--diff-expansion-background-color: #{$gl-color-neutral-100};
}
&.diff-grid-row.expansion .diff-td {
background-color: $solarized-light-matchline-bg;
}

View File

@ -27,7 +27,7 @@
- if empty_diff? && !@lazy
= render RapidDiffs::EmptyStateComponent.new
.code{ class: helpers.user_color_scheme }
.rd-app-code-theme.code{ class: helpers.user_color_scheme }
.rd-app-diffs-list{ data: { diffs_list: true } }
= javascript_tag nonce: content_security_policy_nonce do
:plain

View File

@ -45,7 +45,7 @@ module Issuable
}.with_indifferent_access.freeze
included do
cache_markdown_field :title, pipeline: :single_line
cache_markdown_field :title, pipeline: :single_line_markdown
cache_markdown_field :description, issuable_reference_expansion_enabled: true
redact_field :description
@ -153,7 +153,7 @@ module Issuable
includes(*associations)
end
attr_mentionable :title, pipeline: :single_line
attr_mentionable :title, pipeline: :single_line_markdown
attr_mentionable :description
participant :author

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
class DropArtifactsPartitionIdJobIdIndex < Gitlab::Database::Migration[2.2]
milestone '18.0'
INDEX_NAME = :p_ci_job_artifacts_partition_id_job_id_idx
COLUMNS = [:partition_id, :job_id]
# Index to be destroyed synchronously in
# https://gitlab.com/gitlab-org/gitlab/-/merge_requests/187564
#
def up
prepare_async_index_removal :p_ci_job_artifacts, COLUMNS, name: INDEX_NAME
end
def down
unprepare_async_index :p_ci_job_artifacts, COLUMNS, name: INDEX_NAME
end
end

View File

@ -0,0 +1 @@
26e359f933851e7383e30437fa9f19759a284cdde0c5e13997953fdecea1ec96

View File

@ -194,6 +194,8 @@ You can run the Geo tracking database on a single node as follows:
gitlab_rails['auto_migrate'] = false
```
1. [Opt out of automatic PostgreSQL upgrades](https://docs.gitlab.com/omnibus/settings/database/#opt-out-of-automatic-postgresql-upgrades) to avoid unintended downtime when upgrading GitLab. Be aware of the known [caveats when upgrading PostgreSQL with Geo](https://docs.gitlab.com/omnibus/settings/database/#caveats-when-upgrading-postgresql-with-geo). Especially for larger environments, PostgreSQL upgrades must be planned and executed consciously. As a result and going forward, ensure PostgreSQL upgrades are part of the regular maintenance activities.
After making these changes, [reconfigure GitLab](../../restart_gitlab.md#reconfigure-a-linux-package-installation) so the changes take effect.
If using an external PostgreSQL instance, refer also to

View File

@ -83,6 +83,8 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
sudo -i
```
1. [Opt out of automatic PostgreSQL upgrades](https://docs.gitlab.com/omnibus/settings/database/#opt-out-of-automatic-postgresql-upgrades) to avoid unintended downtime when upgrading GitLab. Be aware of the known [caveats when upgrading PostgreSQL with Geo](https://docs.gitlab.com/omnibus/settings/database/#caveats-when-upgrading-postgresql-with-geo). Especially for larger environments, PostgreSQL upgrades must be planned and executed consciously. As a result and going forward, ensure PostgreSQL upgrades are part of the regular maintenance activities.
1. Edit `/etc/gitlab/gitlab.rb` and add a **unique** name for your site:
```ruby
@ -348,6 +350,8 @@ There is an [issue where support is being discussed](https://gitlab.com/gitlab-o
sudo -i
```
1. [Opt out of automatic PostgreSQL upgrades](https://docs.gitlab.com/omnibus/settings/database/#opt-out-of-automatic-postgresql-upgrades) to avoid unintended downtime when upgrading GitLab. Be aware of the known [caveats when upgrading PostgreSQL with Geo](https://docs.gitlab.com/omnibus/settings/database/#caveats-when-upgrading-postgresql-with-geo). Especially for larger environments, PostgreSQL upgrades must be planned and executed consciously. As a result and going forward, ensure PostgreSQL upgrades are part of the regular maintenance activities.
1. Stop application server and Sidekiq:
```shell
@ -730,6 +734,8 @@ Leader instance**:
sudo -i
```
1. [Opt out of automatic PostgreSQL upgrades](https://docs.gitlab.com/omnibus/settings/database/#opt-out-of-automatic-postgresql-upgrades) to avoid unintended downtime when upgrading GitLab. Be aware of the known [caveats when upgrading PostgreSQL with Geo](https://docs.gitlab.com/omnibus/settings/database/#caveats-when-upgrading-postgresql-with-geo). Especially for larger environments, PostgreSQL upgrades must be planned and executed consciously. As a result and going forward, ensure PostgreSQL upgrades are part of the regular maintenance activities.
1. Edit `/etc/gitlab/gitlab.rb` and add the following:
```ruby
@ -790,6 +796,8 @@ Leader instance**:
sudo -i
```
1. [Opt out of automatic PostgreSQL upgrades](https://docs.gitlab.com/omnibus/settings/database/#opt-out-of-automatic-postgresql-upgrades) to avoid unintended downtime when upgrading GitLab. Be aware of the known [caveats when upgrading PostgreSQL with Geo](https://docs.gitlab.com/omnibus/settings/database/#caveats-when-upgrading-postgresql-with-geo). Especially for larger environments, PostgreSQL upgrades must be planned and executed consciously. As a result and going forward, ensure PostgreSQL upgrades are part of the regular maintenance activities.
1. Edit `/etc/gitlab/gitlab.rb` and add the following:
```ruby
@ -972,6 +980,8 @@ For each node running a Patroni instance on the secondary site:
sudo -i
```
1. [Opt out of automatic PostgreSQL upgrades](https://docs.gitlab.com/omnibus/settings/database/#opt-out-of-automatic-postgresql-upgrades) to avoid unintended downtime when upgrading GitLab. Be aware of the known [caveats when upgrading PostgreSQL with Geo](https://docs.gitlab.com/omnibus/settings/database/#caveats-when-upgrading-postgresql-with-geo). Especially for larger environments, PostgreSQL upgrades must be planned and executed consciously. As a result and going forward, ensure PostgreSQL upgrades are part of the regular maintenance activities.
1. Edit `/etc/gitlab/gitlab.rb` and add the following:
```ruby

View File

@ -39,6 +39,8 @@ Prerequisites:
sudo -i
```
1. [Opt out of automatic PostgreSQL upgrades](https://docs.gitlab.com/omnibus/settings/database/#opt-out-of-automatic-postgresql-upgrades) to avoid unintended downtime when upgrading GitLab. Be aware of the known [caveats when upgrading PostgreSQL with Geo](https://docs.gitlab.com/omnibus/settings/database/#caveats-when-upgrading-postgresql-with-geo). Especially for larger environments, PostgreSQL upgrades must be planned and executed consciously. As a result and going forward, ensure PostgreSQL upgrades are part of the regular maintenance activities.
1. Add a unique Geo site name to `/etc/gitlab/gitlab.rb`:
```ruby
@ -251,6 +253,8 @@ Prerequisites:
sudo -i
```
1. [Opt out of automatic PostgreSQL upgrades](https://docs.gitlab.com/omnibus/settings/database/#opt-out-of-automatic-postgresql-upgrades) to avoid unintended downtime when upgrading GitLab. Be aware of the known [caveats when upgrading PostgreSQL with Geo](https://docs.gitlab.com/omnibus/settings/database/#caveats-when-upgrading-postgresql-with-geo). Especially for larger environments, PostgreSQL upgrades must be planned and executed consciously. As a result and going forward, ensure PostgreSQL upgrades are part of the regular maintenance activities.
1. To prevent any commands from running before the site is configured, stop the application server and Sidekiq:
```shell

View File

@ -198,9 +198,9 @@ Use title case for **AI Impact Dashboard**.
On first mention on a page, use **GitLab Duo AI Impact Dashboard**.
Thereafter, use **AI Impact Dashboard** by itself.
## AI-powered DevSecOps platform
## AI-powered, AI-native
If preceded by GitLab, capitalize **Platform**. For example, the GitLab AI-powered DevSecOps Platform.
Use **AI-native** instead of **AI-powered**. For example, **Code Suggestions is an AI-native feature**.
## air gap, air-gapped
@ -743,10 +743,6 @@ Do not use bold.
Do not use **Developer permissions**. A user who is assigned the Developer role has a set of associated permissions.
## DevSecOps platform
If preceded by GitLab, capitalize **Platform**. For example, the GitLab DevSecOps Platform.
## dialog
Use **dialog** rather than any of these alternatives:

View File

@ -27,15 +27,18 @@ Use the Jira DVCS (distributed version control system) connector if you self-hos
with Jira Data Center or Jira Server and want to use the [Jira development panel](../development_panel.md).
The Jira DVCS connector is developed and maintained by Atlassian.
To configure the Jira DVCS connector, see the
[Atlassian documentation](https://confluence.atlassian.com/adminjiraserver/integrating-with-development-tools-using-dvcs-1047552689.html).
To configure the Jira DVCS connector, see
[integrating with development tools using DVCS](https://confluence.atlassian.com/adminjiraserver/integrating-with-development-tools-using-dvcs-1047552689.html).
Jira creates a webhook in the GitLab project to provide real-time updates.
To configure this webhook, you must have at least the Maintainer role for the project.
For more information, see [configuring webhook security](https://confluence.atlassian.com/adminjiraserver/configuring-webhook-security-1299913153.html).
If you're on Jira Cloud, migrate to the GitLab for Jira Cloud app.
For more information, see [Install the GitLab for Jira Cloud app](../connect-app.md#install-the-gitlab-for-jira-cloud-app).
## Refresh data imported to Jira
Jira imports commits and branches for GitLab projects every 60 minutes.
By default, Jira imports commits and branches for GitLab projects every 60 minutes.
To refresh the data manually in Jira:
1. Sign in to your Jira instance as the user you configured the integration with.

View File

@ -2,13 +2,12 @@
stage: Monitor
group: Platform Insights
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: Track errors, application performance issues, customer behavior patterns and manage incident response.
description: Track errors and manage incident response.
title: Monitor your application
---
Visualize and analyze errors, traces, metrics, logs, and product analytics events collected from your application and its infrastructure. Monitor, identify, and resolve performance and customer behavior related issues and incidents collaboratively.
Visualize and analyze errors and incidents related to your application and its infrastructure.
| | | |
|--|--|--|
| [**Getting started**](../user/get_started/get_started_monitoring.md)<br>Overview of how features fit together. | [**Error tracking**](error_tracking.md)<br>Error tracking, logging, debugging, and data retention. | [**Distributed tracing**](tracing.md)<br>Monitoring, troubleshooting, performance analysis, and request tracking. |
| [**Metrics**](metrics.md) and [**Logs**](logs.md)<br>Monitoring, visualization, aggregation, and retention. Centralized logging, analysis, configuration, and filtering. | [**Product Analytics**](product_analytics/_index.md)<br>Monitor and analyze your customer's behavior and core usage patterns within your applications. | [**Incident management**](incident_management/_index.md)<br>Alert handling, response coordination, and escalation procedures. |
| [**Getting started**](../user/get_started/get_started_monitoring.md)<br>Overview of how features fit together. | [**Error tracking**](error_tracking.md)<br>Error tracking, logging, debugging, data retention. | [**Incident management**](incident_management/_index.md)<br>Alert handling, response coordination, escalation procedures. |

View File

@ -140,7 +140,8 @@ see [placeholder user limits](#placeholder-user-limits).
{{< alert type="note" >}}
Ghost user contributions are handled differently. Contributions previously made by the ghost user (deleted user) on the source instance will automatically be mapped to the ghost user on the destination instance without creating placeholder users.
Contributions from a deleted user on the source instance are
mapped automatically to that user on the destination instance.
{{< /alert >}}
@ -192,8 +193,8 @@ Placeholder users do not count towards license limits.
A placeholder user is created for each user on the source instance, except in the following scenarios:
- You are importing a project from [Gitea](gitea.md) and the user has been deleted on Gitea before the import.
Contributions from these "ghost users" are mapped to the user who imported the project and not to a placeholder user.
- You're importing a project from [Gitea](gitea.md), and the user was deleted on Gitea before the import.
Contributions from these users are mapped to the user who imported the project, not to a placeholder user.
- You have exceeded your [placeholder user limit](#placeholder-user-limits). Contributions from any new users after exceeding your limit are
mapped to a single non-functional user called `Import User`.
- You are importing to a [personal namespace](../../namespace/_index.md#types-of-namespaces).
@ -226,12 +227,6 @@ To preserve historical context, the placeholder user name and username are deriv
#### View placeholder users
{{< history >}}
- Ability for administrators to filter for placeholder users for an instance [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/521974) in GitLab 17.11.
{{< /history >}}
Prerequisites:
- You must have the Owner role for the group.
@ -244,11 +239,30 @@ To view placeholder users created during imports to a top-level group and its su
1. Select **Manage > Members**.
1. Select the **Placeholders** tab.
Administrators can view all placeholder users created during imports for an entire instance:
#### Filter for placeholder users
{{< details >}}
- Offering: GitLab Self-Managed, GitLab Dedicated
{{< /details >}}
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/521974) in GitLab 17.11.
{{< /history >}}
Prerequisites:
- You must have administrator access to the instance.
Placeholder users are created on the destination instance while a group or project is imported.
To filter for placeholder users created during imports for an entire instance:
1. On the left sidebar, at the bottom, select **Admin**.
1. Select **Overview > Users**.
1. Use the user search box to filter users by **type**.
1. In the search box, filter users by **type**.
#### Placeholder user limits
@ -482,9 +496,8 @@ actual users later. Ensure all required reassignments are completed before keepi
placeholders.
You can keep contributions assigned to placeholder users either one at a time or in bulk.
When applied in bulk, it affects the entire namespace and only users with the following
**Reassignment status** values in the **Awaiting reassignment** tab:
When you reassign contributions in bulk, the entire namespace and users with the following
[reassignment statuses](#view-and-filter-by-reassignment-status) are affected:
- `Not started`
- `Rejected`
@ -531,9 +544,9 @@ If a user is not acting on a reassignment request, you can prompt them again by
1. Go to **Awaiting reassignment** sub-tab, where placeholders are listed in a table.
1. Select **Notify** in the correct row.
#### View and filter and sort by reassignment status
#### View and filter by reassignment status
You can review statuses of all placeholder users for which the reassignment process haven't been completed yet:
To view the reassignment status of all placeholder users:
1. On the left sidebar, select **Search or go to** and find your group.
This group must be at the top level.
@ -542,12 +555,7 @@ You can review statuses of all placeholder users for which the reassignment proc
1. Go to **Awaiting reassignment** sub-tab, where placeholders are listed in a table.
1. See the status of each placeholder user in **Reassignment status** column.
You can filter by reassignment status:
1. In filter dropdown list, select **Status**.
1. Choose one of available statuses.
In the **Awaiting reassignment** tab possible statuses are:
In the **Awaiting reassignment** tab, possible statuses are:
- `Not started` - Reassignment has not started.
- `Pending approval` - Reassignment is waiting on user approval.
@ -555,16 +563,13 @@ In the **Awaiting reassignment** tab possible statuses are:
- `Rejected` - Reassignment was rejected by user.
- `Failed` - Reassignment failed.
In the **Reassigned** tab possible statuses are:
In the **Reassigned** tab, possible statuses are:
- `Success` - Reassignment succeeded.
- `Kept as placeholder` - Placeholder user was made permanent.
By default, the table is sorted alphabetically by placeholder user name. You can also sort the table by reassignment
status:
1. Select on the sort dropdown list.
1. Select **Reassignment status**.
By default, the table is sorted alphabetically by placeholder user name.
You can also sort the table by reassignment status.
### Accept contribution reassignment

View File

@ -172,11 +172,15 @@ To automatically renew certificates, see [`cert-manager`](https://cert-manager.i
## Register a GitLab OAuth application
To register an application on your GitLab instance:
To register an OAuth application on your GitLab instance:
1. [Configure GitLab as an OAuth 2.0 identity provider](../../integration/oauth_provider.md).
1. [Create an OAuth application](../../integration/oauth_provider.md) in GitLab. You can create a:
- User-owned application
- Group-owned application
- Instance-wide application from the Admin area
1. Set the redirect URI to `https://${GITLAB_WORKSPACES_PROXY_DOMAIN}/auth/callback`.
1. Select the **Trusted** checkbox.
1. Ensure the **Confidential** checkbox is selected. It should be selected by default.
1. If you create an instance-wide application, also select the **Trusted** checkbox.
1. Set the scopes to `api`, `read_user`, `openid`, and `profile`.
1. Export your configuration values:
@ -188,7 +192,7 @@ To register an application on your GitLab instance:
export SIGNING_KEY="make_up_a_random_key_consisting_of_letters_numbers_and_special_chars"
```
1. Store the client ID and generated secret securely. For examples, in 1Password.
1. Store the client ID and generated secret securely, for example, in 1Password.
## Generate an SSH host key

View File

@ -8,6 +8,7 @@ module Banzai
# - Banzai::Filter::SanitizationFilter (Markdown)
# - Banzai::Filter::AsciiDocSanitizationFilter (AsciiDoc/Asciidoctor)
# - Banzai::Filter::BroadcastMessageSanitizationFilter (Markdown with styled links and line breaks)
# - Banzai::Filter::MinimumMarkdownSanitizationFilter (only inline elements)
#
# Extends HTML::Pipeline::SanitizationFilter with common rules.
class BaseSanitizationFilter < HTML::Pipeline::SanitizationFilter

View File

@ -33,6 +33,15 @@ module Banzai
unsafe: true
}.freeze
# Supports the bare minimum markdown. Usually used for single line
# titles.
MINIMUM_MARKDOWN = {
autolink: true,
hardbreaks: false,
strikethrough: true,
unsafe: false
}.freeze
def render(text)
::GLFMMarkdown.to_html(text, options: render_options)
end
@ -40,6 +49,7 @@ module Banzai
private
def render_options
return MINIMUM_MARKDOWN if minimum_markdown_enabled?
return OPTIONS unless sourcepos_disabled? || headers_disabled? || autolink_disabled? || raw_html_disabled?
OPTIONS.merge(
@ -62,6 +72,10 @@ module Banzai
def raw_html_disabled?
context[:disable_raw_html]
end
def minimum_markdown_enabled?
context[:minimum_markdown]
end
end
end
end

View File

@ -0,0 +1,39 @@
# frozen_string_literal: true
module Banzai
module Filter
# Sanitize a single line of text or HTML produced by Markdown.
class MinimumMarkdownSanitizationFilter < Banzai::Filter::BaseSanitizationFilter
prepend Concerns::TimeoutFilterHandler
include Gitlab::Utils::StrongMemoize
# These are the basic inline markdown features. We support autolinking, so
# allow limited protocols for `a`
ALLOWLIST = {
elements: %w[em strong code del a],
attributes: { 'a' => ['href'] },
remove_contents: ['script'],
protocols: { 'a' => { 'href' => %w[http https] } }
}.freeze
def call
Sanitize.clean_node!(doc, allowlist)
# The markdown filter always wraps it's output in a `<p>` tag.
# The sanitizer will turn it into a text node of space. So let's remove
# the leading and trailing spaces if it exists.
doc.children.first.remove if doc.children.first.blank?
doc.children.last.remove if doc.children.last.blank?
doc
end
# This completely overrides the BaseSanitizationFilter allowlist. We don't
# want to support math, spans, etc. Bare minimum markdown
def allowlist
ALLOWLIST
end
strong_memoize_attr :allowlist
end
end
end

View File

@ -0,0 +1,46 @@
# frozen_string_literal: true
module Banzai
module Pipeline
# Does the same transformation as SingleLinePipeline, but runs
# it through the MarkdownFilter first
class SingleLineMarkdownPipeline < SingleLinePipeline
def self.filters
@filters ||= FilterArray[
Filter::MarkdownFilter,
Filter::ConvertTextToDocFilter,
Filter::MinimumMarkdownSanitizationFilter,
Filter::SanitizeLinkFilter,
Filter::AssetProxyFilter,
Filter::EmojiFilter,
Filter::CustomEmojiFilter,
Filter::ExternalLinkFilter,
*reference_filters
]
end
# UserReferenceFilter is intentionally excluded to prevent generating
# a notification. This pipeline is mostly for titles.
def self.reference_filters
[
Filter::References::UserReferenceFilter,
Filter::References::IssueReferenceFilter,
Filter::References::WorkItemReferenceFilter,
Filter::References::ExternalIssueReferenceFilter,
Filter::References::MergeRequestReferenceFilter,
Filter::References::SnippetReferenceFilter,
Filter::References::CommitRangeReferenceFilter,
Filter::References::CommitReferenceFilter,
Filter::References::AlertReferenceFilter,
Filter::References::FeatureFlagReferenceFilter
]
end
def self.transform_context(context)
super.merge(minimum_markdown: true)
end
end
end
end
Banzai::Pipeline::SingleLinePipeline.prepend_mod_with('Banzai::Pipeline::SingleLineMarkdownPipeline')

View File

@ -2,11 +2,11 @@
module Banzai
module Pipeline
class SingleLinePipeline < GfmPipeline
class SingleLinePipeline < BasePipeline
def self.filters
@filters ||= FilterArray[
Filter::HtmlEntityFilter,
Filter::SanitizationFilter,
Filter::MinimumMarkdownSanitizationFilter,
Filter::SanitizeLinkFilter,
Filter::AssetProxyFilter,
Filter::EmojiFilter,
@ -34,10 +34,9 @@ module Banzai
def self.transform_context(context)
context = Filter::AssetProxyFilter.transform_context(context)
context[:only_path] = true unless context.key?(:only_path)
super(context).merge(
no_sourcepos: true
)
context
end
end
end

View File

@ -27,6 +27,18 @@ module Gitlab
.not_match("#{Gitlab::Database::Reindexing::ReindexConcurrently::TEMPORARY_INDEX_PATTERN}$")
end
scope :without_parent_partitioned_tables, -> do
partitioned_table = PostgresPartitionedTable.arel_table
index_table = arel_table
parent_tables_query = PostgresPartitionedTable
.where(partitioned_table[:schema].eq(index_table[:schema]))
.where(partitioned_table[:name].eq(index_table[:tablename]))
.select(1)
where('NOT EXISTS (?)', parent_tables_query)
end
scope :reindexing_leftovers, -> { match("#{Gitlab::Database::Reindexing::ReindexConcurrently::TEMPORARY_INDEX_PATTERN}$").order(:name) }
scope :not_match, ->(regex) { where("name !~ ?", regex) }

View File

@ -35,7 +35,11 @@ module Gitlab
end
def relations_that_need_cleaning_before_deadline
relation = candidates.not_recently_reindexed.where('ondisk_size_bytes >= ?', minimum_index_size)
relation = candidates
.not_recently_reindexed
.without_parent_partitioned_tables
.where('ondisk_size_bytes >= ?', minimum_index_size)
relation = relation.where.not(tablename: VERY_LARGE_TABLES) if too_late_for_very_large_table?
relation
end

View File

@ -56,7 +56,7 @@ module Gitlab
@user = User.find_by_username(username)
@registration_prefix = options[:registration_prefix] || DEFAULT_PREFIX
@runner_count = options[:runner_count] || DEFAULT_RUNNER_COUNT
@organization = nil
@organization_id = nil
@groups = {}
@projects = {}
end
@ -72,7 +72,7 @@ module Gitlab
runner_count: @runner_count
)
@organization = create_organization
@organization_id = ensure_organization_id
groups_and_projects = create_groups_and_projects
runner_ids = create_runners(groups_and_projects)
@ -113,23 +113,28 @@ module Gitlab
true
end
def create_organization
def ensure_organization_id
args = {
name: 'GitLab',
path: 'gitlab'
}
organization = ::Organizations::Organization.find_by_path(args[:path])
organization_id = ::Organizations::Organization.find_by_path(args[:path])&.id
return organization if organization
return organization_id if organization_id
logger.info(message: 'Creating organization', **args)
execute_service!(::Organizations::CreateService.new(current_user: @user, params: args), :organization)
if Feature.enabled?(:allow_organization_creation, @user)
logger.info(message: 'Creating organization', **args)
service = ::Organizations::CreateService.new(current_user: @user, params: args)
return execute_service!(service, :organization)&.id
end
::Organizations::Organization::DEFAULT_ORGANIZATION_ID
end
def create_groups_and_projects
root_group_1 = ensure_group(name: 'top-level group 1', organization_id: @organization.id)
root_group_2 = ensure_group(name: 'top-level group 2', organization_id: @organization.id)
root_group_1 = ensure_group(name: 'top-level group 1', organization_id: @organization_id)
root_group_2 = ensure_group(name: 'top-level group 2', organization_id: @organization_id)
group_1_1 = ensure_group(name: 'group 1.1', parent_id: root_group_1.id)
group_1_1_1 = ensure_group(name: 'group 1.1.1', parent_id: group_1_1.id)
group_1_1_2 = ensure_group(name: 'group 1.1.2', parent_id: group_1_1.id)
@ -142,12 +147,12 @@ module Gitlab
group_1_1_1: group_1_1_1,
group_1_1_2: group_1_1_2,
project_1_1_1_1: ensure_project(
name: 'project 1.1.1.1', namespace_id: group_1_1_1.id, organization_id: @organization.id),
name: 'project 1.1.1.1', namespace_id: group_1_1_1.id, organization_id: @organization_id),
project_1_1_2_1: ensure_project(
name: 'project 1.1.2.1', namespace_id: group_1_1_2.id, organization_id: @organization.id),
name: 'project 1.1.2.1', namespace_id: group_1_1_2.id, organization_id: @organization_id),
group_2_1: group_2_1,
project_2_1_1: ensure_project(
name: 'project 2.1.1', namespace_id: group_2_1.id, organization_id: @organization.id)
name: 'project 2.1.1', namespace_id: group_2_1.id, organization_id: @organization_id)
}
end

View File

@ -6490,6 +6490,9 @@ msgstr ""
msgid "AmazonQ|Create a merge request to incorporate Amazon Q suggestions"
msgstr ""
msgid "AmazonQ|Create an Amazon Q Developer profile in the %{linkStart}Amazon Q Developer console.%{linkEnd}"
msgstr ""
msgid "AmazonQ|Create an identity provider for this GitLab instance within AWS using the following values. %{helpStart}Learn more%{helpEnd}."
msgstr ""

View File

@ -206,7 +206,6 @@ module Trigger
class CNG < Base
TriggerRefBranchCreationFailed = Class.new(StandardError)
ASSETS_HASH = "cached-assets-hash.txt"
DEFAULT_DEBIAN_IMAGE = "debian:bookworm-slim"
DEFAULT_ALPINE_IMAGE = "alpine:3.20"
DEFAULT_SKIPPED_JOBS = %w[final-images-listing].freeze
@ -258,6 +257,14 @@ module Trigger
private
def assets_tag_variable
tag = ENV['GLCI_ASSETS_IMAGE_TAG']
return { 'GITLAB_ASSETS_TAG' => tag } unless tag.nil? || tag.empty?
logger.warn("No image tag found in GLCI_ASSETS_IMAGE_TAG environment variable, enabling asset compilation in CNG pipeline")
{ 'COMPILE_ASSETS' => 'true' }
end
# overridden base class methods
def downstream_project_path
ENV.fetch('CNG_PROJECT_PATH', 'gitlab-org/build/CNG-mirror')
@ -324,7 +331,8 @@ module Trigger
"SKIP_JOB_REGEX" => DEFAULT_SKIPPED_JOB_REGEX,
"DEBIAN_IMAGE" => DEFAULT_DEBIAN_IMAGE, # Make sure default values are always set to not end up as empty string
"ALPINE_IMAGE" => DEFAULT_ALPINE_IMAGE, # Make sure default values are always set to not end up as empty string
**default_build_vars
**default_build_vars,
**assets_tag_variable
}
end

View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
FactoryBot.define do
factory :postgres_partitioned_table, class: 'Gitlab::Database::PostgresPartitionedTable' do
identifier { "#{schema}.#{name}" }
sequence(:oid) { |n| n }
schema { 'public' }
name { '_test_partitioned_table' }
strategy { 'range' }
key_columns { ['timestamp'] }
end
end

View File

@ -6,6 +6,7 @@ import VueApollo from 'vue-apollo';
import MockAdapter from 'axios-mock-adapter';
import createMockApollo from 'helpers/mock_apollo_helper';
import waitForPromises from 'helpers/wait_for_promises';
import ModalCopyButton from '~/vue_shared/components/modal_copy_button.vue';
import { HTTP_STATUS_OK, HTTP_STATUS_UNPROCESSABLE_ENTITY } from '~/lib/utils/http_status';
import WorkItemCreateBranchMergeRequestModal from '~/work_items/components/work_item_development/work_item_create_branch_merge_request_modal.vue';
import getProjectRootRef from '~/work_items/graphql/get_project_root_ref.query.graphql';
@ -92,6 +93,7 @@ describe('CreateBranchMergeRequestModal', () => {
const findPrivateForksSelector = () => wrapper.findComponent(ProjectFormGroup);
const findSourceBranch = () => wrapper.find('[data-testid="source-name"]');
const findTargetBranch = () => wrapper.find('[data-testid="target-name"]');
const findCopyToClipboardButton = () => wrapper.findComponent(ModalCopyButton);
describe('when hosted at the root', () => {
beforeEach(() => {
@ -159,6 +161,20 @@ describe('CreateBranchMergeRequestModal', () => {
});
});
describe('Copy to clipboard', () => {
it('shows a button that copies the branch name to the clipboard', async () => {
findTargetBranch().vm.$emit('input', 'target');
await nextTick();
expect(findCopyToClipboardButton().exists()).toBe(true);
expect(findCopyToClipboardButton().props()).toMatchObject({
text: `target`,
title: 'Copy to clipboard',
});
});
});
it('shows a success toast message when branch is created', async () => {
createWrapper();
await waitForPromises();

View File

@ -47,4 +47,13 @@ RSpec.describe Banzai::Filter::MarkdownEngines::GlfmMarkdown, feature_category:
expect(engine.render('`code`')).to eq expected
end
it 'turns on minimal markdown options' do
engine = described_class.new({ minimum_markdown: true })
expected = <<~TEXT
<p><a href="http://example.com">http://example.com</a> <em>emphasis</em> $x + y$</p>
TEXT
expect(engine.render('http://example.com _emphasis_ $x + y$')).to eq expected
end
end

View File

@ -0,0 +1,58 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Banzai::Filter::MinimumMarkdownSanitizationFilter, feature_category: :markdown do
include FilterSpecHelper
it 'sanitizes tags that are not allowed' do
list = Banzai::Filter::SanitizationFilter::ALLOWLIST[:elements] -
Banzai::Filter::MinimumMarkdownSanitizationFilter::ALLOWLIST[:elements]
act = list.map { |tag| "<#{tag}>#{tag}</#{tag}>" }.join(' ')
exp = list.map { |tag| tag }.join(' ')
expect(filter(act).to_html.squeeze(' ')).to eq exp
end
it 'sanitizes tag attributes' do
act = %q(<a href="http://example.com/bar.html" onclick="bar">Text</a>)
exp = %q(<a href="http://example.com/bar.html">Text</a>)
expect(filter(act).to_html).to eq exp
end
it 'allows allowlisted HTML tags from the user' do
list = Banzai::Filter::MinimumMarkdownSanitizationFilter::ALLOWLIST[:elements]
act = list.map { |tag| "<#{tag}>#{tag}</#{tag}>" }.join(' ')
expect(filter(act).to_html.squeeze(' ')).to eq act
end
it 'sanitizes `class` attribute on any element' do
act = %q(<strong class="foo">Strong</strong>)
expect(filter(act).to_html).to eq %q(<strong>Strong</strong>)
end
it 'sanitizes `id` attribute on any element' do
act = %q(<em>Emphasis</em> <a href="http://foo" id="bar">foo bar</a>)
exp = %q(<em>Emphasis</em> <a href="http://foo">foo bar</a>)
expect(filter(act).to_html).to eq exp
end
it 'only allows http and https protocols' do
act = %q(<a href="http://foo">http</a> <a href="https://foo">https</a> <a href="mailto://foo">mailto</a>)
exp = %q(<a href="http://foo">http</a> <a href="https://foo">https</a> <a>mailto</a>)
expect(filter(act).to_html).to eq exp
end
it_behaves_like 'does not use pipeline timing check'
it_behaves_like 'a filter timeout' do
let(:text) { 'text' }
let(:expected_result) { described_class::COMPLEX_MARKDOWN_MESSAGE }
let(:expected_timeout) { described_class::SANITIZATION_RENDER_TIMEOUT }
end
end

View File

@ -0,0 +1,66 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Banzai::Pipeline::SingleLineMarkdownPipeline, feature_category: :markdown do
let_it_be(:user) { create(:user, :with_namespace) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:issue) { create(:issue, project: project) }
it_behaves_like 'sanitize pipeline'
it 'processes markdown and does not surround output with a paragraph tag' do
text = '_italic_ and `code`'
expect(to_html(text)).to eq('<em>italic</em> and <code>code</code>')
end
it 'removes additional block level tags pre, p, img, ol, ul, and li' do
text = <<~MARKDOWN
Hello world! ![](world.png)
- item one
- item two
1. number one
2. number two
```ruby
x = 1
```
MARKDOWN
expected = "Hello world! \n \n item one \n item two \n \n \n number one \n number two \n \n <code>x = 1\n</code>"
expect(to_html(text)).to eq(expected)
end
it 'handles emojis and autolinking' do
text = ':smile: using http://example.com'
result = to_html(text)
expect(result).to include('gl-emoji')
expect(result).to include('<a href="http://example.com"')
end
it 'recognizes references' do
text = "Issue #{issue.to_reference}, User #{user.to_reference}"
result = to_html(text)
expect(result).to include('data-reference-type="issue"')
expect(result).to include('data-reference-type="user"')
end
it 'does not recognize references in inline code' do
text = "Issue `#{issue.to_reference}`, User `#{user.to_reference}`"
result = to_html(text)
expect(result).not_to include('data-reference-type="issue"')
expect(result).not_to include('data-reference-type="user"')
end
def to_html(text)
described_class.to_html(text, project: project, pipeline: :single_line_markdown)
end
end

View File

@ -0,0 +1,44 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Banzai::Pipeline::SingleLinePipeline, feature_category: :markdown do
let_it_be(:user) { create(:user, :with_namespace) }
let_it_be(:group) { create(:group) }
let_it_be(:project) { create(:project, group: group) }
let_it_be(:issue) { create(:issue, project: project) }
it_behaves_like 'sanitize pipeline'
it 'does not process markdown' do
text = '_italic_'
expect(to_html(text)).to eq(text)
end
it 'escapes HTML' do
text = '<p>Hello<br>World</p>'
expect(to_html(text)).to eq('&lt;p&gt;Hello&lt;br&gt;World&lt;/p&gt;')
end
it 'handles emojis and autolinking' do
text = ':smile: using http://example.com'
result = to_html(text)
expect(result).to include('gl-emoji')
expect(result).to include('<a href="http://example.com"')
end
it 'recognizes references' do
text = "Issue #{issue.to_reference}, User #{user.to_reference}"
result = to_html(text)
expect(result).to include('data-reference-type="issue"')
expect(result).to include('data-reference-type="user"')
end
def to_html(text)
described_class.to_html(text, project: project, pipeline: :single_line)
end
end

View File

@ -88,6 +88,24 @@ RSpec.describe Gitlab::Database::PostgresIndex, feature_category: :database do
end
end
describe '.without_parent_partitioned_tables' do
subject(:postgres_indexes) { described_class.without_parent_partitioned_tables.map(&:name) }
it 'excludes indexes from parent partitioned tables' do
expect(postgres_indexes).not_to include('_test_partitioned_pkey')
end
it 'includes indexes from partition children' do
expect(postgres_indexes).to include('_test_partitioned_1_pkey')
end
it 'includes indexes from non-partitioned tables', :aggregate_failures do
expect(postgres_indexes).to include('foo_idx')
expect(postgres_indexes).to include('bar_key')
expect(postgres_indexes).to include('_test_gitlab_main_example_table_pkey')
end
end
describe '#bloat_size' do
subject { build(:postgres_index, bloat_estimate: bloat_estimate) }

View File

@ -102,4 +102,23 @@ RSpec.describe Gitlab::Database::Reindexing::IndexSelection, feature_category: :
it { expect(subject).not_to include(ci_builds.index) }
end
end
context 'with partitioned parent table' do
before do
swapout_view_for_table(:postgres_partitioned_tables, connection: connection)
create(:postgres_partitioned_table, name: '_test_partitioned_parent')
end
let!(:parent_index) do
create(
:postgres_index_bloat_estimate,
index: create(:postgres_index, tablename: '_test_partitioned_parent', ondisk_size_bytes: 100.gigabytes),
bloat_size_bytes: 40.gigabytes
)
end
it 'excludes indexes from parent partitioned tables' do
expect(subject).not_to include(parent_index)
end
end
end

View File

@ -103,5 +103,19 @@ RSpec.describe ::Gitlab::Seeders::Ci::Runner::RunnerFleetSeeder, feature_categor
expect { seed }.to raise_error(RuntimeError)
end
end
context 'when feature flag allow_organization_creation is disabled' do
let_it_be(:default_organization) { create(:organization, :default) }
before do
stub_feature_flags(allow_organization_creation: false)
end
it 'uses the default organization ID' do
expect(::Organizations::Organization).not_to receive(:default_organization)
expect { seed }.not_to raise_error
expect(Group.search(registration_prefix).pluck(:organization_id)).to all(eq(default_organization.id))
end
end
end
end

View File

@ -7,7 +7,7 @@ RSpec.describe Issuable, feature_category: :team_planning do
using RSpec::Parameterized::TableSyntax
let(:issuable_class) { Issue }
let(:issue) { create(:issue, title: 'An issue', description: 'A description') }
let(:issue) { create(:issue, title: 'An _issue_', description: 'A **description**') }
let(:user) { create(:user) }
describe "Associations" do
@ -1158,4 +1158,20 @@ RSpec.describe Issuable, feature_category: :team_planning do
it_behaves_like 'an exportable'
end
end
describe '#title_html' do
let(:expected_title) { 'An <em>issue</em>' }
subject { issue.title_html }
it { is_expected.to eq(expected_title) }
end
describe '#description_html' do
let(:expected_description) { '<p dir="auto">A <strong>description</strong></p>' }
subject { issue.description_html }
it { is_expected.to eq_no_sourcepos(expected_description) }
end
end

View File

@ -43,8 +43,6 @@ RSpec.describe API::Conan::V1::InstancePackages, feature_category: :package_regi
end
context 'with recipe endpoints' do
include_context 'for conan recipe endpoints'
let(:project_id) { 9999 }
let(:url_prefix) { "#{Settings.gitlab.base_url}/api/v4" }

View File

@ -55,8 +55,6 @@ RSpec.describe API::Conan::V1::ProjectPackages, feature_category: :package_regis
end
context 'with recipe endpoints' do
include_context 'for conan recipe endpoints'
let(:url_prefix) { "#{Settings.gitlab.base_url}/api/v4/projects/#{project_id}" }
let(:recipe_path) { package.conan_recipe_path }

View File

@ -212,8 +212,6 @@ RSpec.describe API::Conan::V2::ProjectPackages, feature_category: :package_regis
describe 'GET /api/v4/projects/:id/packages/conan/v2/conans/:package_name/:package_version/:package_username' \
'/:package_channel/latest' do
include_context 'for conan recipe endpoints'
let(:recipe_path) { package.conan_recipe_path }
let(:url_suffix) { "#{recipe_path}/latest" }
@ -250,8 +248,6 @@ RSpec.describe API::Conan::V2::ProjectPackages, feature_category: :package_regis
describe 'GET /api/v4/projects/:id/packages/conan/v2/conans/:package_name/:package_version/:package_username' \
'/:package_channel/revisions' do
include_context 'for conan recipe endpoints'
let(:recipe_path) { package.conan_recipe_path }
let(:url_suffix) { "#{recipe_path}/revisions" }
let_it_be(:revision1) { package.conan_recipe_revisions.first }

View File

@ -25,8 +25,7 @@ RSpec.describe Trigger, feature_category: :tooling do
'GITLAB_USER_NAME' => 'gitlab_user_name',
'GITLAB_USER_LOGIN' => 'gitlab_user_login',
'QA_IMAGE' => 'qa_image',
'DOCS_PROJECT_API_TOKEN' => nil,
'CNG_SKIP_REDUNDANT_JOBS' => "false"
'DOCS_PROJECT_API_TOKEN' => nil
}
end
@ -230,6 +229,11 @@ RSpec.describe Trigger, feature_category: :tooling do
end
describe Trigger::CNG do
before do
stub_env('CNG_SKIP_REDUNDANT_JOBS', 'false')
stub_env('GLCI_ASSETS_IMAGE_TAG', 'assets_tag')
end
describe '#variables' do
it 'does not include redundant variables' do
expect(subject.variables).not_to include('TRIGGER_SOURCE', 'TRIGGERED_USER')
@ -351,6 +355,25 @@ RSpec.describe Trigger, feature_category: :tooling do
end
end
describe "GLCI_ASSETS_IMAGE_TAG" do
context 'when GLCI_ASSETS_IMAGE_TAG is set' do
it 'sets GITLAB_ASSETS_TAG to GLCI_ASSETS_IMAGE_TAG value' do
expect(subject.variables['GITLAB_ASSETS_TAG']).to eq('assets_tag')
end
end
context 'when GLCI_ASSETS_IMAGE_TAG is not set' do
before do
stub_env('GLCI_ASSETS_IMAGE_TAG', '')
end
it 'sets COMPILE_ASSETS to true' do
expect(subject.variables['COMPILE_ASSETS']).to eq('true')
expect(subject.variables['GITLAB_ASSETS_TAG']).to be_nil
end
end
end
describe "GITLAB_TAG" do
context 'when CI_COMMIT_TAG is set' do
before do

View File

@ -20,12 +20,6 @@ RSpec.shared_context 'with conan api setup' do
let(:conan_package_reference) { package.conan_package_references.first.reference }
let(:job_token) { job.token }
let(:auth_token) { personal_access_token.token }
let(:headers) do
{ 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials('foo', auth_token) }
end
let(:jwt_secret) do
OpenSSL::HMAC.hexdigest(
OpenSSL::Digest.new('SHA256'),
@ -34,25 +28,15 @@ RSpec.shared_context 'with conan api setup' do
)
end
let(:jwt) { build_jwt(personal_access_token) }
let(:headers) { build_token_auth_header(jwt.encoded) }
let(:snowplow_gitlab_standard_context) do
{ user: user, project: project, namespace: project.namespace, property: 'i_package_conan_user' }
end
end
RSpec.shared_context 'for conan recipe endpoints' do
include PackagesManagerApiSpecHelpers
include HttpBasicAuthHelpers
let(:jwt) { build_jwt(personal_access_token) }
let(:headers) { build_token_auth_header(jwt.encoded) }
end
RSpec.shared_context 'for conan file download endpoints' do
include PackagesManagerApiSpecHelpers
include HttpBasicAuthHelpers
let(:jwt) { build_jwt(personal_access_token) }
let(:headers) { build_token_auth_header(jwt.encoded) }
let(:recipe_path) { package.conan_recipe_path }
let(:package_file) { package.package_files.find_by(file_name: 'conaninfo.txt') }
let(:recipe_file) { package.package_files.find_by!(file_name: 'conanfile.py') }
@ -61,13 +45,10 @@ RSpec.shared_context 'for conan file download endpoints' do
end
RSpec.shared_context 'for conan file upload endpoints' do
include PackagesManagerApiSpecHelpers
include WorkhorseHelpers
include HttpBasicAuthHelpers
include_context 'workhorse headers'
let(:jwt) { build_jwt(personal_access_token) }
let(:headers_with_token) { build_token_auth_header(jwt.encoded).merge(workhorse_headers) }
let(:recipe_path) { "#{recipe_path_name}/#{recipe_path_version}/#{recipe_path_username}/#{recipe_path_channel}" }
let(:recipe_path_name) { "#{package.name}_new" }

View File

@ -146,6 +146,11 @@ RSpec.shared_examples 'conan search endpoint with access to package registry for
end
RSpec.shared_examples 'conan authenticate endpoint' do
let(:auth_token) { personal_access_token.token }
let(:headers) do
{ 'HTTP_AUTHORIZATION' => ActionController::HttpAuthentication::Basic.encode_credentials('foo', auth_token) }
end
subject { get api(url), headers: headers }
it_behaves_like 'conan FIPS mode'