Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
ab621c63b7
commit
c799d8a4fb
|
|
@ -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}"
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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>
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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%));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -0,0 +1 @@
|
|||
26e359f933851e7383e30437fa9f19759a284cdde0c5e13997953fdecea1ec96
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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. |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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')
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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) }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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 ""
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
@ -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! 
|
||||
|
||||
- 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
|
||||
|
|
@ -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('<p>Hello<br>World</p>')
|
||||
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
|
||||
|
|
@ -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) }
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
||||
|
|
|
|||
|
|
@ -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 }
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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" }
|
||||
|
|
|
|||
|
|
@ -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'
|
||||
|
|
|
|||
Loading…
Reference in New Issue