Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
68d3938909
commit
7eeb48577d
|
|
@ -200,6 +200,20 @@ overrides:
|
|||
no-unsanitized/method: off
|
||||
no-unsanitized/property: off
|
||||
local-rules/require-valid-help-page-path: off
|
||||
no-restricted-imports:
|
||||
- error
|
||||
- paths:
|
||||
- name: mousetrap
|
||||
message: 'Import { Mousetrap } from ~/lib/mousetrap instead.'
|
||||
- name: vuex
|
||||
message: 'See our documentation on "Migrating from VueX" for tips on how to avoid adding new VueX stores.'
|
||||
- name: '@sentry/browser'
|
||||
message: Use "import * as Sentry from '~/sentry/sentry_browser_wrapper';" instead
|
||||
- name: ~/locale
|
||||
importNames:
|
||||
- __
|
||||
- s__
|
||||
message: 'Do not externalize strings in specs: https://docs.gitlab.com/ee/development/i18n/externalization.html#test-files-jest'
|
||||
- files:
|
||||
- 'config/**/*'
|
||||
- 'scripts/**/*'
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ workflow:
|
|||
|
||||
variables:
|
||||
PG_VERSION: "14"
|
||||
DEFAULT_CI_IMAGE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}-node-${NODE_VERSION}-postgresql-${PG_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-2.36-lfs-2.9-chrome-${CHROME_VERSION}-yarn-1.22-graphicsmagick-1.3.36"
|
||||
DEFAULT_CI_IMAGE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}-node-${NODE_VERSION}-postgresql-${PG_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-${GIT_VERSION}-lfs-${LFS_VERSION}-chrome-${CHROME_VERSION}-yarn-${YARN_VERSION}-graphicsmagick-${GRAPHICSMAGICK_VERSION}"
|
||||
DEFAULT_JOB_TAG: "gitlab-org"
|
||||
DEFAULT_RSPEC_PREDICTIVE_JOB_TAGS: "${DEFAULT_JOB_TAG}" # Separated by commas, overridden in JiHu
|
||||
# We set $GITLAB_DEPENDENCY_PROXY to another variable (since it's set at the group level and has higher precedence than .gitlab-ci.yml)
|
||||
|
|
@ -219,7 +219,7 @@ variables:
|
|||
DOCS_REVIEW_APPS_DOMAIN: "docs.gitlab-review.app"
|
||||
DOCS_GITLAB_REPO_SUFFIX: "ee"
|
||||
|
||||
REVIEW_APPS_IMAGE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}:gcloud-383-kubectl-1.28-helm-3.9"
|
||||
REVIEW_APPS_IMAGE: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}:gcloud-${GCLOUD_VERSION}-kubectl-${KUBECTL_VERSION}-helm-${HELM_VERSION}"
|
||||
REVIEW_APPS_DOMAIN: "gitlab-review.app"
|
||||
REVIEW_APPS_GCP_PROJECT: "gitlab-review-apps"
|
||||
REVIEW_APPS_GCP_REGION: "us-central1"
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@
|
|||
- .default-retry
|
||||
- .default-before_script
|
||||
- .assets-compile-cache
|
||||
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}-node-${NODE_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-2.33-lfs-2.9-yarn-1.22-graphicsmagick-1.3.36
|
||||
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}-node-${NODE_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-${GIT_VERSION}-lfs-${LFS_VERSION}-yarn-${YARN_VERSION}-graphicsmagick-${GRAPHICSMAGICK_VERSION}
|
||||
variables:
|
||||
SETUP_DB: "false"
|
||||
WEBPACK_VENDOR_DLL: "true"
|
||||
|
|
|
|||
|
|
@ -94,6 +94,7 @@ sync-as-if-jh-branch:
|
|||
- RUST_VERSION
|
||||
- PG_VERSION
|
||||
- RUBYGEMS_VERSION
|
||||
- GIT_VERSION
|
||||
- CHROME_VERSION
|
||||
- NODE_ENV
|
||||
variables:
|
||||
|
|
|
|||
|
|
@ -44,13 +44,19 @@
|
|||
QA_EXPORT_TEST_METRICS: "true" # Export test metrics directly to influxdb by default
|
||||
inherit:
|
||||
variables:
|
||||
- BUILD_OS
|
||||
- CHROME_VERSION
|
||||
- DOCKER_VERSION
|
||||
- GCLOUD_VERSION
|
||||
- GIT_VERSION
|
||||
- GO_VERSION
|
||||
- HELM_VERSION
|
||||
- KUBECTL_VERSION
|
||||
- LFS_VERSION
|
||||
- OS_VERSION
|
||||
- RUBY_VERSION_DEFAULT
|
||||
- RUBY_VERSION_NEXT
|
||||
- RUBY_VERSION
|
||||
- DOCKER_VERSION
|
||||
- BUILD_OS
|
||||
- OS_VERSION
|
||||
- RUBYGEMS_VERSION
|
||||
- REGISTRY_GROUP
|
||||
- REGISTRY_HOST
|
||||
- OMNIBUS_GITLAB_CACHE_UPDATE
|
||||
|
|
|
|||
|
|
@ -53,7 +53,7 @@ setup-test-env:
|
|||
setup-test-env-fips:
|
||||
extends:
|
||||
- setup-test-env
|
||||
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-2.36-exiftool-12.60
|
||||
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-${GIT_VERSION}-exiftool-${EXIFTOOL_VERSION}
|
||||
variables:
|
||||
BUILD_OS: "ubi"
|
||||
OS_VERSION: ${UBI_VERSION}
|
||||
|
|
|
|||
|
|
@ -86,19 +86,28 @@ start-review-app-pipeline:
|
|||
# https://gitlab.com/gitlab-org/gitlab/-/issues/387183
|
||||
inherit:
|
||||
variables:
|
||||
- REGISTRY_GROUP
|
||||
- REGISTRY_HOST
|
||||
- REVIEW_APPS_DOMAIN
|
||||
- REVIEW_APPS_GCP_PROJECT
|
||||
- REVIEW_APPS_GCP_REGION
|
||||
- REVIEW_APPS_IMAGE
|
||||
- BUILD_OS
|
||||
- CHROME_VERSION
|
||||
- DOCKER_VERSION
|
||||
- EXIFTOOL_VERSION
|
||||
- GCLOUD_VERSION
|
||||
- GIT_VERSION
|
||||
- GO_VERSION
|
||||
- GRAPHICSMAGICK_VERSION
|
||||
- HELM_VERSION
|
||||
- KIND_VERSION
|
||||
- KUBECTL_VERSION
|
||||
- LFS_VERSION
|
||||
- NODE_VERSION
|
||||
- OS_VERSION
|
||||
- RUBY_VERSION_DEFAULT
|
||||
- RUBY_VERSION_NEXT
|
||||
- RUBY_VERSION
|
||||
- BUILD_OS
|
||||
- OS_VERSION
|
||||
- DOCKER_VERSION
|
||||
- CHROME_VERSION
|
||||
- RUBYGEMS_VERSION
|
||||
- RUST_VERSION
|
||||
- UBI_VERSION
|
||||
- YARN_VERSION
|
||||
- REGISTRY_GROUP
|
||||
- REGISTRY_HOST
|
||||
# These variables are set in the pipeline schedules.
|
||||
# They need to be explicitly passed on to the child pipeline.
|
||||
# https://docs.gitlab.com/ee/ci/pipelines/multi_project_pipelines.html#pass-cicd-variables-to-a-downstream-pipeline-by-using-the-variables-keyword
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ workflow:
|
|||
- when: always
|
||||
|
||||
.cng-test:
|
||||
image: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}:git-2.36-lfs-2.9-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-kubectl-1.23-helm-3.14-kind-0.20"
|
||||
image: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}:git-${GIT_VERSION}-lfs-${LFS_VERSION}-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-kubectl-${KUBECTL_VERSION}-helm-${HELM_VERSION}-kind-${KIND_VERSION}"
|
||||
stage: test
|
||||
extends:
|
||||
- .qa-cache
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ include:
|
|||
- mv $CI_BUILDS_DIR/*.log $CI_PROJECT_DIR/
|
||||
|
||||
.gdk-qa-base:
|
||||
image: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}:git-2.36-lfs-2.9-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-gcloud-383-kubectl-1.23"
|
||||
image: "${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}:git-${GIT_VERSION}-lfs-${LFS_VERSION}-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-gcloud-${GCLOUD_VERSION}-kubectl-${KUBECTL_VERSION}-helm-${HELM_VERSION}"
|
||||
extends:
|
||||
- .qa-cache
|
||||
- .docker-in-docker
|
||||
|
|
|
|||
|
|
@ -1,12 +1,21 @@
|
|||
variables:
|
||||
BUILD_OS: "debian"
|
||||
OS_VERSION: "bookworm"
|
||||
UBI_VERSION: "8.6"
|
||||
CHROME_VERSION: "123"
|
||||
DOCKER_VERSION: "24.0.5"
|
||||
RUBYGEMS_VERSION: "3.4"
|
||||
EXIFTOOL_VERSION: "12.60"
|
||||
GCLOUD_VERSION: "413"
|
||||
GIT_VERSION: "2.45"
|
||||
GO_VERSION: "1.22"
|
||||
GRAPHICSMAGICK_VERSION: "1.3.36"
|
||||
HELM_VERSION: "3.14"
|
||||
KIND_VERSION: "0.20"
|
||||
KUBECTL_VERSION: "1.28"
|
||||
LFS_VERSION: "2.9"
|
||||
NODE_VERSION: "20.12"
|
||||
RUST_VERSION: "1.73"
|
||||
OS_VERSION: "bookworm"
|
||||
RUBY_VERSION_DEFAULT: "3.1.5"
|
||||
RUBY_VERSION_NEXT: "3.2.4"
|
||||
RUBYGEMS_VERSION: "3.4"
|
||||
RUST_VERSION: "1.73"
|
||||
UBI_VERSION: "8.6"
|
||||
YARN_VERSION: "1.22"
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ workhorse:verify:
|
|||
extends:
|
||||
- .workhorse:rules:workhorse
|
||||
- .gitaly-with-transactions
|
||||
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-2.36-exiftool-12.60
|
||||
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-${GIT_VERSION}-exiftool-${EXIFTOOL_VERSION}
|
||||
services:
|
||||
- name: redis:${REDIS_VERSION}-alpine
|
||||
variables:
|
||||
|
|
@ -68,7 +68,7 @@ workhorse:test fips:
|
|||
matrix:
|
||||
- GO_VERSION: ["1.21", "1.22"]
|
||||
REDIS_VERSION: ["7.0", "6.2"]
|
||||
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-2.36-exiftool-12.60
|
||||
image: ${REGISTRY_HOST}/${REGISTRY_GROUP}/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}-golang-${GO_VERSION}-rust-${RUST_VERSION}:rubygems-${RUBYGEMS_VERSION}-git-${GIT_VERSION}-exiftool-${EXIFTOOL_VERSION}
|
||||
variables:
|
||||
FIPS_MODE: 1
|
||||
BUILD_OS: "ubi"
|
||||
|
|
|
|||
|
|
@ -248,8 +248,8 @@
|
|||
{"name":"google-cloud-artifact_registry-v1","version":"0.11.0","platform":"ruby","checksum":"ba80d2dce9767e663931ded7929b7f8bf5983a6e2ea68078e27e7ca9a940783e"},
|
||||
{"name":"google-cloud-common","version":"1.1.0","platform":"ruby","checksum":"738db08fd144b4fe37b4578ffd63308b64a86fd59f6979d240048f917a6fb5fb"},
|
||||
{"name":"google-cloud-compute-v1","version":"2.6.0","platform":"ruby","checksum":"b96059b33ffc2f25644d20161a0c1aa1331197073c2e44786b18f8b670f1141e"},
|
||||
{"name":"google-cloud-core","version":"1.6.0","platform":"ruby","checksum":"ea1744cd5a3085d3072de3fab9106afc769cd198609ebb5c6eeb5f13da46b72a"},
|
||||
{"name":"google-cloud-env","version":"1.6.0","platform":"ruby","checksum":"6179acb946975892c7908748df5722a4ebadfc8cf5bb7b0d8d933ca67183fa15"},
|
||||
{"name":"google-cloud-core","version":"1.7.0","platform":"ruby","checksum":"748028a48530ea5bce159722eb7a02cd0562f1c52f0569e9ed69da3cba6b4f35"},
|
||||
{"name":"google-cloud-env","version":"2.1.1","platform":"ruby","checksum":"cf4bb8c7d517ee1ea692baedf06e0b56ce68007549d8d5a66481aa9f97f46999"},
|
||||
{"name":"google-cloud-errors","version":"1.3.0","platform":"ruby","checksum":"450b681e24c089a20721a01acc4408bb4a7b0df28c175aaab488da917480d64b"},
|
||||
{"name":"google-cloud-location","version":"0.6.0","platform":"ruby","checksum":"386c99ca156e5cac413731c055d7d9c55629860129ad7658a2bf39ea5004d2d0"},
|
||||
{"name":"google-cloud-profiler-v2","version":"0.4.0","platform":"ruby","checksum":"53fc2ab175d08f54233c644310d47798feac996220916815c4fb44c937b5d3e3"},
|
||||
|
|
@ -280,15 +280,15 @@
|
|||
{"name":"graphql","version":"2.3.5","platform":"ruby","checksum":"9c367835f86541660d24c3d81632267ecee553d304577aaee070f8ac05860af1"},
|
||||
{"name":"graphql-client","version":"0.23.0","platform":"ruby","checksum":"f238b8e451676baad06bd15f95396e018192243dcf12c4e6d13fb41d9a2babc1"},
|
||||
{"name":"graphql-docs","version":"5.0.0","platform":"ruby","checksum":"76baca6e5a803a4b6a9fbbbfdbf16742b7c4c546c8592b6e1a7aa4e79e562d04"},
|
||||
{"name":"grpc","version":"1.65.2","platform":"aarch64-linux","checksum":"a541d5aeb721ac5e732284ca8b6b955b2e2e5135c3c23134b926a569eca68933"},
|
||||
{"name":"grpc","version":"1.65.2","platform":"arm64-darwin","checksum":"1a7e762ae1b59c363f26dfbbd857a87bf8f806744438a1a85d828e92d57ba436"},
|
||||
{"name":"grpc","version":"1.65.2","platform":"ruby","checksum":"9d696e4e742eb1a7f3b3b7a6b3ee1796e4a6a2b009513b5f048df50e823622cc"},
|
||||
{"name":"grpc","version":"1.65.2","platform":"x64-mingw-ucrt","checksum":"b3341bfa6050b1e1790fcfa5560bc9b0d82ffe36d7bacfccb5c621401424198d"},
|
||||
{"name":"grpc","version":"1.65.2","platform":"x64-mingw32","checksum":"ea5162774967da44606552d3ca0c8efb3769c6a7b094e0764c38edca5ecab3e5"},
|
||||
{"name":"grpc","version":"1.65.2","platform":"x86-linux","checksum":"d7566459acb8964aff730f3c662e31122fca148befd76598fa11ea80efe8a892"},
|
||||
{"name":"grpc","version":"1.65.2","platform":"x86-mingw32","checksum":"6c102550453269f1de35cedc001aee1315bfec7af862008a8232c3262dcf130d"},
|
||||
{"name":"grpc","version":"1.65.2","platform":"x86_64-darwin","checksum":"4693e166dc84270f16e6b71d8f758cbbd367070f1d980d590d97e8b4b9b8d6ff"},
|
||||
{"name":"grpc","version":"1.65.2","platform":"x86_64-linux","checksum":"229bd96065637e867a2c13a1c5edb34ebdd14d2250428f03df718fd7a541edb5"},
|
||||
{"name":"grpc","version":"1.63.0","platform":"aarch64-linux","checksum":"dc75c5fd570b819470781d9512105dddfdd11d984f38b8e60bb946f92d1f79ee"},
|
||||
{"name":"grpc","version":"1.63.0","platform":"arm64-darwin","checksum":"91b93a354508a9d1772f095554f2e4c04358c2b32d7a670e3705b7fc4695c996"},
|
||||
{"name":"grpc","version":"1.63.0","platform":"ruby","checksum":"5f4383c4ee2886e92c31b90422261b7527f26e3baa585d877e9804e715983686"},
|
||||
{"name":"grpc","version":"1.63.0","platform":"x64-mingw-ucrt","checksum":"bbca63f19b45cca5a485f5c5eb363a8684d23a6d0c3421bde5e72e6227291488"},
|
||||
{"name":"grpc","version":"1.63.0","platform":"x64-mingw32","checksum":"fb6251f497c8327eda92c4af293ec07fcaec4ffaa2514d3942a7c31406bfaf5b"},
|
||||
{"name":"grpc","version":"1.63.0","platform":"x86-linux","checksum":"152140fa2c28e384d3c1ded454a66d5e22fb2ff1d2920c2ef2530b2d707de6fd"},
|
||||
{"name":"grpc","version":"1.63.0","platform":"x86-mingw32","checksum":"eed13225b08e705421fef9d986de6c2310ec692df1d80f7a4d407de7c1f98525"},
|
||||
{"name":"grpc","version":"1.63.0","platform":"x86_64-darwin","checksum":"a814414ff178e89ee3ad0cc2a826ce1ca96c68063effb81affe3e5ceff7b44cc"},
|
||||
{"name":"grpc","version":"1.63.0","platform":"x86_64-linux","checksum":"41a90a597f44959c8dbb94619db2b0c0939a768569a5dfad41fffa227eb1287d"},
|
||||
{"name":"grpc-google-iam-v1","version":"1.5.0","platform":"ruby","checksum":"cea356d150dac69751f6a4c71f1571c8022c69d9f4ce9c18139200932c19374e"},
|
||||
{"name":"gssapi","version":"1.3.1","platform":"ruby","checksum":"c51cf30842ee39bd93ce7fc33e20405ff8a04cda9dec6092071b61258284aee1"},
|
||||
{"name":"guard","version":"2.16.2","platform":"ruby","checksum":"71ba7abaddecc8be91ab77bbaf78f767246603652ebbc7b976fda497ebdc8fbb"},
|
||||
|
|
|
|||
12
Gemfile.lock
12
Gemfile.lock
|
|
@ -822,11 +822,11 @@ GEM
|
|||
gapic-common (>= 0.20.0, < 2.a)
|
||||
google-cloud-common (~> 1.0)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-core (1.6.0)
|
||||
google-cloud-env (~> 1.0)
|
||||
google-cloud-core (1.7.0)
|
||||
google-cloud-env (>= 1.0, < 3.a)
|
||||
google-cloud-errors (~> 1.0)
|
||||
google-cloud-env (1.6.0)
|
||||
faraday (>= 0.17.3, < 3.0)
|
||||
google-cloud-env (2.1.1)
|
||||
faraday (>= 1.0, < 3.a)
|
||||
google-cloud-errors (1.3.0)
|
||||
google-cloud-location (0.6.0)
|
||||
gapic-common (>= 0.20.0, < 2.a)
|
||||
|
|
@ -900,8 +900,8 @@ GEM
|
|||
graphql (~> 2.0)
|
||||
html-pipeline (~> 2.14, >= 2.14.3)
|
||||
sass-embedded (~> 1.58)
|
||||
grpc (1.65.2)
|
||||
google-protobuf (>= 3.25, < 5.0)
|
||||
grpc (1.63.0)
|
||||
google-protobuf (~> 3.25)
|
||||
googleapis-common-protos-types (~> 1.0)
|
||||
grpc-google-iam-v1 (1.5.0)
|
||||
google-protobuf (~> 3.18)
|
||||
|
|
|
|||
|
|
@ -16,8 +16,10 @@ import HorizontalRule from './horizontal_rule';
|
|||
import HTMLNodes from './html_nodes';
|
||||
import Image from './image';
|
||||
import Italic from './italic';
|
||||
import InlineDiff from './inline_diff';
|
||||
import Link from './link';
|
||||
import ListItem from './list_item';
|
||||
import MathInline from './math_inline';
|
||||
import OrderedList from './ordered_list';
|
||||
import Paragraph from './paragraph';
|
||||
import ReferenceDefinition from './reference_definition';
|
||||
|
|
@ -55,8 +57,10 @@ export default Extension.create({
|
|||
HorizontalRule.name,
|
||||
Image.name,
|
||||
Italic.name,
|
||||
InlineDiff.name,
|
||||
Link.name,
|
||||
ListItem.name,
|
||||
MathInline.name,
|
||||
OrderedList.name,
|
||||
Paragraph.name,
|
||||
ReferenceDefinition.name,
|
||||
|
|
|
|||
|
|
@ -120,7 +120,17 @@ const createChangeTracker = (doc, pristineDoc) => {
|
|||
if (node.attrs.sourceMapKey) {
|
||||
pristineSourceMarkdownMap.set(`${node.attrs.sourceMapKey}${node.type.name}`, node);
|
||||
}
|
||||
|
||||
node.marks?.forEach((mark) => {
|
||||
if (mark.attrs.sourceMapKey) {
|
||||
pristineSourceMarkdownMap.set(`${mark.attrs.sourceMapKey}${mark.type.name}`, {
|
||||
mark,
|
||||
node,
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
doc.descendants((node) => {
|
||||
const pristineNode = pristineSourceMarkdownMap.get(
|
||||
`${node.attrs.sourceMapKey}${node.type.name}`,
|
||||
|
|
@ -129,6 +139,15 @@ const createChangeTracker = (doc, pristineDoc) => {
|
|||
if (pristineNode) {
|
||||
changeTracker.set(node, node.eq(pristineNode));
|
||||
}
|
||||
|
||||
node.marks?.forEach((mark) => {
|
||||
const { node: pristineNodeForMark, mark: pristineMark } =
|
||||
pristineSourceMarkdownMap.get(`${mark.attrs.sourceMapKey}${mark.type.name}`) || {};
|
||||
|
||||
if (pristineMark) {
|
||||
changeTracker.set(mark, mark.eq(pristineMark) && node.eq(pristineNodeForMark));
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -138,6 +138,49 @@ export function preserveUnchanged(configOrRender) {
|
|||
};
|
||||
}
|
||||
|
||||
export function preserveUnchangedMark({ open, close, ...restConfig }) {
|
||||
// use a buffer to replace the content of the serialized mark with the sourceMarkdown
|
||||
// when the mark is unchanged
|
||||
let bufferStartPos = -1;
|
||||
|
||||
function startBuffer(state) {
|
||||
bufferStartPos = state.out.length;
|
||||
}
|
||||
|
||||
function bufferStarted() {
|
||||
return bufferStartPos !== -1;
|
||||
}
|
||||
|
||||
function endBuffer(state, replace) {
|
||||
state.out = state.out.substring(0, bufferStartPos) + replace;
|
||||
bufferStartPos = -1;
|
||||
}
|
||||
|
||||
return {
|
||||
...restConfig,
|
||||
open: (state, mark, parent, index) => {
|
||||
const same = state.options.changeTracker.get(mark);
|
||||
|
||||
if (same) {
|
||||
startBuffer(state);
|
||||
return '';
|
||||
}
|
||||
|
||||
return open(state, mark, parent, index);
|
||||
},
|
||||
close: (state, mark, parent, index) => {
|
||||
const { sourceMarkdown } = mark.attrs;
|
||||
|
||||
if (bufferStarted()) {
|
||||
endBuffer(state, sourceMarkdown);
|
||||
return '';
|
||||
}
|
||||
|
||||
return close(state, mark, parent, index);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
export const findChildWithMark = (mark, parent) => {
|
||||
let child;
|
||||
let offset;
|
||||
|
|
|
|||
|
|
@ -1,28 +1,20 @@
|
|||
import { openTag, closeTag } from '../serialization_helpers';
|
||||
import { openTag, closeTag, preserveUnchangedMark } from '../serialization_helpers';
|
||||
|
||||
const generateBoldTags = (wrapTagName = openTag) => {
|
||||
const generateBoldTag = (wrapTagName = openTag) => {
|
||||
return (_, mark) => {
|
||||
const type = /^(\*\*|__|<strong|<b).*/.exec(mark.attrs.sourceMarkdown)?.[1];
|
||||
const type = /^(\*\*|__).*/.exec(mark.attrs.sourceMarkdown)?.[1];
|
||||
if (type === '**' || type === '__') return type;
|
||||
if (mark.attrs.sourceTagName) return wrapTagName(mark.attrs.sourceTagName);
|
||||
|
||||
switch (type) {
|
||||
case '**':
|
||||
case '__':
|
||||
return type;
|
||||
// eslint-disable-next-line @gitlab/require-i18n-strings
|
||||
case '<strong':
|
||||
case '<b':
|
||||
return wrapTagName(type.substring(1));
|
||||
default:
|
||||
return '**';
|
||||
}
|
||||
return '**';
|
||||
};
|
||||
};
|
||||
|
||||
const bold = {
|
||||
open: generateBoldTags(),
|
||||
close: generateBoldTags(closeTag),
|
||||
const bold = preserveUnchangedMark({
|
||||
open: generateBoldTag(),
|
||||
close: generateBoldTag(closeTag),
|
||||
mixable: true,
|
||||
expelEnclosingWhitespace: true,
|
||||
};
|
||||
});
|
||||
|
||||
export default bold;
|
||||
|
|
|
|||
|
|
@ -4,11 +4,8 @@ const generateCodeTag = (wrapTagName = openTag) => {
|
|||
const isOpen = wrapTagName === openTag;
|
||||
|
||||
return (_, mark, parent) => {
|
||||
const type = /^(`|<code).*/.exec(mark.attrs.sourceMarkdown)?.[1];
|
||||
|
||||
if (type === '<code') {
|
||||
return wrapTagName(type.substring(1));
|
||||
}
|
||||
const { sourceTagName, sourceMarkdown } = mark.attrs;
|
||||
if (sourceTagName && !sourceMarkdown) return wrapTagName(mark.attrs.sourceTagName);
|
||||
|
||||
const childText = getMarkText(mark, parent);
|
||||
if (childText.includes('`')) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,6 @@
|
|||
const inlineDiff = {
|
||||
import { preserveUnchangedMark } from '../serialization_helpers';
|
||||
|
||||
const inlineDiff = preserveUnchangedMark({
|
||||
mixable: true,
|
||||
open(_, mark) {
|
||||
return mark.attrs.type === 'addition' ? '{+' : '{-';
|
||||
|
|
@ -6,6 +8,6 @@ const inlineDiff = {
|
|||
close(_, mark) {
|
||||
return mark.attrs.type === 'addition' ? '+}' : '-}';
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default inlineDiff;
|
||||
|
|
|
|||
|
|
@ -1,28 +1,21 @@
|
|||
import { openTag, closeTag } from '../serialization_helpers';
|
||||
import { openTag, closeTag, preserveUnchangedMark } from '../serialization_helpers';
|
||||
|
||||
const generateItalicTag = (wrapTagName = openTag) => {
|
||||
return (_, mark) => {
|
||||
const type = /^(\*|_|<em|<i).*/.exec(mark.attrs.sourceMarkdown)?.[1];
|
||||
const type = /^(\*|_).*/.exec(mark.attrs.sourceMarkdown)?.[1];
|
||||
if (type === '*' || type === '_') return type;
|
||||
|
||||
switch (type) {
|
||||
case '*':
|
||||
case '_':
|
||||
return type;
|
||||
// eslint-disable-next-line @gitlab/require-i18n-strings
|
||||
case '<em':
|
||||
case '<i':
|
||||
return wrapTagName(type.substring(1));
|
||||
default:
|
||||
return '_';
|
||||
}
|
||||
if (mark.attrs.sourceTagName) return wrapTagName(mark.attrs.sourceTagName);
|
||||
|
||||
return '_';
|
||||
};
|
||||
};
|
||||
|
||||
const italic = {
|
||||
const italic = preserveUnchangedMark({
|
||||
open: generateItalicTag(),
|
||||
close: generateItalicTag(closeTag),
|
||||
mixable: true,
|
||||
expelEnclosingWhitespace: true,
|
||||
};
|
||||
});
|
||||
|
||||
export default italic;
|
||||
|
|
|
|||
|
|
@ -1,8 +1,11 @@
|
|||
import { removeLastSlashInUrlPath, removeUrlProtocol } from '~/lib/utils/url_utility';
|
||||
import { findChildWithMark, openTag, closeTag, getMarkText } from '../serialization_helpers';
|
||||
|
||||
const LINK_HTML = 'linkHtml';
|
||||
const LINK_MARKDOWN = 'linkMarkdown';
|
||||
import {
|
||||
findChildWithMark,
|
||||
openTag,
|
||||
closeTag,
|
||||
getMarkText,
|
||||
preserveUnchangedMark,
|
||||
} from '../serialization_helpers';
|
||||
|
||||
/**
|
||||
* Validates that the provided URL is a valid GFM autolink
|
||||
|
|
@ -63,41 +66,28 @@ function getLinkHref(mark, useCanonicalSrc = true) {
|
|||
return href || '';
|
||||
}
|
||||
|
||||
const linkType = (sourceMarkdown) => {
|
||||
const expression = /^(\[|<a).*/.exec(sourceMarkdown)?.[1];
|
||||
|
||||
if (!expression || expression === '[') {
|
||||
return LINK_MARKDOWN;
|
||||
}
|
||||
|
||||
return LINK_HTML;
|
||||
};
|
||||
|
||||
const link = {
|
||||
const link = preserveUnchangedMark({
|
||||
open(state, mark, parent) {
|
||||
if (isAutoLink(mark, parent)) {
|
||||
return isBracketAutoLink(mark.attrs.sourceMarkdown) ? '<' : '';
|
||||
}
|
||||
|
||||
const { href, title, sourceMarkdown, isGollumLink } = mark.attrs;
|
||||
const { href, title, isGollumLink, sourceTagName, sourceMarkdown } = mark.attrs;
|
||||
|
||||
// eslint-disable-next-line @gitlab/require-i18n-strings
|
||||
if (href.startsWith('data:') || href.startsWith('blob:')) return '';
|
||||
|
||||
if (linkType(sourceMarkdown) === LINK_MARKDOWN) {
|
||||
if (isGollumLink) return '[[';
|
||||
return '[';
|
||||
}
|
||||
|
||||
const attrs = {
|
||||
href: state.esc(getLinkHref(mark, state.options.useCanonicalSrc)),
|
||||
};
|
||||
|
||||
if (title) {
|
||||
attrs.title = title;
|
||||
attrs.title = state.esc(title);
|
||||
}
|
||||
|
||||
return openTag('a', attrs);
|
||||
if (sourceTagName && !sourceMarkdown) return openTag(sourceTagName, attrs);
|
||||
if (isGollumLink) return '[[';
|
||||
return '[';
|
||||
},
|
||||
close(state, mark, parent) {
|
||||
if (isAutoLink(mark, parent)) {
|
||||
|
|
@ -107,6 +97,7 @@ const link = {
|
|||
const {
|
||||
href = '',
|
||||
title,
|
||||
sourceTagName,
|
||||
sourceMarkdown,
|
||||
isReference,
|
||||
isGollumLink,
|
||||
|
|
@ -116,12 +107,12 @@ const link = {
|
|||
// eslint-disable-next-line @gitlab/require-i18n-strings
|
||||
if (href.startsWith('data:') || href.startsWith('blob:')) return '';
|
||||
|
||||
if (isReference) {
|
||||
return `][${state.esc(getLinkHref(mark, state.options.useCanonicalSrc))}]`;
|
||||
if (sourceTagName && !sourceMarkdown) {
|
||||
return closeTag(sourceTagName);
|
||||
}
|
||||
|
||||
if (linkType(sourceMarkdown) === LINK_HTML) {
|
||||
return closeTag('a');
|
||||
if (isReference) {
|
||||
return `][${state.esc(getLinkHref(mark, state.options.useCanonicalSrc))}]`;
|
||||
}
|
||||
|
||||
if (isGollumLink) {
|
||||
|
|
@ -139,6 +130,6 @@ const link = {
|
|||
title ? ` ${state.quote(title)}` : ''
|
||||
})`;
|
||||
},
|
||||
};
|
||||
});
|
||||
|
||||
export default link;
|
||||
|
|
|
|||
|
|
@ -1,29 +1,20 @@
|
|||
import { openTag, closeTag } from '../serialization_helpers';
|
||||
import { openTag, closeTag, preserveUnchangedMark } from '../serialization_helpers';
|
||||
|
||||
const generateStrikeTag = (wrapTagName = openTag) => {
|
||||
return (_, mark) => {
|
||||
if (mark.attrs.sourceMarkdown) return '~~';
|
||||
if (mark.attrs.sourceTagName) return wrapTagName(mark.attrs.sourceTagName);
|
||||
if (mark.attrs.htmlTag) return wrapTagName(mark.attrs.htmlTag);
|
||||
|
||||
const type = /^(~~|<del|<strike|<s).*/.exec(mark.attrs.sourceMarkdown)?.[1];
|
||||
|
||||
switch (type) {
|
||||
case '~~':
|
||||
return type;
|
||||
case '<del': // eslint-disable-line @gitlab/require-i18n-strings
|
||||
case '<strike': // eslint-disable-line @gitlab/require-i18n-strings
|
||||
case '<s':
|
||||
return wrapTagName(type.substring(1));
|
||||
default:
|
||||
return '~~';
|
||||
}
|
||||
return '~~';
|
||||
};
|
||||
};
|
||||
|
||||
const strike = {
|
||||
const strike = preserveUnchangedMark({
|
||||
open: generateStrikeTag(),
|
||||
close: generateStrikeTag(closeTag),
|
||||
mixable: true,
|
||||
expelEnclosingWhitespace: true,
|
||||
};
|
||||
});
|
||||
|
||||
export default strike;
|
||||
|
|
|
|||
|
|
@ -359,6 +359,16 @@ class Repository
|
|||
@branch_names_include = nil
|
||||
end
|
||||
|
||||
def expire_branch_names_cache
|
||||
expire_method_caches(%i[branch_names branch_count])
|
||||
@local_branches = nil
|
||||
end
|
||||
|
||||
def expire_tag_names_cache
|
||||
expire_method_caches(%i[tag_names tag_count])
|
||||
@tags = nil
|
||||
end
|
||||
|
||||
def expire_protected_branches_cache
|
||||
ProtectedBranches::CacheService.new(project).refresh if project # rubocop:disable CodeReuse/ServiceClass
|
||||
end
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ class PostReceive
|
|||
|
||||
sidekiq_options retry: 3
|
||||
include Gitlab::Experiment::Dsl
|
||||
include ::Gitlab::ExclusiveLeaseHelpers
|
||||
|
||||
feature_category :source_code_management
|
||||
urgency :high
|
||||
|
|
@ -18,6 +19,8 @@ class PostReceive
|
|||
|
||||
def perform(gl_repository, identifier, changes, push_options = {})
|
||||
container, project, repo_type = Gitlab::GlRepository.parse(gl_repository)
|
||||
@project = project
|
||||
@gl_repository = gl_repository
|
||||
|
||||
if container.nil? || (container.is_a?(ProjectSnippet) && project.nil?)
|
||||
log("Triggered hook for non-existing gl_repository \"#{gl_repository}\"")
|
||||
|
|
@ -111,8 +114,49 @@ class PostReceive
|
|||
# Expire the repository status, branch, and tag cache once per push.
|
||||
def expire_caches(post_received, repository)
|
||||
repository.expire_status_cache if repository.empty?
|
||||
repository.expire_branches_cache if post_received.includes_branches?
|
||||
repository.expire_caches_for_tags if post_received.includes_tags?
|
||||
expire_branch_cache(repository) if post_received.includes_branches?
|
||||
expire_tag_cache(repository) if post_received.includes_tags?
|
||||
end
|
||||
|
||||
def expire_branch_cache(repository)
|
||||
repository.expire_branches_cache
|
||||
|
||||
# Consider the scenario where multiple pushes happen in close succession:
|
||||
#
|
||||
# 1. Job 1 expires cache.
|
||||
# 2. Job 1 starts computing branch list.
|
||||
# 3. Job 2 starts.
|
||||
# 4. Job 2 expires cache (no-op because nothing is there).
|
||||
# 5. Job 1 finishes computing branch list, persists cache.
|
||||
# 6. Job 2 reads from stale cache instead of loading a fresh branch list.
|
||||
#
|
||||
# To avoid this, atomically expire and refresh the branch name cache
|
||||
# so that tasks such as pipeline creation will find the branch.
|
||||
if Feature.enabled?(:post_receive_sync_refresh_cache, @project)
|
||||
in_lock(lease_key(:branch), ttl: cache_ttl) do
|
||||
repository.expire_branch_names_cache
|
||||
repository.branch_names
|
||||
end
|
||||
end
|
||||
rescue Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError
|
||||
log("Failed to obtain lease for expiring branch name cache")
|
||||
end
|
||||
|
||||
def expire_tag_cache(repository)
|
||||
repository.expire_caches_for_tags
|
||||
|
||||
if Feature.enabled?(:post_receive_sync_refresh_cache, @project)
|
||||
in_lock(lease_key(:tag), ttl: cache_ttl) do
|
||||
repository.expire_tag_names_cache
|
||||
repository.tag_names
|
||||
end
|
||||
end
|
||||
rescue Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError
|
||||
log("Failed to obtain lease for expiring tag name cache")
|
||||
end
|
||||
|
||||
def lease_key(ref_type)
|
||||
"post_receive:#{@gl_repository}:#{ref_type}"
|
||||
end
|
||||
|
||||
# Schedule an update for the repository size and commit count if necessary.
|
||||
|
|
@ -152,6 +196,10 @@ class PostReceive
|
|||
def log(message)
|
||||
Gitlab::GitLogger.error("POST-RECEIVE: #{message}")
|
||||
end
|
||||
|
||||
def cache_ttl
|
||||
::Gitlab::GitalyClient.fast_timeout * 2
|
||||
end
|
||||
end
|
||||
|
||||
PostReceive.prepend_mod_with('PostReceive')
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
name: post_receive_sync_refresh_cache
|
||||
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/20891
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/160946
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/474741
|
||||
milestone: '17.3'
|
||||
group: group::pipeline execution
|
||||
type: gitlab_com_derisk
|
||||
default_enabled: false
|
||||
|
|
@ -1,11 +1,16 @@
|
|||
ARG DOCKER_VERSION=24.0.5
|
||||
ARG CHROME_VERSION=123
|
||||
ARG RUBY_VERSION=3.2.4
|
||||
ARG BUILD_OS=debian
|
||||
ARG CHROME_VERSION=123
|
||||
ARG DOCKER_VERSION=24.0.5
|
||||
ARG GCLOUD_VERSION=413
|
||||
ARG GIT_VERSION=2.45
|
||||
ARG HELM_VERSION=3.14
|
||||
ARG KUBECTL_VERSION=1.28
|
||||
ARG LFS_VERSION=2.9
|
||||
ARG OS_VERSION=bookworm
|
||||
ARG QA_BUILD_TARGET=ee
|
||||
ARG RUBY_VERSION=3.2.4
|
||||
|
||||
FROM registry.gitlab.com/gitlab-org/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}:git-2.36-lfs-2.9-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-gcloud-383-kubectl-1.23 AS foss
|
||||
FROM registry.gitlab.com/gitlab-org/gitlab-build-images/${BUILD_OS}-${OS_VERSION}-ruby-${RUBY_VERSION}:git-${GIT_VERSION}-lfs-${LFS_VERSION}-chrome-${CHROME_VERSION}-docker-${DOCKER_VERSION}-gcloud-${GCLOUD_VERSION}-kubectl-${KUBECTL_VERSION}-helm-${HELM_VERSION} AS foss
|
||||
LABEL maintainer="GitLab Quality Department <quality@gitlab.com>"
|
||||
|
||||
ENV DEBIAN_FRONTEND="noninteractive"
|
||||
|
|
|
|||
|
|
@ -84,12 +84,17 @@ docker buildx build \
|
|||
--cache-from="$QA_IMAGE_BRANCH" \
|
||||
--cache-from="$QA_IMAGE_MASTER" \
|
||||
--platform=${ARCH:-amd64} \
|
||||
--build-arg=BUILD_OS="${BUILD_OS}" \
|
||||
--build-arg=CHROME_VERSION="${CHROME_VERSION}" \
|
||||
--build-arg=DOCKER_VERSION="${DOCKER_VERSION}" \
|
||||
--build-arg=RUBY_VERSION="${RUBY_VERSION}" \
|
||||
--build-arg=BUILD_OS="${BUILD_OS}" \
|
||||
--build-arg=GCLOUD_VERSION="${GCLOUD_VERSION}" \
|
||||
--build-arg=GIT_VERSION="${GIT_VERSION}" \
|
||||
--build-arg=HELM_VERSION="${HELM_VERSION}" \
|
||||
--build-arg=KUBECTL_VERSION="${KUBECTL_VERSION}" \
|
||||
--build-arg=LFS_VERSION="${LFS_VERSION}" \
|
||||
--build-arg=OS_VERSION="${OS_VERSION}" \
|
||||
--build-arg=QA_BUILD_TARGET="${QA_BUILD_TARGET}" \
|
||||
--build-arg=RUBY_VERSION="${RUBY_VERSION}" \
|
||||
--file="${CI_PROJECT_DIR}/qa/Dockerfile" \
|
||||
--push \
|
||||
--provenance=false \
|
||||
|
|
|
|||
|
|
@ -282,7 +282,14 @@ RSpec.describe '.gitlab/ci/rules.gitlab-ci.yml', feature_category: :tooling do
|
|||
next unless name.end_with?('patterns')
|
||||
|
||||
# Ignore EE-only patterns list when in FOSS context
|
||||
relevant_patterns = foss_context ? patterns.reject { |pattern| pattern =~ %r|^{?ee/| } : patterns
|
||||
relevant_patterns = if foss_context
|
||||
patterns.reject do |pattern|
|
||||
pattern =~ %r|^{?ee/| || pattern == '.tool-versions'
|
||||
end
|
||||
else
|
||||
patterns
|
||||
end
|
||||
|
||||
next if relevant_patterns.empty?
|
||||
next if foss_context && name == '.custom-roles-patterns'
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,4 @@
|
|||
import { uniqueId } from 'lodash';
|
||||
import { builders } from 'prosemirror-test-builder';
|
||||
import Sourcemap from '~/content_editor/extensions/sourcemap';
|
||||
import MarkdownSerializer from '~/content_editor/services/markdown_serializer';
|
||||
|
|
@ -11,7 +12,18 @@ const b = builders(tiptapEditor.schema);
|
|||
export { b as builders };
|
||||
|
||||
export const serializeWithOptions = (options, ...content) =>
|
||||
new MarkdownSerializer().serialize({ doc: b.doc(...content) }, options);
|
||||
new MarkdownSerializer().serialize(
|
||||
{ doc: b.doc(...content), pristineDoc: options.pristineDoc && b.doc(options.pristineDoc) },
|
||||
options,
|
||||
);
|
||||
|
||||
export const serialize = (...content) =>
|
||||
new MarkdownSerializer().serialize({ doc: b.doc(...content) });
|
||||
new MarkdownSerializer().serialize({ doc: b.doc(...content), pristineDoc: b.doc(...content) });
|
||||
|
||||
export const source = (sourceMarkdown, sourceTagName) => ({
|
||||
sourceMarkdown,
|
||||
sourceMapKey: uniqueId('key-'),
|
||||
sourceTagName,
|
||||
});
|
||||
|
||||
export const sourceTag = (sourceTagName) => ({ sourceTagName });
|
||||
|
|
|
|||
|
|
@ -1,7 +1,49 @@
|
|||
import { serialize, builders } from '../../serialization_utils';
|
||||
import {
|
||||
serialize,
|
||||
builders,
|
||||
source,
|
||||
sourceTag,
|
||||
serializeWithOptions,
|
||||
} from '../../serialization_utils';
|
||||
|
||||
const { paragraph, bold } = builders;
|
||||
|
||||
it('correctly serializes bold', () => {
|
||||
expect(serialize(paragraph(bold('bold')))).toBe('**bold**');
|
||||
});
|
||||
|
||||
it.each`
|
||||
boldStyle
|
||||
${'**'}
|
||||
${'__'}
|
||||
`('correctly serializes bold with sourcemap including $boldStyle', ({ boldStyle }) => {
|
||||
const sourceMarkdown = source(`${boldStyle}bolded\ncontent${boldStyle}`, 'strong');
|
||||
|
||||
expect(serialize(paragraph(bold(sourceMarkdown, 'bolded content')))).toBe(
|
||||
`${boldStyle}bolded\ncontent${boldStyle}`,
|
||||
);
|
||||
|
||||
expect(
|
||||
serializeWithOptions(
|
||||
{ pristineDoc: paragraph(bold(sourceMarkdown, 'bolded content')) },
|
||||
paragraph(bold(sourceMarkdown, 'new content')),
|
||||
),
|
||||
).toBe(`${boldStyle}new content${boldStyle}`);
|
||||
});
|
||||
|
||||
it.each`
|
||||
htmlTag
|
||||
${'strong'}
|
||||
${'b'}
|
||||
`('correctly preserves bold with a htmlTag $htmlTag', ({ htmlTag }) => {
|
||||
expect(serialize(paragraph(bold(sourceTag(htmlTag), 'bolded content')))).toBe(
|
||||
`<${htmlTag}>bolded content</${htmlTag}>`,
|
||||
);
|
||||
|
||||
expect(
|
||||
serializeWithOptions(
|
||||
{ pristineDoc: paragraph(bold(sourceTag(htmlTag), 'bolded content')) },
|
||||
paragraph(bold(sourceTag(htmlTag), 'new content')),
|
||||
),
|
||||
).toBe(`<${htmlTag}>new content</${htmlTag}>`);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,10 @@
|
|||
import { serialize, builders } from '../../serialization_utils';
|
||||
import {
|
||||
serialize,
|
||||
source,
|
||||
serializeWithOptions,
|
||||
builders,
|
||||
sourceTag,
|
||||
} from '../../serialization_utils';
|
||||
|
||||
const { paragraph, code, italic, bold, strike } = builders;
|
||||
|
||||
|
|
@ -23,3 +29,25 @@ it('correctly serializes inline code wrapped by italics and bold marks', () => {
|
|||
expect(serialize(paragraph(strike(code(content))))).toBe(`~~\`${content}\`~~`);
|
||||
expect(serialize(paragraph(code(strike(content))))).toBe(`~~\`${content}\`~~`);
|
||||
});
|
||||
|
||||
it('correctly serializes code with sourcemap including `', () => {
|
||||
const sourceMarkdown = source('`code content`', 'code');
|
||||
|
||||
expect(
|
||||
serializeWithOptions(
|
||||
{ pristineDoc: paragraph(code(sourceMarkdown, 'code content')) },
|
||||
paragraph(code(sourceMarkdown, 'new content')),
|
||||
),
|
||||
).toBe(`\`new content\``);
|
||||
});
|
||||
|
||||
it('correctly preserves code with a html tag <code>', () => {
|
||||
expect(serialize(paragraph(code(sourceTag('code'), 'code')))).toBe(`<code>code</code>`);
|
||||
|
||||
expect(
|
||||
serializeWithOptions(
|
||||
{ pristineDoc: paragraph(code(sourceTag('code'), 'code content')) },
|
||||
paragraph(code(sourceTag('code'), 'new content')),
|
||||
),
|
||||
).toBe(`<code>new content</code>`);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
import { serialize, builders } from '../../serialization_utils';
|
||||
import { serialize, serializeWithOptions, builders, source } from '../../serialization_utils';
|
||||
|
||||
const { paragraph, inlineDiff } = builders;
|
||||
|
||||
|
|
@ -12,3 +12,21 @@ it('correctly serializes inline diff', () => {
|
|||
),
|
||||
).toBe('{++30 lines+}{--10 lines-}');
|
||||
});
|
||||
|
||||
it.each`
|
||||
type | start | end
|
||||
${'addition'} | ${'{+'} | ${'+}'}
|
||||
${'deletion'} | ${'{-'} | ${'-}'}
|
||||
`('correctly serializes inline diff with sourcemap', ({ type, start, end }) => {
|
||||
const sourceMarkdown = source(`${start}+30 lines${end}`);
|
||||
const diffAttrs = { ...sourceMarkdown, type };
|
||||
|
||||
expect(serialize(paragraph(inlineDiff(diffAttrs, '+30 lines')))).toBe(`${start}+30 lines${end}`);
|
||||
|
||||
expect(
|
||||
serializeWithOptions(
|
||||
{ pristineDoc: paragraph(inlineDiff(diffAttrs, '+30 lines')) },
|
||||
paragraph(inlineDiff(diffAttrs, '+40 lines')),
|
||||
),
|
||||
).toBe(`${start}+40 lines${end}`);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,7 +1,49 @@
|
|||
import { serialize, builders } from '../../serialization_utils';
|
||||
import {
|
||||
serialize,
|
||||
builders,
|
||||
source,
|
||||
sourceTag,
|
||||
serializeWithOptions,
|
||||
} from '../../serialization_utils';
|
||||
|
||||
const { paragraph, italic } = builders;
|
||||
|
||||
it('correctly serializes italics', () => {
|
||||
expect(serialize(paragraph(italic('italics')))).toBe('_italics_');
|
||||
});
|
||||
|
||||
it.each`
|
||||
italicStyle
|
||||
${'*'}
|
||||
${'_'}
|
||||
`('correctly serializes italic with sourcemap including $italicStyle', ({ italicStyle }) => {
|
||||
const sourceMarkdown = source(`${italicStyle}italic\ncontent${italicStyle}`, 'em');
|
||||
|
||||
expect(serialize(paragraph(italic(sourceMarkdown, 'italic content')))).toBe(
|
||||
`${italicStyle}italic\ncontent${italicStyle}`,
|
||||
);
|
||||
|
||||
expect(
|
||||
serializeWithOptions(
|
||||
{ pristineDoc: paragraph(italic(sourceMarkdown, 'italic content')) },
|
||||
paragraph(italic(sourceMarkdown, 'new content')),
|
||||
),
|
||||
).toBe(`${italicStyle}new content${italicStyle}`);
|
||||
});
|
||||
|
||||
it.each`
|
||||
htmlTag
|
||||
${'em'}
|
||||
${'i'}
|
||||
`('correctly preserves italic with a htmlTag $htmlTag', ({ htmlTag }) => {
|
||||
expect(serialize(paragraph(italic(sourceTag(htmlTag), 'italic content')))).toBe(
|
||||
`<${htmlTag}>italic content</${htmlTag}>`,
|
||||
);
|
||||
|
||||
expect(
|
||||
serializeWithOptions(
|
||||
{ pristineDoc: paragraph(italic(sourceTag(htmlTag), 'italic content')) },
|
||||
paragraph(italic(sourceTag(htmlTag), 'new content')),
|
||||
),
|
||||
).toBe(`<${htmlTag}>new content</${htmlTag}>`);
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,4 +1,10 @@
|
|||
import { serialize, builders } from '../../serialization_utils';
|
||||
import {
|
||||
serialize,
|
||||
serializeWithOptions,
|
||||
builders,
|
||||
source,
|
||||
sourceTag,
|
||||
} from '../../serialization_utils';
|
||||
|
||||
const { paragraph, link } = builders;
|
||||
|
||||
|
|
@ -95,3 +101,42 @@ it.each`
|
|||
).toBe(serialized);
|
||||
},
|
||||
);
|
||||
|
||||
it('correctly serializes links with sourcemap', () => {
|
||||
const sourceMarkdown = source('[link\nwith\nwhitespace](https://link.url "title")');
|
||||
const linkAttrs = {
|
||||
...sourceMarkdown,
|
||||
href: 'https://link.url',
|
||||
title: 'title',
|
||||
};
|
||||
|
||||
expect(serialize(paragraph(link(linkAttrs, 'link with whitespace')))).toBe(
|
||||
'[link\nwith\nwhitespace](https://link.url "title")',
|
||||
);
|
||||
|
||||
expect(
|
||||
serializeWithOptions(
|
||||
{ pristineDoc: paragraph(link(linkAttrs, 'link with whitespace')) },
|
||||
paragraph(link(linkAttrs, 'new content')),
|
||||
),
|
||||
).toBe('[new content](https://link.url "title")');
|
||||
});
|
||||
|
||||
it('correctly serializes links as an HTML tag', () => {
|
||||
const linkAttrs = {
|
||||
href: 'https://example.com',
|
||||
title: 'example',
|
||||
...sourceTag('a'),
|
||||
};
|
||||
|
||||
expect(serialize(paragraph(link(linkAttrs, 'example url')))).toBe(
|
||||
'<a href="https://example.com" title="example">example url</a>',
|
||||
);
|
||||
|
||||
expect(
|
||||
serializeWithOptions(
|
||||
{ pristineDoc: paragraph(link(linkAttrs, 'example url')) },
|
||||
paragraph(link(linkAttrs, 'new content')),
|
||||
),
|
||||
).toBe('<a href="https://example.com" title="example">new content</a>');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -0,0 +1,7 @@
|
|||
import { serialize, builders } from '../../serialization_utils';
|
||||
|
||||
const { paragraph, mathInline } = builders;
|
||||
|
||||
it('correctly serializes inline math', () => {
|
||||
expect(serialize(paragraph(mathInline('a^2 + b^2')))).toBe('$`a^2 + b^2`$');
|
||||
});
|
||||
|
|
@ -1,4 +1,10 @@
|
|||
import { serialize, builders } from '../../serialization_utils';
|
||||
import {
|
||||
serialize,
|
||||
serializeWithOptions,
|
||||
builders,
|
||||
source,
|
||||
sourceTag,
|
||||
} from '../../serialization_utils';
|
||||
|
||||
const { paragraph, strike } = builders;
|
||||
|
||||
|
|
@ -7,11 +13,36 @@ it('correctly serializes strikethrough', () => {
|
|||
});
|
||||
|
||||
it.each`
|
||||
strikeTag
|
||||
${'s'}
|
||||
${'strike'}
|
||||
`('correctly serializes strikethrough with "$strikeTag" tag', ({ strikeTag }) => {
|
||||
expect(serialize(paragraph(strike({ htmlTag: strikeTag }, 'deleted content')))).toBe(
|
||||
`<${strikeTag}>deleted content</${strikeTag}>`,
|
||||
attrs | tagName
|
||||
${sourceTag('s')} | ${'s'}
|
||||
${sourceTag('strike')} | ${'strike'}
|
||||
${sourceTag('del')} | ${'del'}
|
||||
${{ htmlTag: 's' }} | ${'s'}
|
||||
${{ htmlTag: 'strike' }} | ${'strike'}
|
||||
`('correctly serializes strikethrough with a attrs $attrs', ({ attrs, tagName }) => {
|
||||
expect(serialize(paragraph(strike(attrs, 'deleted content')))).toBe(
|
||||
`<${tagName}>deleted content</${tagName}>`,
|
||||
);
|
||||
|
||||
expect(
|
||||
serializeWithOptions(
|
||||
{ pristineDoc: paragraph(strike(attrs, 'deleted content')) },
|
||||
paragraph(strike(attrs, 'new content')),
|
||||
),
|
||||
).toBe(`<${tagName}>new content</${tagName}>`);
|
||||
});
|
||||
|
||||
it('correctly serializes strikethrough with sourcemap', () => {
|
||||
const sourceMarkdown = source('~~deleted\ncontent~~');
|
||||
|
||||
expect(serialize(paragraph(strike(sourceMarkdown, 'deleted content')))).toBe(
|
||||
'~~deleted\ncontent~~',
|
||||
);
|
||||
|
||||
expect(
|
||||
serializeWithOptions(
|
||||
{ pristineDoc: paragraph(strike(sourceMarkdown, 'deleted content')) },
|
||||
paragraph(strike(sourceMarkdown, 'new content')),
|
||||
),
|
||||
).toBe('~~new content~~');
|
||||
});
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { DATE_TIME_FORMATS, localeDateFormat } from '~/lib/utils/datetime/locale_dateformat';
|
||||
import { setLanguage } from 'jest/__helpers__/locale_helper';
|
||||
// eslint-disable-next-line no-restricted-imports
|
||||
import * as localeFns from '~/locale';
|
||||
|
||||
describe('localeDateFormat (en-US)', () => {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
// Copied to ee/spec/frontend/notes/mock_data.js
|
||||
import { HTTP_STATUS_OK } from '~/lib/utils/http_status';
|
||||
import { __ } from '~/locale';
|
||||
|
||||
export const notesDataMock = {
|
||||
discussionsPath: '/gitlab-org/gitlab-foss/issues/26/discussions.json',
|
||||
|
|
@ -1300,15 +1299,15 @@ export const draftDiffDiscussion = {
|
|||
|
||||
export const notesFilters = [
|
||||
{
|
||||
title: __('Show all activity'),
|
||||
title: 'Show all activity',
|
||||
value: 0,
|
||||
},
|
||||
{
|
||||
title: __('Show comments only'),
|
||||
title: 'Show comments only',
|
||||
value: 1,
|
||||
},
|
||||
{
|
||||
title: __('Show history only'),
|
||||
title: 'Show history only',
|
||||
value: 2,
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -5,7 +5,6 @@ import {
|
|||
SAST_IAC_SHORT_NAME,
|
||||
PRE_RECEIVE_SECRET_DETECTION,
|
||||
} from '~/security_configuration/constants';
|
||||
import { __, s__ } from '~/locale';
|
||||
import { helpPagePath } from '~/helpers/help_page_helper';
|
||||
|
||||
import {
|
||||
|
|
@ -23,36 +22,31 @@ export const testTrainingUrls = [
|
|||
'https://www.vendornamethree.com/url',
|
||||
];
|
||||
|
||||
const SAST_DESCRIPTION = __('Analyze your source code for known vulnerabilities.');
|
||||
const SAST_DESCRIPTION = 'Analyze your source code for known vulnerabilities.';
|
||||
const SAST_HELP_PATH = helpPagePath('user/application_security/sast/index');
|
||||
const SAST_CONFIG_HELP_PATH = helpPagePath('user/application_security/sast/index', {
|
||||
anchor: 'configuration',
|
||||
});
|
||||
|
||||
const BAS_BADGE_TEXT = s__('SecurityConfiguration|Incubating feature');
|
||||
const BAS_BADGE_TOOLTIP = s__(
|
||||
'SecurityConfiguration|Breach and Attack Simulation is an incubating feature extending existing security testing by simulating adversary activity.',
|
||||
);
|
||||
const BAS_DESCRIPTION = s__(
|
||||
'SecurityConfiguration|Simulate breach and attack scenarios against your running application by attempting to detect and exploit known vulnerabilities.',
|
||||
);
|
||||
const BAS_BADGE_TEXT = 'Incubating feature';
|
||||
const BAS_BADGE_TOOLTIP =
|
||||
'Breach and Attack Simulation is an incubating feature extending existing security testing by simulating adversary activity.';
|
||||
const BAS_DESCRIPTION =
|
||||
'Simulate breach and attack scenarios against your running application by attempting to detect and exploit known vulnerabilities.';
|
||||
const BAS_HELP_PATH = helpPagePath('user/application_security/breach_and_attack_simulation/index');
|
||||
const BAS_NAME = s__('SecurityConfiguration|Breach and Attack Simulation (BAS)');
|
||||
const BAS_SHORT_NAME = s__('SecurityConfiguration|BAS');
|
||||
const BAS_DAST_FEATURE_FLAG_DESCRIPTION = s__(
|
||||
'SecurityConfiguration|Enable incubating Breach and Attack Simulation focused features such as callback attacks in your DAST scans.',
|
||||
);
|
||||
const BAS_NAME = 'Breach and Attack Simulation (BAS)';
|
||||
const BAS_SHORT_NAME = 'BAS';
|
||||
const BAS_DAST_FEATURE_FLAG_DESCRIPTION =
|
||||
'Enable incubating Breach and Attack Simulation focused features such as callback attacks in your DAST scans.';
|
||||
const BAS_DAST_FEATURE_FLAG_HELP_PATH = helpPagePath(
|
||||
'user/application_security/breach_and_attack_simulation/index',
|
||||
{ anchor: 'extend-dynamic-application-security-testing-dast' },
|
||||
);
|
||||
const BAS_DAST_FEATURE_FLAG_NAME = s__(
|
||||
'SecurityConfiguration|Out-of-Band Application Security Testing (OAST)',
|
||||
);
|
||||
const BAS_DAST_FEATURE_FLAG_NAME =
|
||||
'SecurityConfiguration|Out-of-Band Application Security Testing (OAST)';
|
||||
|
||||
const SAST_IAC_DESCRIPTION = __(
|
||||
'Analyze your infrastructure as code configuration files for known vulnerabilities.',
|
||||
);
|
||||
const SAST_IAC_DESCRIPTION =
|
||||
'Analyze your infrastructure as code configuration files for known vulnerabilities.';
|
||||
const SAST_IAC_HELP_PATH = helpPagePath('user/application_security/iac_scanning/index');
|
||||
const SAST_IAC_CONFIG_HELP_PATH = helpPagePath('user/application_security/iac_scanning/index', {
|
||||
anchor: 'configuration',
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
import { s__ } from '~/locale';
|
||||
|
||||
export const getIssueCrmContactsQueryResponse = {
|
||||
data: {
|
||||
issue: {
|
||||
|
|
@ -72,42 +70,42 @@ export const issueCrmContactsUpdateResponse = {
|
|||
};
|
||||
|
||||
export const mockSuggestedColors = {
|
||||
'#009966': s__('SuggestedColors|Green-cyan'),
|
||||
'#8fbc8f': s__('SuggestedColors|Dark sea green'),
|
||||
'#3cb371': s__('SuggestedColors|Medium sea green'),
|
||||
'#00b140': s__('SuggestedColors|Green screen'),
|
||||
'#013220': s__('SuggestedColors|Dark green'),
|
||||
'#6699cc': s__('SuggestedColors|Blue-gray'),
|
||||
'#0000ff': s__('SuggestedColors|Blue'),
|
||||
'#e6e6fa': s__('SuggestedColors|Lavender'),
|
||||
'#9400d3': s__('SuggestedColors|Dark violet'),
|
||||
'#330066': s__('SuggestedColors|Deep violet'),
|
||||
'#808080': s__('SuggestedColors|Gray'),
|
||||
'#36454f': s__('SuggestedColors|Charcoal grey'),
|
||||
'#f7e7ce': s__('SuggestedColors|Champagne'),
|
||||
'#c21e56': s__('SuggestedColors|Rose red'),
|
||||
'#cc338b': s__('SuggestedColors|Magenta-pink'),
|
||||
'#dc143c': s__('SuggestedColors|Crimson'),
|
||||
'#ff0000': s__('SuggestedColors|Red'),
|
||||
'#cd5b45': s__('SuggestedColors|Dark coral'),
|
||||
'#eee600': s__('SuggestedColors|Titanium yellow'),
|
||||
'#ed9121': s__('SuggestedColors|Carrot orange'),
|
||||
'#c39953': s__('SuggestedColors|Aztec Gold'),
|
||||
'#009966': 'Green-cyan',
|
||||
'#8fbc8f': 'Dark sea green',
|
||||
'#3cb371': 'Medium sea green',
|
||||
'#00b140': 'Green screen',
|
||||
'#013220': 'Dark green',
|
||||
'#6699cc': 'Blue-gray',
|
||||
'#0000ff': 'Blue',
|
||||
'#e6e6fa': 'Lavender',
|
||||
'#9400d3': 'Dark violet',
|
||||
'#330066': 'Deep violet',
|
||||
'#808080': 'Gray',
|
||||
'#36454f': 'Charcoal grey',
|
||||
'#f7e7ce': 'Champagne',
|
||||
'#c21e56': 'Rose red',
|
||||
'#cc338b': 'Magenta-pink',
|
||||
'#dc143c': 'Crimson',
|
||||
'#ff0000': 'Red',
|
||||
'#cd5b45': 'Dark coral',
|
||||
'#eee600': 'Titanium yellow',
|
||||
'#ed9121': 'Carrot orange',
|
||||
'#c39953': 'Aztec Gold',
|
||||
};
|
||||
|
||||
export const mockSuggestedEpicColors = [
|
||||
{ '#E9BE74': s__('WorkItem|Apricot') },
|
||||
{ '#D99530': s__('WorkItem|Copper') },
|
||||
{ '#C17D10': s__('WorkItem|Rust') },
|
||||
{ '#F57F6C': s__('WorkItem|Pink') },
|
||||
{ '#EC5941': s__('WorkItem|Vermilion') },
|
||||
{ '#DD2B0E': s__('WorkItem|Red') },
|
||||
{ '#C91C00': s__('WorkItem|Dark red') },
|
||||
{ '#52B87A': s__('WorkItem|Teal') },
|
||||
{ '#2DA160': s__('WorkItem|Green') },
|
||||
{ '#108548': s__('WorkItem|Forest green') },
|
||||
{ '#63A6E9': s__('WorkItem|Sky blue') },
|
||||
{ '#428FDC': s__('WorkItem|Royal blue') },
|
||||
{ '#1F75CB': s__('WorkItem|Blue') },
|
||||
{ '#1068BF': s__('WorkItem|Midnight blue') },
|
||||
{ '#E9BE74': 'Apricot' },
|
||||
{ '#D99530': 'Copper' },
|
||||
{ '#C17D10': 'Rust' },
|
||||
{ '#F57F6C': 'Pink' },
|
||||
{ '#EC5941': 'Vermilion' },
|
||||
{ '#DD2B0E': 'Red' },
|
||||
{ '#C91C00': 'Dark red' },
|
||||
{ '#52B87A': 'Teal' },
|
||||
{ '#2DA160': 'Green' },
|
||||
{ '#108548': 'Forest green' },
|
||||
{ '#63A6E9': 'Sky blue' },
|
||||
{ '#428FDC': 'Royal blue' },
|
||||
{ '#1F75CB': 'Blue' },
|
||||
{ '#1068BF': 'Midnight blue' },
|
||||
];
|
||||
|
|
|
|||
|
|
@ -2699,6 +2699,16 @@ RSpec.describe Repository, feature_category: :source_code_management do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#expire_branch_names_cache' do
|
||||
it 'expires the cache' do
|
||||
expect(repository).to receive(:expire_method_caches)
|
||||
.with(%i[branch_names branch_count])
|
||||
.and_call_original
|
||||
|
||||
repository.expire_branch_names_cache
|
||||
end
|
||||
end
|
||||
|
||||
describe '#expire_protected_branches_cache' do
|
||||
it 'expires the cache' do
|
||||
expect_next_instance_of(ProtectedBranches::CacheService) do |cache_service|
|
||||
|
|
@ -2729,6 +2739,16 @@ RSpec.describe Repository, feature_category: :source_code_management do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#expire_tag_names_cache' do
|
||||
it 'expires the cache' do
|
||||
expect(repository).to receive(:expire_method_caches)
|
||||
.with(%i[tag_names tag_count])
|
||||
.and_call_original
|
||||
|
||||
repository.expire_tag_names_cache
|
||||
end
|
||||
end
|
||||
|
||||
describe '#add_tag' do
|
||||
let(:user) { build_stubbed(:user) }
|
||||
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ RSpec.configure do |config|
|
|||
metadata[:type] = :feature
|
||||
end
|
||||
|
||||
config.define_derived_metadata(file_path: %r{spec/dot_gitlab_ci/}) do |metadata|
|
||||
config.define_derived_metadata(file_path: %r{spec/dot_gitlab_ci/job_dependency_spec.rb}) do |metadata|
|
||||
metadata[:ci_config_validation] = true
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe PostReceive, feature_category: :source_code_management do
|
||||
RSpec.describe PostReceive, :clean_gitlab_redis_shared_state, feature_category: :source_code_management do
|
||||
include AfterNextHelpers
|
||||
|
||||
let(:changes) do
|
||||
|
|
@ -448,6 +448,37 @@ RSpec.describe PostReceive, feature_category: :source_code_management do
|
|||
|
||||
perform
|
||||
end
|
||||
|
||||
context 'with post_receive_sync_refresh_cache feature flag enabled' do
|
||||
it 'refreshes branch names cache' do
|
||||
expect(snippet.repository).to receive(:expire_branch_names_cache).and_call_original
|
||||
expect(snippet.repository).to receive(:branch_names).and_call_original
|
||||
|
||||
perform
|
||||
end
|
||||
|
||||
context 'when exclusive lease fails' do
|
||||
it 'logs a message' do
|
||||
expect(snippet.repository).to receive(:branch_names).and_raise(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
|
||||
expect(Gitlab::GitLogger).to receive(:error).with("POST-RECEIVE: Failed to obtain lease for expiring branch name cache")
|
||||
|
||||
perform
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with post_receive_sync_refresh_cache feature flag disabled' do
|
||||
before do
|
||||
stub_feature_flags(post_receive_sync_refresh_cache: false)
|
||||
end
|
||||
|
||||
it 'does not expire branch names cache' do
|
||||
expect(snippet.repository).not_to receive(:expire_tag_names_cache)
|
||||
expect(snippet.repository).not_to receive(:tag_names)
|
||||
|
||||
perform
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'tags' do
|
||||
|
|
@ -472,6 +503,37 @@ RSpec.describe PostReceive, feature_category: :source_code_management do
|
|||
perform
|
||||
end
|
||||
end
|
||||
|
||||
context 'with post_receive_sync_refresh_cache feature flag enabled' do
|
||||
it 'refreshes the tag names cache' do
|
||||
expect(snippet.repository).to receive(:expire_tag_names_cache).and_call_original
|
||||
expect(snippet.repository).to receive(:tag_names).and_call_original
|
||||
|
||||
perform
|
||||
end
|
||||
|
||||
context 'when exclusive lease fails' do
|
||||
it 'logs a message' do
|
||||
expect(snippet.repository).to receive(:tag_names).and_raise(Gitlab::ExclusiveLeaseHelpers::FailedToObtainLockError)
|
||||
expect(Gitlab::GitLogger).to receive(:error).with("POST-RECEIVE: Failed to obtain lease for expiring tag name cache")
|
||||
|
||||
perform
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'with post_receive_sync_refresh_cache feature flag disabled' do
|
||||
before do
|
||||
stub_feature_flags(post_receive_sync_refresh_cache: false)
|
||||
end
|
||||
|
||||
it 'does not expire tag names cache' do
|
||||
expect(snippet.repository).not_to receive(:expire_tag_names_cache)
|
||||
expect(snippet.repository).not_to receive(:tag_names)
|
||||
|
||||
perform
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
it_behaves_like 'an idempotent worker'
|
||||
|
|
|
|||
|
|
@ -37,6 +37,10 @@ mapping:
|
|||
- source: 'rubocop/(?<rest>.+)\.rb'
|
||||
test: 'spec/rubocop/%{rest}_spec.rb'
|
||||
|
||||
# .gitlab/ci related specs
|
||||
- source: '.gitlab/ci/(?<rest>.+)\.gitlab-ci\.yml'
|
||||
test: 'spec/dot_gitlab_ci/rules_spec.rb'
|
||||
|
||||
# Map config to respective specs
|
||||
- source: 'config/(?<rest>.+)\..*'
|
||||
test: 'spec/config/%{rest}_spec.rb'
|
||||
|
|
|
|||
Loading…
Reference in New Issue