Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
37a739daec
commit
4597f7fe47
|
|
@ -19,14 +19,19 @@ build-qa-image:
|
|||
QA_IMAGE_BRANCH: ${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_REF_SLUG}
|
||||
script:
|
||||
- export QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_SHA}"
|
||||
# Auto-deploy tag format uses first 12 letters of commit SHA. Tag with
|
||||
# that reference also
|
||||
- export QA_IMAGE_FOR_AUTO_DEPLOY="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_SHA:0:11}"
|
||||
- echo $QA_IMAGE
|
||||
- echo $QA_IMAGE_BRANCH
|
||||
- echo $QA_IMAGE_FOR_AUTO_DEPLOY
|
||||
- |
|
||||
/kaniko/executor \
|
||||
--context=${CI_PROJECT_DIR} \
|
||||
--dockerfile=${CI_PROJECT_DIR}/qa/Dockerfile \
|
||||
--destination=${QA_IMAGE} \
|
||||
--destination=${QA_IMAGE_BRANCH} \
|
||||
--destination=${QA_IMAGE_FOR_AUTO_DEPLOY} \
|
||||
--build-arg=CHROME_VERSION=${CHROME_VERSION} \
|
||||
--build-arg=DOCKER_VERSION=${DOCKER_VERSION} \
|
||||
--build-arg=QA_BUILD_TARGET=${QA_BUILD_TARGET:-qa} \
|
||||
|
|
|
|||
|
|
@ -378,51 +378,19 @@ db:migrate:reset single-db:
|
|||
- .single-db
|
||||
- .rails:rules:single-db
|
||||
|
||||
db:migrate-from-previous-major-version:
|
||||
extends: .db-job-base
|
||||
variables:
|
||||
USE_BUNDLE_INSTALL: "false"
|
||||
SETUP_DB: "false"
|
||||
PROJECT_TO_CHECKOUT: "gitlab-foss"
|
||||
TAG_TO_CHECKOUT: "v14.10.2"
|
||||
before_script:
|
||||
- !reference [.default-before_script, before_script]
|
||||
- '[[ -d "ee/" ]] || export PROJECT_TO_CHECKOUT="gitlab"'
|
||||
- '[[ -d "ee/" ]] || export TAG_TO_CHECKOUT="${TAG_TO_CHECKOUT}-ee"'
|
||||
- retry 'git fetch https://gitlab.com/gitlab-org/$PROJECT_TO_CHECKOUT.git $TAG_TO_CHECKOUT'
|
||||
- git checkout -f FETCH_HEAD
|
||||
- SETUP_DB=false USE_BUNDLE_INSTALL=true ENABLE_BOOTSNAP=false bash scripts/prepare_build.sh
|
||||
- run_timed_command "ENABLE_BOOTSNAP=false bundle exec rake db:drop db:create db:structure:load db:migrate db:seed_fu"
|
||||
- git checkout -f $CI_COMMIT_SHA
|
||||
- SETUP_DB=false USE_BUNDLE_INSTALL=true bash scripts/prepare_build.sh
|
||||
script:
|
||||
- run_timed_command "scripts/db_tasks db:migrate"
|
||||
|
||||
db:migrate-from-previous-major-version-single-db:
|
||||
extends:
|
||||
- db:migrate-from-previous-major-version
|
||||
- .single-db
|
||||
- .rails:rules:single-db
|
||||
|
||||
.db:check-schema-base:
|
||||
extends:
|
||||
- .rails:rules:ee-mr-and-default-branch-only
|
||||
variables:
|
||||
TAG_TO_CHECKOUT: "v14.7.0" # this version updated grpc to 1.42.0, which supports Ruby 2 & 3
|
||||
script:
|
||||
- run_timed_command "scripts/db_tasks db:migrate"
|
||||
- scripts/schema_changed.sh
|
||||
- scripts/validate_migration_timestamps
|
||||
|
||||
db:check-schema:
|
||||
extends:
|
||||
- db:migrate-from-previous-major-version
|
||||
- .db:check-schema-base
|
||||
- .db-job-base
|
||||
- .rails:rules:ee-mr-and-default-branch-only
|
||||
script:
|
||||
- run_timed_command "bundle exec rake db:drop db:create"
|
||||
- run_timed_command "scripts/db_tasks db:migrate"
|
||||
|
||||
db:check-schema-single-db:
|
||||
extends:
|
||||
- db:migrate-from-previous-major-version-single-db
|
||||
- .db:check-schema-base
|
||||
- db:check-schema
|
||||
- .single-db
|
||||
- .rails:rules:single-db
|
||||
|
||||
db:check-migrations:
|
||||
extends:
|
||||
|
|
|
|||
|
|
@ -643,9 +643,8 @@
|
|||
changes: *ci-build-images-patterns
|
||||
- <<: *if-dot-com-gitlab-org-and-security-merge-request
|
||||
changes: *code-qa-patterns
|
||||
- <<: *if-dot-com-gitlab-org-default-branch
|
||||
changes: *code-qa-patterns
|
||||
- <<: *if-tag
|
||||
- <<: *if-auto-deploy-branches
|
||||
- <<: *if-default-branch-or-tag
|
||||
- <<: *if-dot-com-gitlab-org-schedule
|
||||
- <<: *if-force-ci
|
||||
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
3.0.1
|
||||
3.0.2
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ export default {
|
|||
>
|
||||
<gl-daterange-picker
|
||||
v-model="dateRange"
|
||||
class="d-flex flex-column flex-lg-row"
|
||||
class="gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row"
|
||||
:default-start-date="startDate"
|
||||
:default-end-date="endDate"
|
||||
:default-min-date="minDate"
|
||||
|
|
@ -93,7 +93,7 @@ export default {
|
|||
:tooltip="maxDateRangeTooltip"
|
||||
theme="animate-picker"
|
||||
start-picker-class="js-daterange-picker-from gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-lg-align-items-center gl-lg-mr-3 gl-mb-2 gl-lg-mb-0"
|
||||
end-picker-class="js-daterange-picker-to d-flex flex-column flex-lg-row align-items-lg-center gl-mb-2 gl-lg-mb-0"
|
||||
end-picker-class="js-daterange-picker-to gl-display-flex gl-flex-direction-column gl-lg-flex-direction-row gl-lg-align-items-center gl-mb-2 gl-lg-mb-0"
|
||||
label-class="gl-mb-2 gl-lg-mb-0"
|
||||
>
|
||||
<gl-sprintf :message="n__('1 day selected', '%d days selected', numberOfDays)">
|
||||
|
|
|
|||
|
|
@ -3,13 +3,7 @@ import { Plugin, PluginKey } from 'prosemirror-state';
|
|||
import { __ } from '~/locale';
|
||||
import { VARIANT_DANGER } from '~/flash';
|
||||
import createMarkdownDeserializer from '../services/gl_api_markdown_deserializer';
|
||||
import {
|
||||
ALERT_EVENT,
|
||||
LOADING_CONTENT_EVENT,
|
||||
LOADING_SUCCESS_EVENT,
|
||||
LOADING_ERROR_EVENT,
|
||||
EXTENSION_PRIORITY_HIGHEST,
|
||||
} from '../constants';
|
||||
import { ALERT_EVENT, EXTENSION_PRIORITY_HIGHEST } from '../constants';
|
||||
import CodeBlockHighlight from './code_block_highlight';
|
||||
import Diagram from './diagram';
|
||||
import Frontmatter from './frontmatter';
|
||||
|
|
@ -34,10 +28,8 @@ export default Extension.create({
|
|||
const { renderMarkdown, eventHub } = options;
|
||||
const deserializer = createMarkdownDeserializer({ render: renderMarkdown });
|
||||
|
||||
eventHub.$emit(LOADING_CONTENT_EVENT);
|
||||
|
||||
deserializer
|
||||
.deserialize({ schema: editor.schema, content: markdown })
|
||||
.deserialize({ schema: editor.schema, markdown })
|
||||
.then(({ document }) => {
|
||||
if (!document) {
|
||||
return;
|
||||
|
|
@ -48,14 +40,12 @@ export default Extension.create({
|
|||
|
||||
tr.replaceWith(selection.from - 1, selection.to, document.content);
|
||||
view.dispatch(tr);
|
||||
eventHub.$emit(LOADING_SUCCESS_EVENT);
|
||||
})
|
||||
.catch(() => {
|
||||
eventHub.$emit(ALERT_EVENT, {
|
||||
message: __('An error occurred while pasting text in the editor. Please try again.'),
|
||||
variant: VARIANT_DANGER,
|
||||
});
|
||||
eventHub.$emit(LOADING_ERROR_EVENT);
|
||||
});
|
||||
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ export const createContentEditor = ({
|
|||
MathInline,
|
||||
OrderedList,
|
||||
Paragraph,
|
||||
PasteMarkdown,
|
||||
PasteMarkdown.configure({ eventHub, renderMarkdown }),
|
||||
Reference,
|
||||
ReferenceDefinition,
|
||||
Sourcemap,
|
||||
|
|
|
|||
|
|
@ -246,9 +246,7 @@ export default {
|
|||
</p>
|
||||
<p class="gl-m-0">
|
||||
<span data-testid="vsa-stage-event-build-author-and-date">
|
||||
<gl-link class="gl-text-black-normal build-date" :href="item.url">{{
|
||||
item.date
|
||||
}}</gl-link>
|
||||
<gl-link class="gl-text-black-normal" :href="item.url">{{ item.date }}</gl-link>
|
||||
{{ s__('ByAuthor|by') }}
|
||||
<gl-link
|
||||
class="gl-text-black-normal issue-author-link"
|
||||
|
|
|
|||
|
|
@ -52,7 +52,7 @@ export default {
|
|||
};
|
||||
</script>
|
||||
<template>
|
||||
<span class="total-time">
|
||||
<span>
|
||||
<template v-if="hasData">
|
||||
{{ calculatedTime.duration }} <span>{{ calculatedTime.units }}</span>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ export default {
|
|||
params: { id: filename },
|
||||
query: $route.query,
|
||||
}"
|
||||
class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
|
||||
class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new gl-mb-0"
|
||||
>
|
||||
<div
|
||||
class="card-body gl-p-0 gl-display-flex gl-align-items-center gl-justify-content-center gl-overflow-hidden gl-relative"
|
||||
|
|
|
|||
|
|
@ -135,7 +135,7 @@ export default {
|
|||
designDropzoneWrapperClass() {
|
||||
return this.isDesignListEmpty
|
||||
? 'col-12'
|
||||
: 'gl-flex-direction-column col-md-6 col-lg-3 gl-mb-3';
|
||||
: 'gl-flex-direction-column col-md-6 col-lg-3 gl-mt-5';
|
||||
},
|
||||
},
|
||||
mounted() {
|
||||
|
|
@ -364,15 +364,15 @@ export default {
|
|||
data-testid="design-toolbar-wrapper"
|
||||
>
|
||||
<div
|
||||
class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-w-full gl-flex-wrap"
|
||||
class="gl-display-flex gl-justify-content-space-between gl-align-items-center gl-w-full gl-flex-wrap gl-gap-3"
|
||||
>
|
||||
<div class="gl-display-flex gl-align-items-center gl-my-2">
|
||||
<div class="gl-display-flex gl-align-items-center">
|
||||
<span class="gl-font-weight-bold gl-mr-3">{{ s__('DesignManagement|Designs') }}</span>
|
||||
<design-version-dropdown />
|
||||
</div>
|
||||
<div
|
||||
v-show="hasDesigns"
|
||||
class="gl-display-flex gl-align-items-center gl-my-2"
|
||||
class="gl-display-flex gl-align-items-center"
|
||||
data-testid="design-selector-toolbar"
|
||||
>
|
||||
<gl-button
|
||||
|
|
@ -413,7 +413,7 @@ export default {
|
|||
</div>
|
||||
</div>
|
||||
</header>
|
||||
<div class="gl-mt-6">
|
||||
<div>
|
||||
<gl-loading-icon v-if="isLoading" size="lg" />
|
||||
<gl-alert v-else-if="error" variant="danger" :dismissible="false">
|
||||
{{ __('An error occurred while loading designs. Please try again.') }}
|
||||
|
|
@ -449,7 +449,7 @@ export default {
|
|||
<li
|
||||
v-for="design in designs"
|
||||
:key="design.id"
|
||||
class="col-md-6 col-lg-3 gl-mb-3 gl-bg-transparent gl-shadow-none js-design-tile"
|
||||
class="col-md-6 col-lg-3 gl-mt-5 gl-bg-transparent gl-shadow-none js-design-tile"
|
||||
>
|
||||
<design-dropzone
|
||||
:display-as-card="hasDesigns"
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ import { escape } from 'lodash';
|
|||
export default (input, parameters, escapeParameters = true) => {
|
||||
let output = input;
|
||||
|
||||
output = output.replace(/%+/g, '%');
|
||||
|
||||
if (parameters) {
|
||||
const mappedParameters = new Map(Object.entries(parameters));
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1 @@
|
|||
import initForm from '../form';
|
||||
|
||||
initForm();
|
||||
import '../show/index';
|
||||
|
|
|
|||
|
|
@ -13,9 +13,10 @@ import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
|||
import WebIdeLink from '~/vue_shared/components/web_ide_link.vue';
|
||||
import CodeIntelligence from '~/code_navigation/components/app.vue';
|
||||
import LineHighlighter from '~/blob/line_highlighter';
|
||||
import blobInfoQuery from 'shared_queries/repository/blob_info.query.graphql';
|
||||
import addBlameLink from '~/blob/blob_blame_link';
|
||||
import projectInfoQuery from '../queries/project_info.query.graphql';
|
||||
import getRefMixin from '../mixins/get_ref';
|
||||
import blobInfoQuery from '../queries/blob_info.query.graphql';
|
||||
import userInfoQuery from '../queries/user_info.query.graphql';
|
||||
import applicationInfoQuery from '../queries/application_info.query.graphql';
|
||||
import { DEFAULT_BLOB_INFO, TEXT_FILE_TYPE, LFS_STORAGE, LEGACY_FILE_TYPES } from '../constants';
|
||||
|
|
@ -41,6 +42,21 @@ export default {
|
|||
},
|
||||
},
|
||||
apollo: {
|
||||
projectInfo: {
|
||||
query: projectInfoQuery,
|
||||
variables() {
|
||||
return {
|
||||
projectPath: this.projectPath,
|
||||
};
|
||||
},
|
||||
error() {
|
||||
this.displayError();
|
||||
},
|
||||
update({ project }) {
|
||||
this.pathLocks = project.pathLocks || DEFAULT_BLOB_INFO.pathLocks;
|
||||
this.userPermissions = project.userPermissions;
|
||||
},
|
||||
},
|
||||
gitpodEnabled: {
|
||||
query: applicationInfoQuery,
|
||||
error() {
|
||||
|
|
@ -121,6 +137,8 @@ export default {
|
|||
gitpodEnabled: DEFAULT_BLOB_INFO.gitpodEnabled,
|
||||
currentUser: DEFAULT_BLOB_INFO.currentUser,
|
||||
useFallback: false,
|
||||
pathLocks: DEFAULT_BLOB_INFO.pathLocks,
|
||||
userPermissions: DEFAULT_BLOB_INFO.userPermissions,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
|
|
@ -163,7 +181,7 @@ export default {
|
|||
);
|
||||
},
|
||||
canLock() {
|
||||
const { pushCode, downloadCode } = this.project.userPermissions;
|
||||
const { pushCode, downloadCode } = this.userPermissions;
|
||||
const currentUsername = window.gon?.current_username;
|
||||
|
||||
if (this.pathLockedByUser && this.pathLockedByUser.username !== currentUsername) {
|
||||
|
|
@ -173,12 +191,12 @@ export default {
|
|||
return pushCode && downloadCode;
|
||||
},
|
||||
pathLockedByUser() {
|
||||
const pathLock = this.project?.pathLocks?.nodes.find((node) => node.path === this.path);
|
||||
const pathLock = this.pathLocks?.nodes.find((node) => node.path === this.path);
|
||||
|
||||
return pathLock ? pathLock.user : null;
|
||||
},
|
||||
showForkSuggestion() {
|
||||
const { createMergeRequestIn, forkProject } = this.project.userPermissions;
|
||||
const { createMergeRequestIn, forkProject } = this.userPermissions;
|
||||
const { canModifyBlob } = this.blobInfo;
|
||||
|
||||
return this.isLoggedIn && !canModifyBlob && createMergeRequestIn && forkProject;
|
||||
|
|
@ -338,7 +356,7 @@ export default {
|
|||
:name="blobInfo.name"
|
||||
:replace-path="blobInfo.replacePath"
|
||||
:delete-path="blobInfo.webPath"
|
||||
:can-push-code="project.userPermissions.pushCode"
|
||||
:can-push-code="userPermissions.pushCode"
|
||||
:can-push-to-branch="blobInfo.canCurrentUserPushToBranch"
|
||||
:empty-repo="project.repository.empty"
|
||||
:project-path="projectPath"
|
||||
|
|
|
|||
|
|
@ -17,8 +17,8 @@ import { TREE_PAGE_SIZE, ROW_APPEAR_DELAY } from '~/repository/constants';
|
|||
import FileIcon from '~/vue_shared/components/file_icon.vue';
|
||||
import TimeagoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
|
||||
import glFeatureFlagMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import blobInfoQuery from 'shared_queries/repository/blob_info.query.graphql';
|
||||
import getRefMixin from '../../mixins/get_ref';
|
||||
import blobInfoQuery from '../../queries/blob_info.query.graphql';
|
||||
import commitQuery from '../../queries/commit.query.graphql';
|
||||
|
||||
export default {
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
#import "ee_else_ce/repository/queries/path_locks.fragment.graphql"
|
||||
|
||||
query getProjectInfo($projectPath: ID!) {
|
||||
project(fullPath: $projectPath) {
|
||||
id
|
||||
userPermissions {
|
||||
pushCode
|
||||
downloadCode
|
||||
createMergeRequestIn
|
||||
forkProject
|
||||
}
|
||||
...ProjectPathLocksFragment
|
||||
}
|
||||
}
|
||||
|
|
@ -149,7 +149,7 @@ export default {
|
|||
>
|
||||
<slot>
|
||||
<button
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
|
||||
type="button"
|
||||
@click="openFileUpload"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -97,6 +97,15 @@ export default {
|
|||
error() {
|
||||
this.error = this.$options.i18n.fetchError;
|
||||
},
|
||||
result() {
|
||||
if (!this.isModal) {
|
||||
const path = this.workItem.project?.fullPath
|
||||
? ` · ${this.workItem.project.fullPath}`
|
||||
: '';
|
||||
|
||||
document.title = `${this.workItem.title} · ${this.workItem?.workItemType?.name}${path}`;
|
||||
}
|
||||
},
|
||||
subscribeToMore: {
|
||||
document: workItemTitleSubscription,
|
||||
variables() {
|
||||
|
|
|
|||
|
|
@ -1,5 +1,3 @@
|
|||
#import "ee_else_ce/repository/queries/path_locks.fragment.graphql"
|
||||
|
||||
query getBlobInfo(
|
||||
$projectPath: ID!
|
||||
$filePath: String!
|
||||
|
|
@ -7,17 +5,15 @@ query getBlobInfo(
|
|||
$shouldFetchRawText: Boolean!
|
||||
) {
|
||||
project(fullPath: $projectPath) {
|
||||
userPermissions {
|
||||
pushCode
|
||||
downloadCode
|
||||
createMergeRequestIn
|
||||
forkProject
|
||||
}
|
||||
...ProjectPathLocksFragment
|
||||
__typename
|
||||
id
|
||||
repository {
|
||||
__typename
|
||||
empty
|
||||
blobs(paths: [$filePath], ref: $ref) {
|
||||
__typename
|
||||
nodes {
|
||||
__typename
|
||||
id
|
||||
webPath
|
||||
name
|
||||
|
|
@ -65,7 +65,7 @@ class NotifyPreview < ActionMailer::Preview
|
|||
end
|
||||
|
||||
def new_mention_in_merge_request_email
|
||||
Notify.new_mention_in_merge_request_email(user.id, issue.id, user.id).message
|
||||
Notify.new_mention_in_merge_request_email(user.id, merge_request.id, user.id).message
|
||||
end
|
||||
|
||||
def closed_issue_email
|
||||
|
|
@ -101,7 +101,7 @@ class NotifyPreview < ActionMailer::Preview
|
|||
end
|
||||
|
||||
def closed_merge_request_email
|
||||
Notify.closed_merge_request_email(user.id, issue.id, user.id).message
|
||||
Notify.closed_merge_request_email(user.id, merge_request.id, user.id).message
|
||||
end
|
||||
|
||||
def merge_request_status_email
|
||||
|
|
@ -209,14 +209,6 @@ class NotifyPreview < ActionMailer::Preview
|
|||
Notify.inactive_project_deletion_warning_email(project, user, '2022-04-22').message
|
||||
end
|
||||
|
||||
def user_auto_banned_instance_email
|
||||
::Notify.user_auto_banned_email(user.id, user.id, max_project_downloads: 5, within_seconds: 600).message
|
||||
end
|
||||
|
||||
def user_auto_banned_namespace_email
|
||||
::Notify.user_auto_banned_email(user.id, user.id, max_project_downloads: 5, within_seconds: 600, group: group).message
|
||||
end
|
||||
|
||||
def verification_instructions_email
|
||||
Notify.verification_instructions_email(user.id, token: '123456', expires_in: 60).message
|
||||
end
|
||||
|
|
@ -224,7 +216,7 @@ class NotifyPreview < ActionMailer::Preview
|
|||
private
|
||||
|
||||
def project
|
||||
@project ||= Project.find_by_full_path('gitlab-org/gitlab-test')
|
||||
@project ||= Project.first
|
||||
end
|
||||
|
||||
def issue
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
|
||||
module Ci
|
||||
class JobArtifact < Ci::ApplicationRecord
|
||||
include Ci::Partitionable
|
||||
include IgnorableColumns
|
||||
include AfterCommitQueue
|
||||
include ObjectStorage::BackgroundMove
|
||||
|
|
@ -134,14 +135,16 @@ module Ci
|
|||
|
||||
mount_file_store_uploader JobArtifactUploader, skip_store_file: true
|
||||
|
||||
before_save :set_size, if: :file_changed?
|
||||
after_save :store_file_in_transaction!, unless: :store_after_commit?
|
||||
after_commit :store_file_after_transaction!, on: [:create, :update], if: :store_after_commit?
|
||||
|
||||
validates :job, presence: true
|
||||
validates :file_format, presence: true, unless: :trace?, on: :create
|
||||
validate :validate_file_format!, unless: :trace?, on: :create
|
||||
before_save :set_size, if: :file_changed?
|
||||
|
||||
update_project_statistics project_statistics_name: :build_artifacts_size
|
||||
partitionable scope: :job
|
||||
|
||||
scope :not_expired, -> { where('expire_at IS NULL OR expire_at > ?', Time.current) }
|
||||
scope :for_sha, ->(sha, project_id) { joins(job: :pipeline).where(ci_pipelines: { sha: sha, project_id: project_id }) }
|
||||
|
|
|
|||
|
|
@ -0,0 +1,42 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Ci
|
||||
##
|
||||
# This module implements a way to set the `partion_id` value on a dependent
|
||||
# resource from a parent record.
|
||||
# Usage:
|
||||
#
|
||||
# class PipelineVariable < Ci::ApplicationRecord
|
||||
# include Ci::Partitionable
|
||||
#
|
||||
# belongs_to :pipeline
|
||||
# partitionable scope: :pipeline
|
||||
#
|
||||
module Partitionable
|
||||
extend ActiveSupport::Concern
|
||||
include ::Gitlab::Utils::StrongMemoize
|
||||
|
||||
included do
|
||||
before_validation :set_partition_id, on: :create
|
||||
validates :partition_id, presence: true
|
||||
|
||||
def set_partition_id
|
||||
return unless partition_scope_record
|
||||
|
||||
self.partition_id = partition_scope_record.partition_id
|
||||
end
|
||||
end
|
||||
|
||||
class_methods do
|
||||
private
|
||||
|
||||
def partitionable(scope:)
|
||||
define_method(:partition_scope_record) do
|
||||
strong_memoize(:partition_scope_record) do
|
||||
scope.to_proc.call(self)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -80,7 +80,7 @@ module Ci
|
|||
Gitlab::CurrentSettings.current_application_settings.default_artifacts_expire_in
|
||||
|
||||
artifact_attributes = {
|
||||
job_id: job.id,
|
||||
job: job,
|
||||
project: project,
|
||||
expire_in: expire_in
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
- signatures_path = namespace_project_signatures_path(namespace_id: @project.namespace.full_path, project_id: @project.path, id: @last_commit, limit: 1)
|
||||
- content_for :prefetch_asset_tags do
|
||||
- webpack_preload_asset_tag('monaco', prefetch: true)
|
||||
- add_page_startup_graphql_call('repository/blob_info', { projectPath: @project.full_path, ref: current_ref, filePath: @blob.path, shouldFetchRawText: @blob.rendered_as_text? && !@blob.rich_viewer })
|
||||
|
||||
.js-signature-container{ data: { 'signatures-path': signatures_path } }
|
||||
|
||||
|
|
|
|||
|
|
@ -43,7 +43,8 @@
|
|||
- if milestone.merge_requests_enabled?
|
||||
·
|
||||
= link_to pluralize(milestone.total_merge_requests_count, _('Merge request')), merge_requests_path
|
||||
.float-lg-right.light #{milestone.percent_complete}% complete
|
||||
.float-lg-right.light
|
||||
= format(s_('Milestone|%{percentage}%{percent} complete'), percentage: milestone.percent_complete, percent: '%')
|
||||
.col-md-2
|
||||
.milestone-actions.d-flex.justify-content-sm-start.justify-content-md-end
|
||||
- if @project # if in milestones list on project level
|
||||
|
|
|
|||
|
|
@ -63,7 +63,7 @@ Rails.application.configure do
|
|||
config.action_mailer.raise_delivery_errors = true
|
||||
# Don't make a mess when bootstrapping a development environment
|
||||
config.action_mailer.perform_deliveries = (ENV['BOOTSTRAP'] != '1')
|
||||
config.action_mailer.preview_path = "#{Rails.root}{/ee,}/app/mailers/previews"
|
||||
config.action_mailer.preview_path = GitlabEdition.path_glob('app/mailers/previews')
|
||||
|
||||
config.eager_load = false
|
||||
|
||||
|
|
|
|||
|
|
@ -48,6 +48,8 @@ Rails.application.configure do
|
|||
# ActionMailer::Base.deliveries array.
|
||||
config.action_mailer.delivery_method = :test
|
||||
|
||||
config.action_mailer.preview_path = GitlabEdition.path_glob('app/mailers/previews')
|
||||
|
||||
# Print deprecation notices to the stderr
|
||||
config.active_support.deprecation = :stderr
|
||||
|
||||
|
|
|
|||
|
|
@ -118,6 +118,12 @@
|
|||
- 'i_code_review_merge_request_widget_status_checks_expand_failed'
|
||||
- 'i_code_review_submit_review_approve'
|
||||
- 'i_code_review_submit_review_comment'
|
||||
- 'i_code_review_merge_request_widget_license_compliance_view'
|
||||
- 'i_code_review_merge_request_widget_license_compliance_full_report_clicked'
|
||||
- 'i_code_review_merge_request_widget_license_compliance_expand'
|
||||
- 'i_code_review_merge_request_widget_license_compliance_expand_success'
|
||||
- 'i_code_review_merge_request_widget_license_compliance_expand_warning'
|
||||
- 'i_code_review_merge_request_widget_license_compliance_expand_failed'
|
||||
- name: code_review_category_monthly_active_users
|
||||
operator: OR
|
||||
source: redis
|
||||
|
|
@ -224,6 +230,12 @@
|
|||
- 'i_code_review_merge_request_widget_status_checks_expand_failed'
|
||||
- 'i_code_review_submit_review_approve'
|
||||
- 'i_code_review_submit_review_comment'
|
||||
- 'i_code_review_merge_request_widget_license_compliance_view'
|
||||
- 'i_code_review_merge_request_widget_license_compliance_full_report_clicked'
|
||||
- 'i_code_review_merge_request_widget_license_compliance_expand'
|
||||
- 'i_code_review_merge_request_widget_license_compliance_expand_success'
|
||||
- 'i_code_review_merge_request_widget_license_compliance_expand_warning'
|
||||
- 'i_code_review_merge_request_widget_license_compliance_expand_failed'
|
||||
- name: code_review_extension_category_monthly_active_users
|
||||
operator: OR
|
||||
source: redis
|
||||
|
|
|
|||
|
|
@ -66,6 +66,12 @@ options:
|
|||
- i_code_review_merge_request_widget_test_summary_expand_warning
|
||||
- i_code_review_merge_request_widget_test_summary_full_report_clicked
|
||||
- i_code_review_merge_request_widget_test_summary_view
|
||||
- i_code_review_merge_request_widget_license_compliance_expand
|
||||
- i_code_review_merge_request_widget_license_compliance_expand_failed
|
||||
- i_code_review_merge_request_widget_license_compliance_expand_success
|
||||
- i_code_review_merge_request_widget_license_compliance_warning
|
||||
- i_code_review_merge_request_widget_license_compliance_full_report_clicked
|
||||
- i_code_review_merge_request_widget_license_compliance_view
|
||||
- i_code_review_mr_diffs
|
||||
- i_code_review_mr_single_file_diffs
|
||||
- i_code_review_mr_with_invalid_approvers
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ options:
|
|||
- p_ci_templates_security_dast_api
|
||||
- p_ci_templates_security_dast_api_latest
|
||||
- p_ci_templates_security_container_scanning
|
||||
- p_ci_templates_security_container_scanning_latest
|
||||
- p_ci_templates_security_dast_latest
|
||||
- p_ci_templates_security_dependency_scanning
|
||||
- p_ci_templates_security_api_fuzzing
|
||||
|
|
@ -94,7 +95,9 @@ options:
|
|||
- p_ci_templates_jobs_code_intelligence
|
||||
- p_ci_templates_jobs_code_quality
|
||||
- p_ci_templates_jobs_dependency_scanning
|
||||
- p_ci_templates_jobs_dependency_scanning_latest
|
||||
- p_ci_templates_jobs_license_scanning
|
||||
- p_ci_templates_jobs_license_scanning_latest
|
||||
- p_ci_templates_jobs_deploy_ecs
|
||||
- p_ci_templates_jobs_deploy_ec2
|
||||
- p_ci_templates_jobs_deploy
|
||||
|
|
@ -140,7 +143,9 @@ options:
|
|||
- p_ci_templates_implicit_jobs_code_intelligence
|
||||
- p_ci_templates_implicit_jobs_code_quality
|
||||
- p_ci_templates_implicit_jobs_dependency_scanning
|
||||
- p_ci_templates_implicit_jobs_dependency_scanning_latest
|
||||
- p_ci_templates_implicit_jobs_license_scanning
|
||||
- p_ci_templates_implicit_jobs_license_scanning_latest
|
||||
- p_ci_templates_implicit_jobs_deploy_ecs
|
||||
- p_ci_templates_implicit_jobs_deploy_ec2
|
||||
- p_ci_templates_implicit_auto_devops_deploy
|
||||
|
|
@ -163,6 +168,7 @@ options:
|
|||
- p_ci_templates_implicit_security_dast_api
|
||||
- p_ci_templates_implicit_security_dast_api_latest
|
||||
- p_ci_templates_implicit_security_container_scanning
|
||||
- p_ci_templates_implicit_security_container_scanning_latest
|
||||
- p_ci_templates_implicit_security_dast_latest
|
||||
- p_ci_templates_implicit_security_dependency_scanning
|
||||
- p_ci_templates_implicit_security_api_fuzzing
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_license_compliance_view_monthly
|
||||
description: The count of unique users (monthly) who were able to see the License Compliance widget extension
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_view
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_license_compliance_full_report_clicked_monthly
|
||||
description: The count of unique users (monthly) who clicked the Full Report button on the License Compliance widget extension
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_full_report_clicked
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_license_compliance_expand_monthly
|
||||
description: The count of unique users (monthly) who expanded the License Compliance widget extension
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_expand
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_license_compliance_expand_success_monthly
|
||||
description: The count of unique users (monthly) who expanded the License Compliance widget extension while it is in its Success state
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_expand_success
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_license_compliance_expand_warning_monthly
|
||||
description: The count of unique users (monthly) who expanded the License Compliance widget extension while it is in its Warning state
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_expand_warning
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_license_compliance_expand_failed_monthly
|
||||
description: The count of unique users (monthly) who expanded the License Compliance widget extension while it is in its Failed state
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_expand_failed
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_dependency_scanning_latest_monthly
|
||||
description: Monthly counts for Dependency Scanning CI Latest template (Jobs folder)
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: composition_analysis
|
||||
product_category: dependency_scanning
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_jobs_dependency_scanning_latest
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_security_container_scanning_latest_monthly
|
||||
description: Monthly counts for Container Scanning CI Latest template (Security folder)
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: composition_analysis
|
||||
product_category: container_scanning
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_security_container_scanning_latest
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_license_scanning_latest_monthly
|
||||
description: Monthly counts for License Scanning CI Latest template (Jobs folder)
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: composition_analysis
|
||||
product_category: license_scanning
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_jobs_license_scanning_latest
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_dependency_scanning_latest_monthly
|
||||
description: Monthly counts for implicit Dependency Scanning CI Latest template (Jobs folder)
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: composition_analysis
|
||||
product_category: dependency_scanning
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_implicit_jobs_dependency_scanning_latest
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_license_scanning_latest_monthly
|
||||
description: Monthly counts for implicit License Scanning CI Latest template (Jobs folder)
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: composition_analysis
|
||||
product_category: license_scanning
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_implicit_jobs_license_scanning_latest
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_container_scanning_latest_monthly
|
||||
description: Monthly counts for implicit Container Scanning CI Latest template (Security folder)
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: composition_analysis
|
||||
product_category: container_scanning
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
|
||||
time_frame: 28d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_implicit_security_container_scanning_latest
|
||||
|
|
@ -66,6 +66,12 @@ options:
|
|||
- i_code_review_merge_request_widget_test_summary_expand_warning
|
||||
- i_code_review_merge_request_widget_test_summary_full_report_clicked
|
||||
- i_code_review_merge_request_widget_test_summary_view
|
||||
- i_code_review_merge_request_widget_license_compliance_expand
|
||||
- i_code_review_merge_request_widget_license_compliance_expand_failed
|
||||
- i_code_review_merge_request_widget_license_compliance_expand_success
|
||||
- i_code_review_merge_request_widget_license_compliance_warning
|
||||
- i_code_review_merge_request_widget_license_compliance_full_report_clicked
|
||||
- i_code_review_merge_request_widget_license_compliance_view
|
||||
- i_code_review_mr_diffs
|
||||
- i_code_review_mr_single_file_diffs
|
||||
- i_code_review_mr_with_invalid_approvers
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ options:
|
|||
- p_ci_templates_security_dast_api
|
||||
- p_ci_templates_security_dast_api_latest
|
||||
- p_ci_templates_security_container_scanning
|
||||
- p_ci_templates_security_container_scanning_latest
|
||||
- p_ci_templates_security_dast_latest
|
||||
- p_ci_templates_security_dependency_scanning
|
||||
- p_ci_templates_security_api_fuzzing
|
||||
|
|
@ -94,7 +95,9 @@ options:
|
|||
- p_ci_templates_jobs_code_intelligence
|
||||
- p_ci_templates_jobs_code_quality
|
||||
- p_ci_templates_jobs_dependency_scanning
|
||||
- p_ci_templates_jobs_dependency_scanning_latest
|
||||
- p_ci_templates_jobs_license_scanning
|
||||
- p_ci_templates_jobs_license_scanning_latest
|
||||
- p_ci_templates_jobs_deploy_ecs
|
||||
- p_ci_templates_jobs_deploy_ec2
|
||||
- p_ci_templates_jobs_deploy
|
||||
|
|
|
|||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_license_compliance_view_weekly
|
||||
description: The count of unique users (weekly) who were able to see the License Compliance widget extension
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_view
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_license_compliance_full_report_clicked_weekly
|
||||
description: The count of unique users (weekly) who clicked the Full Report button on the License Compliance widget extension
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_full_report_clicked
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_license_compliance_expand_weekly
|
||||
description: The count of unique users (weekly) who expanded the License Compliance widget extension
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_expand
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_license_compliance_expand_success_weekly
|
||||
description: The count of unique users (weekly) who expanded the License Compliance widget extension while it is in its Success state
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_expand_success
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_license_compliance_expand_warning_weekly
|
||||
description: The count of unique users (weekly) who expanded the License Compliance widget extension while it is in its Warning state
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_expand_warning
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.code_review.i_code_review_merge_request_widget_license_compliance_expand_failed_weekly
|
||||
description: The count of unique users (weekly) who expanded the License Compliance widget extension while it is in its Failed state
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_expand_failed
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_dependency_scanning_latest_weekly
|
||||
description: Weekly counts for Dependency Scanning CI Latest template (Jobs folder)
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: composition_analysis
|
||||
product_category: dependency_scanning
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_jobs_dependency_scanning_latest
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_security_container_scanning_latest_weekly
|
||||
description: Weekly counts for Container Scanning CI Latest template (Security folder)
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: composition_analysis
|
||||
product_category: container_scanning
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_security_container_scanning_latest
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_license_scanning_latest_weekly
|
||||
description: Weekly counts for License Scanning CI Latest template (Jobs folder)
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: composition_analysis
|
||||
product_category: license_scanning
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_jobs_license_scanning_latest
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_dependency_scanning_latest_weekly
|
||||
description: Weekly counts for implicit Dependency Scanning CI Latest template (Jobs folder)
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: composition_analysis
|
||||
product_category: dependency_scanning
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_implicit_jobs_dependency_scanning_latest
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_license_scanning_latest_weekly
|
||||
description: Weekly counts for implicit License Scanning CI Latest template (Jobs folder)
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: composition_analysis
|
||||
product_category: license_scanning
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_implicit_jobs_license_scanning_latest
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
---
|
||||
key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_security_container_scanning_latest_weekly
|
||||
description: Weekly counts for implicit Container Scanning CI Latest template (Security folder)
|
||||
product_section: sec
|
||||
product_stage: secure
|
||||
product_group: composition_analysis
|
||||
product_category: container_scanning
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: 'https://gitlab.com/gitlab-org/gitlab/-/merge_requests/97323'
|
||||
time_frame: 7d
|
||||
data_source: redis_hll
|
||||
data_category: optional
|
||||
instrumentation_class: RedisHLLMetric
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
options:
|
||||
events:
|
||||
- p_ci_templates_implicit_security_container_scanning_latest
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: counts.i_code_review_merge_request_widget_license_compliance_count_view
|
||||
description: Total number of times the License Compliance widget extension was viewed (rendered to the screen)
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: all
|
||||
data_source: redis
|
||||
data_category: optional
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_count_view
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: counts.i_code_review_merge_request_widget_license_compliance_count_full_report_clicked
|
||||
description: Total number of times the License Compliance widget extension Full Report button was clicked
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: all
|
||||
data_source: redis
|
||||
data_category: optional
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_count_full_report_clicked
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: counts.i_code_review_merge_request_widget_license_compliance_count_expand
|
||||
description: Total number of times the License Compliance widget extension was expanded (in any state)
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: all
|
||||
data_source: redis
|
||||
data_category: optional
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_count_expand
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: counts.i_code_review_merge_request_widget_license_compliance_count_expand_success
|
||||
description: Total number of times the License Compliance widget extension was expanded (while in its Success state)
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: all
|
||||
data_source: redis
|
||||
data_category: optional
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_count_expand_success
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: counts.i_code_review_merge_request_widget_license_compliance_count_expand_warning
|
||||
description: Total number of times the License Compliance widget extension was expanded (while in its Warning state)
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: all
|
||||
data_source: redis
|
||||
data_category: optional
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_count_expand_warning
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
---
|
||||
key_path: counts.i_code_review_merge_request_widget_license_compliance_count_expand_failed
|
||||
description: Total number of times the License Compliance widget extension was expanded (while in its Failed state)
|
||||
product_section: dev
|
||||
product_stage: create
|
||||
product_group: code_review
|
||||
product_category: code_review
|
||||
value_type: number
|
||||
status: active
|
||||
milestone: "15.4"
|
||||
introduced_by_url: "https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96538"
|
||||
time_frame: all
|
||||
data_source: redis
|
||||
data_category: optional
|
||||
options:
|
||||
events:
|
||||
- i_code_review_merge_request_widget_license_compliance_count_expand_failed
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
tier:
|
||||
- free
|
||||
- premium
|
||||
- ultimate
|
||||
|
|
@ -9909,6 +9909,7 @@ Represents an epic on an issue board.
|
|||
| <a id="boardepiccolor"></a>`color` | [`String`](#string) | Color of the epic. Returns `null` if `epic_color_highlight` feature flag is disabled. |
|
||||
| <a id="boardepicconfidential"></a>`confidential` | [`Boolean`](#boolean) | Indicates if the epic is confidential. |
|
||||
| <a id="boardepiccreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp of when the epic was created. |
|
||||
| <a id="boardepicdefaultprojectforissuecreation"></a>`defaultProjectForIssueCreation` | [`Project`](#project) | Default Project for issue creation. Based on the project the user created the last issue in. |
|
||||
| <a id="boardepicdescendantcounts"></a>`descendantCounts` | [`EpicDescendantCount`](#epicdescendantcount) | Number of open and closed descendant epics and issues. |
|
||||
| <a id="boardepicdescendantweightsum"></a>`descendantWeightSum` | [`EpicDescendantWeights`](#epicdescendantweights) | Total weight of open and closed issues in the epic and its descendants. |
|
||||
| <a id="boardepicdescription"></a>`description` | [`String`](#string) | Description of the epic. |
|
||||
|
|
@ -11734,6 +11735,7 @@ Represents an epic.
|
|||
| <a id="epiccolor"></a>`color` | [`String`](#string) | Color of the epic. Returns `null` if `epic_color_highlight` feature flag is disabled. |
|
||||
| <a id="epicconfidential"></a>`confidential` | [`Boolean`](#boolean) | Indicates if the epic is confidential. |
|
||||
| <a id="epiccreatedat"></a>`createdAt` | [`Time`](#time) | Timestamp of when the epic was created. |
|
||||
| <a id="epicdefaultprojectforissuecreation"></a>`defaultProjectForIssueCreation` | [`Project`](#project) | Default Project for issue creation. Based on the project the user created the last issue in. |
|
||||
| <a id="epicdescendantcounts"></a>`descendantCounts` | [`EpicDescendantCount`](#epicdescendantcount) | Number of open and closed descendant epics and issues. |
|
||||
| <a id="epicdescendantweightsum"></a>`descendantWeightSum` | [`EpicDescendantWeights`](#epicdescendantweights) | Total weight of open and closed issues in the epic and its descendants. |
|
||||
| <a id="epicdescription"></a>`description` | [`String`](#string) | Description of the epic. |
|
||||
|
|
|
|||
|
|
@ -0,0 +1,67 @@
|
|||
---
|
||||
stage: Analyze
|
||||
group: Product Analytics
|
||||
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
|
||||
---
|
||||
|
||||
# Product analytics API
|
||||
|
||||
> Introduced in GitLab 15.4 [with a flag](../administration/feature_flags.md) named `cube_api_proxy`. Disabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available per project or for your entire instance, ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `cube_api_proxy`.
|
||||
On GitLab.com, this feature is not available.
|
||||
This feature is not ready for production use.
|
||||
|
||||
NOTE:
|
||||
Make sure to define the `cube_api_base_url` and `cube_api_key` application settings first using [the API](settings.md).
|
||||
|
||||
## Send request to Cube
|
||||
|
||||
Generate an access token that can be used to query the Cube API. For example:
|
||||
|
||||
```plaintext
|
||||
POST /projects/:id/product_analytics/request
|
||||
```
|
||||
|
||||
| Attribute | Type | Required | Description |
|
||||
| --------- |------------------| -------- |---------------------------------------------------------------|
|
||||
| `id` | integer | yes | The ID of a project that the current user has read access to. |
|
||||
|
||||
### Request body
|
||||
|
||||
The body of the request should be a valid Cube query.
|
||||
|
||||
```json
|
||||
{
|
||||
"query": {
|
||||
"measures": [
|
||||
"Jitsu.count"
|
||||
],
|
||||
"timeDimensions": [
|
||||
{
|
||||
"dimension": "Jitsu.utcTime",
|
||||
"dateRange": "This week"
|
||||
}
|
||||
],
|
||||
"order": [
|
||||
[
|
||||
"Jitsu.count",
|
||||
"desc"
|
||||
],
|
||||
[
|
||||
"Jitsu.docPath",
|
||||
"desc"
|
||||
],
|
||||
[
|
||||
"Jitsu.utcTime",
|
||||
"asc"
|
||||
]
|
||||
],
|
||||
"dimensions": [
|
||||
"Jitsu.docPath"
|
||||
],
|
||||
"limit": 23
|
||||
}
|
||||
}
|
||||
```
|
||||
|
|
@ -99,10 +99,14 @@ If you would like to contribute to GitLab:
|
|||
could speed them up.
|
||||
- Consult the [Contribution Flow](#contribution-flow) section to learn the process.
|
||||
|
||||
If you have any questions or need help visit [Getting Help](https://about.gitlab.com/get-help/) to
|
||||
learn how to communicate with GitLab. We have a [Gitter channel for contributors](https://gitter.im/gitlab/contributors),
|
||||
however we favor
|
||||
[asynchronous communication](https://about.gitlab.com/handbook/communication/#internal-communication) over real time communication.
|
||||
### Communication channels
|
||||
|
||||
If you have any questions or need help, visit [Getting Help](https://about.gitlab.com/get-help/) to learn how to
|
||||
communicate with the GitLab community. GitLab prefers [asynchronous communication](https://about.gitlab.com/handbook/communication/#internal-communication) over real-time communication.
|
||||
|
||||
We do encourage you to connect and hang out with us. GitLab has a Gitter room dedicated for [contributors](https://gitter.im/gitlab/contributors), which is bridged with our
|
||||
internal Slack. We actively monitor this channel. There is also a community-run [Discord server](https://discord.gg/S4cwz9sR8u) where you can
|
||||
find other contributors in the `#contributors` channel.
|
||||
|
||||
Thanks for your contribution!
|
||||
|
||||
|
|
|
|||
|
|
@ -24,7 +24,8 @@ When you document feature flags, you must:
|
|||
|
||||
## Add version history text
|
||||
|
||||
When the state of a flag changes (for example, disabled by default to enabled by default), add the change to the version history.
|
||||
When the state of a flag changes (for example, disabled by default to enabled by default), add the change to the
|
||||
[version history](versions.md#add-a-version-history-item).
|
||||
|
||||
Possible version history entries are:
|
||||
|
||||
|
|
|
|||
|
|
@ -69,6 +69,11 @@ If a feature is moved to another subscription tier, use `moved`:
|
|||
> - [Moved](<link-to-issue>) from GitLab Premium to GitLab Free in 12.0.
|
||||
```
|
||||
|
||||
#### Features introduced behind feature flags
|
||||
|
||||
When features are introduced behind feature flags, you must add details about the feature flag to the documentation.
|
||||
For more information, see [Document features deployed behind feature flags](feature_flags.md).
|
||||
|
||||
### Inline version text
|
||||
|
||||
If you're adding content to an existing topic, you can add version information
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ reproduction.
|
|||
|
||||
### Hanging specs
|
||||
|
||||
If a spec hangs, it might be caused by a [bug in Rails](https://github.com/rails/rails/issues/34310):
|
||||
If a spec hangs, it might be caused by a [bug in Rails](https://github.com/rails/rails/issues/45994):
|
||||
|
||||
- <https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81112>
|
||||
- <https://gitlab.com/gitlab-org/gitlab/-/issues/337039>
|
||||
|
|
|
|||
|
|
@ -166,7 +166,7 @@ may need to set the `production -> elasticsearch -> indexer_path` setting in you
|
|||
### View indexing errors
|
||||
|
||||
Errors from the [GitLab Elasticsearch Indexer](https://gitlab.com/gitlab-org/gitlab-elasticsearch-indexer) are reported in
|
||||
the [`sidekiq.log`](../../administration/logs/index.md#sidekiqlog) file with a `json.exception.class` of `Gitlab::Elastic::Indexer::Error`.
|
||||
the [`elasticsearch.log`](../../administration/logs/index.md#elasticsearchlog) file and the [`sidekiq.log`](../../administration/logs/index.md#sidekiqlog) file with a `json.exception.class` of `Gitlab::Elastic::Indexer::Error`.
|
||||
These errors may occur when indexing Git repository data.
|
||||
|
||||
## Enable Advanced Search
|
||||
|
|
|
|||
|
|
@ -1620,6 +1620,15 @@ To render tables with JSON code blocks, use the following syntax:
|
|||
```
|
||||
````
|
||||
|
||||
Watch the following video walkthrough of this feature:
|
||||
|
||||
<div class="video-fallback">
|
||||
See the video: <a href="https://www.youtube.com/watch?v=12yWKw1AdKY">Demo: JSON Tables in Markdown</a>.
|
||||
</div>
|
||||
<figure class="video-container">
|
||||
<iframe src="https://www.youtube.com/embed/12yWKw1AdKY" frameborder="0" allowfullscreen="true"> </iframe>
|
||||
</figure>
|
||||
|
||||
The `items` attribute is a list of objects representing the data points.
|
||||
|
||||
````markdown
|
||||
|
|
@ -1632,14 +1641,6 @@ The `items` attribute is a list of objects representing the data points.
|
|||
```
|
||||
````
|
||||
|
||||
```json:table
|
||||
{
|
||||
"items" : [
|
||||
{"a": "11", "b": "22", "c": "33"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
To specify the table labels, use the `fields` attribute.
|
||||
|
||||
````markdown
|
||||
|
|
@ -1653,15 +1654,6 @@ To specify the table labels, use the `fields` attribute.
|
|||
```
|
||||
````
|
||||
|
||||
```json:table
|
||||
{
|
||||
"fields" : ["a", "b", "c"],
|
||||
"items" : [
|
||||
{"a": "11", "b": "22", "c": "33"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
Not all elements of `items` must have corresponding values in `fields`.
|
||||
|
||||
````markdown
|
||||
|
|
@ -1676,16 +1668,6 @@ Not all elements of `items` must have corresponding values in `fields`.
|
|||
```
|
||||
````
|
||||
|
||||
```json:table
|
||||
{
|
||||
"fields" : ["a", "b", "c"],
|
||||
"items" : [
|
||||
{"a": "11", "b": "22", "c": "33"},
|
||||
{"a": "211", "c": "233"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
When `fields` is not explicitly specified, the labels are picked from the first element of `items`.
|
||||
|
||||
````markdown
|
||||
|
|
@ -1699,15 +1681,6 @@ When `fields` is not explicitly specified, the labels are picked from the first
|
|||
```
|
||||
````
|
||||
|
||||
```json:table
|
||||
{
|
||||
"items" : [
|
||||
{"a": "11", "b": "22", "c": "33"},
|
||||
{"a": "211", "c": "233"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
You can specify custom labels for `fields`.
|
||||
|
||||
````markdown
|
||||
|
|
@ -1726,20 +1699,6 @@ You can specify custom labels for `fields`.
|
|||
```
|
||||
````
|
||||
|
||||
```json:table
|
||||
{
|
||||
"fields" : [
|
||||
{"key": "a", "label": "AA"},
|
||||
{"key": "b", "label": "BB"},
|
||||
{"key": "c", "label": "CC"}
|
||||
],
|
||||
"items" : [
|
||||
{"a": "11", "b": "22", "c": "33"},
|
||||
{"a": "211", "b": "222", "c": "233"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
You can enable sorting for individual elements of `fields`.
|
||||
|
||||
````markdown
|
||||
|
|
@ -1758,20 +1717,6 @@ You can enable sorting for individual elements of `fields`.
|
|||
```
|
||||
````
|
||||
|
||||
```json:table
|
||||
{
|
||||
"fields" : [
|
||||
{"key": "a", "label": "AA", "sortable": true},
|
||||
{"key": "b", "label": "BB"},
|
||||
{"key": "c", "label": "CC"}
|
||||
],
|
||||
"items" : [
|
||||
{"a": "11", "b": "22", "c": "33"},
|
||||
{"a": "211", "b": "222", "c": "233"}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
You can use the `filter` attribute to render a table with content filtered dynamically by user input.
|
||||
|
||||
````markdown
|
||||
|
|
@ -1791,21 +1736,6 @@ You can use the `filter` attribute to render a table with content filtered dynam
|
|||
```
|
||||
````
|
||||
|
||||
```json:table
|
||||
{
|
||||
"fields" : [
|
||||
{"key": "a", "label": "AA"},
|
||||
{"key": "b", "label": "BB"},
|
||||
{"key": "c", "label": "CC"}
|
||||
],
|
||||
"items" : [
|
||||
{"a": "11", "b": "22", "c": "33"},
|
||||
{"a": "211", "b": "222", "c": "233"}
|
||||
],
|
||||
"filter" : true
|
||||
}
|
||||
```
|
||||
|
||||
By default, every JSON table has the caption `Generated with JSON data`.
|
||||
You can override this caption by specifying the `caption` attribute.
|
||||
|
||||
|
|
@ -1820,15 +1750,6 @@ You can override this caption by specifying the `caption` attribute.
|
|||
```
|
||||
````
|
||||
|
||||
```json:table
|
||||
{
|
||||
"items" : [
|
||||
{"a": "11", "b": "22", "c": "33"}
|
||||
],
|
||||
"caption" : "Custom caption"
|
||||
}
|
||||
```
|
||||
|
||||
If JSON is invalid, an error occurs.
|
||||
|
||||
````markdown
|
||||
|
|
@ -1841,14 +1762,6 @@ If JSON is invalid, an error occurs.
|
|||
```
|
||||
````
|
||||
|
||||
```json:table
|
||||
{
|
||||
"items" : [
|
||||
{"a": "11", "b": "22", "c": "33"}
|
||||
],
|
||||
}
|
||||
```
|
||||
|
||||
## References
|
||||
|
||||
- This document leveraged heavily from the [Markdown-Cheatsheet](https://github.com/adam-p/markdown-here/wiki/Markdown-Cheatsheet).
|
||||
|
|
|
|||
|
|
@ -120,7 +120,7 @@ module Gitlab
|
|||
stage: stage_value,
|
||||
extends: extends,
|
||||
rules: rules_value,
|
||||
job_variables: variables_value.to_h,
|
||||
job_variables: variables_entry.value_with_data,
|
||||
root_variables_inheritance: root_variables_inheritance,
|
||||
only: only_value,
|
||||
except: except_value,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,244 @@
|
|||
# To contribute improvements to CI/CD templates, please follow the Development guide at:
|
||||
# https://docs.gitlab.com/ee/development/cicd/templates.html
|
||||
# This specific template is located at:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.gitlab-ci.yml
|
||||
|
||||
# Read more about this feature here: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/
|
||||
#
|
||||
# Configure dependency scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/index.html).
|
||||
# List of available variables: https://docs.gitlab.com/ee/user/application_security/dependency_scanning/index.html#available-variables
|
||||
|
||||
variables:
|
||||
# Setting this variable will affect all Security templates
|
||||
# (SAST, Dependency Scanning, ...)
|
||||
SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
|
||||
DS_EXCLUDED_ANALYZERS: ""
|
||||
DS_EXCLUDED_PATHS: "spec, test, tests, tmp"
|
||||
DS_MAJOR_VERSION: 3
|
||||
|
||||
dependency_scanning:
|
||||
stage: test
|
||||
script:
|
||||
- echo "$CI_JOB_NAME is used for configuration only, and its script should not be executed"
|
||||
- exit 1
|
||||
artifacts:
|
||||
reports:
|
||||
dependency_scanning: gl-dependency-scanning-report.json
|
||||
dependencies: []
|
||||
rules:
|
||||
- when: never
|
||||
|
||||
.ds-analyzer:
|
||||
extends: dependency_scanning
|
||||
allow_failure: true
|
||||
variables:
|
||||
# DS_ANALYZER_IMAGE is an undocumented variable used internally to allow QA to
|
||||
# override the analyzer image with a custom value. This may be subject to change or
|
||||
# breakage across GitLab releases.
|
||||
DS_ANALYZER_IMAGE: "$SECURE_ANALYZERS_PREFIX/$DS_ANALYZER_NAME:$DS_MAJOR_VERSION"
|
||||
# DS_ANALYZER_NAME is an undocumented variable used in job definitions
|
||||
# to inject the analyzer name in the image name.
|
||||
DS_ANALYZER_NAME: ""
|
||||
image:
|
||||
name: "$DS_ANALYZER_IMAGE$DS_IMAGE_SUFFIX"
|
||||
# `rules` must be overridden explicitly by each child job
|
||||
# see https://gitlab.com/gitlab-org/gitlab/-/issues/218444
|
||||
script:
|
||||
- /analyzer run
|
||||
|
||||
.cyclonedx-reports:
|
||||
artifacts:
|
||||
paths:
|
||||
- "**/gl-sbom-*.cdx.json"
|
||||
|
||||
.gemnasium-shared-rule:
|
||||
exists:
|
||||
- '{Gemfile.lock,*/Gemfile.lock,*/*/Gemfile.lock}'
|
||||
- '{composer.lock,*/composer.lock,*/*/composer.lock}'
|
||||
- '{gems.locked,*/gems.locked,*/*/gems.locked}'
|
||||
- '{go.sum,*/go.sum,*/*/go.sum}'
|
||||
- '{npm-shrinkwrap.json,*/npm-shrinkwrap.json,*/*/npm-shrinkwrap.json}'
|
||||
- '{package-lock.json,*/package-lock.json,*/*/package-lock.json}'
|
||||
- '{yarn.lock,*/yarn.lock,*/*/yarn.lock}'
|
||||
- '{packages.lock.json,*/packages.lock.json,*/*/packages.lock.json}'
|
||||
- '{conan.lock,*/conan.lock,*/*/conan.lock}'
|
||||
|
||||
gemnasium-dependency_scanning:
|
||||
extends:
|
||||
- .ds-analyzer
|
||||
- .cyclonedx-reports
|
||||
variables:
|
||||
DS_ANALYZER_NAME: "gemnasium"
|
||||
GEMNASIUM_LIBRARY_SCAN_ENABLED: "true"
|
||||
rules:
|
||||
- if: $DEPENDENCY_SCANNING_DISABLED
|
||||
when: never
|
||||
- if: $DS_EXCLUDED_ANALYZERS =~ /gemnasium([^-]|$)/
|
||||
when: never
|
||||
|
||||
# Add the job to merge request pipelines if there's an open merge request.
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
|
||||
$CI_GITLAB_FIPS_MODE == "true"
|
||||
exists: !reference [.gemnasium-shared-rule, exists]
|
||||
variables:
|
||||
DS_IMAGE_SUFFIX: "-fips"
|
||||
DS_REMEDIATE: "false"
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/
|
||||
exists: !reference [.gemnasium-shared-rule, exists]
|
||||
|
||||
# Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
|
||||
- if: $CI_OPEN_MERGE_REQUESTS
|
||||
when: never
|
||||
|
||||
# Add the job to branch pipelines.
|
||||
- if: $CI_COMMIT_BRANCH &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
|
||||
$CI_GITLAB_FIPS_MODE == "true"
|
||||
exists: !reference [.gemnasium-shared-rule, exists]
|
||||
variables:
|
||||
DS_IMAGE_SUFFIX: "-fips"
|
||||
DS_REMEDIATE: "false"
|
||||
- if: $CI_COMMIT_BRANCH &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/
|
||||
exists: !reference [.gemnasium-shared-rule, exists]
|
||||
|
||||
.gemnasium-maven-shared-rule:
|
||||
exists:
|
||||
- '{build.gradle,*/build.gradle,*/*/build.gradle}'
|
||||
- '{build.gradle.kts,*/build.gradle.kts,*/*/build.gradle.kts}'
|
||||
- '{build.sbt,*/build.sbt,*/*/build.sbt}'
|
||||
- '{pom.xml,*/pom.xml,*/*/pom.xml}'
|
||||
|
||||
gemnasium-maven-dependency_scanning:
|
||||
extends:
|
||||
- .ds-analyzer
|
||||
- .cyclonedx-reports
|
||||
variables:
|
||||
DS_ANALYZER_NAME: "gemnasium-maven"
|
||||
rules:
|
||||
- if: $DEPENDENCY_SCANNING_DISABLED
|
||||
when: never
|
||||
- if: $DS_EXCLUDED_ANALYZERS =~ /gemnasium-maven/
|
||||
when: never
|
||||
|
||||
# Add the job to merge request pipelines if there's an open merge request.
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
|
||||
$CI_GITLAB_FIPS_MODE == "true"
|
||||
exists: !reference [.gemnasium-maven-shared-rule, exists]
|
||||
variables:
|
||||
DS_IMAGE_SUFFIX: "-fips"
|
||||
DS_REMEDIATE: "false"
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/
|
||||
exists: !reference [.gemnasium-maven-shared-rule, exists]
|
||||
|
||||
# Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
|
||||
- if: $CI_OPEN_MERGE_REQUESTS
|
||||
when: never
|
||||
|
||||
# Add the job to branch pipelines.
|
||||
- if: $CI_COMMIT_BRANCH &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
|
||||
$CI_GITLAB_FIPS_MODE == "true"
|
||||
exists: !reference [.gemnasium-maven-shared-rule, exists]
|
||||
variables:
|
||||
DS_IMAGE_SUFFIX: "-fips"
|
||||
- if: $CI_COMMIT_BRANCH &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/
|
||||
exists: !reference [.gemnasium-maven-shared-rule, exists]
|
||||
|
||||
.gemnasium-python-shared-rule:
|
||||
exists:
|
||||
- '{requirements.txt,*/requirements.txt,*/*/requirements.txt}'
|
||||
- '{requirements.pip,*/requirements.pip,*/*/requirements.pip}'
|
||||
- '{Pipfile,*/Pipfile,*/*/Pipfile}'
|
||||
- '{requires.txt,*/requires.txt,*/*/requires.txt}'
|
||||
- '{setup.py,*/setup.py,*/*/setup.py}'
|
||||
- '{poetry.lock,*/poetry.lock,*/*/poetry.lock}'
|
||||
|
||||
gemnasium-python-dependency_scanning:
|
||||
extends:
|
||||
- .ds-analyzer
|
||||
- .cyclonedx-reports
|
||||
variables:
|
||||
DS_ANALYZER_NAME: "gemnasium-python"
|
||||
rules:
|
||||
- if: $DEPENDENCY_SCANNING_DISABLED
|
||||
when: never
|
||||
- if: $DS_EXCLUDED_ANALYZERS =~ /gemnasium-python/
|
||||
when: never
|
||||
|
||||
# Add the job to merge request pipelines if there's an open merge request.
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
|
||||
$CI_GITLAB_FIPS_MODE == "true"
|
||||
exists: !reference [.gemnasium-python-shared-rule, exists]
|
||||
variables:
|
||||
DS_IMAGE_SUFFIX: "-fips"
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/
|
||||
exists: !reference [.gemnasium-python-shared-rule, exists]
|
||||
# Support passing of $PIP_REQUIREMENTS_FILE
|
||||
# See https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
|
||||
$PIP_REQUIREMENTS_FILE &&
|
||||
$CI_GITLAB_FIPS_MODE == "true"
|
||||
variables:
|
||||
DS_IMAGE_SUFFIX: "-fips"
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
|
||||
$PIP_REQUIREMENTS_FILE
|
||||
|
||||
# Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
|
||||
- if: $CI_OPEN_MERGE_REQUESTS
|
||||
when: never
|
||||
|
||||
# Add the job to branch pipelines.
|
||||
- if: $CI_COMMIT_BRANCH &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
|
||||
$CI_GITLAB_FIPS_MODE == "true"
|
||||
exists: !reference [.gemnasium-python-shared-rule, exists]
|
||||
variables:
|
||||
DS_IMAGE_SUFFIX: "-fips"
|
||||
- if: $CI_COMMIT_BRANCH &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/
|
||||
exists: !reference [.gemnasium-python-shared-rule, exists]
|
||||
# Support passing of $PIP_REQUIREMENTS_FILE
|
||||
# See https://docs.gitlab.com/ee/user/application_security/dependency_scanning/#configuring-specific-analyzers-used-by-dependency-scanning
|
||||
- if: $CI_COMMIT_BRANCH &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
|
||||
$PIP_REQUIREMENTS_FILE &&
|
||||
$CI_GITLAB_FIPS_MODE == "true"
|
||||
variables:
|
||||
DS_IMAGE_SUFFIX: "-fips"
|
||||
- if: $CI_COMMIT_BRANCH &&
|
||||
$GITLAB_FEATURES =~ /\bdependency_scanning\b/ &&
|
||||
$PIP_REQUIREMENTS_FILE
|
||||
|
||||
bundler-audit-dependency_scanning:
|
||||
extends: .ds-analyzer
|
||||
variables:
|
||||
DS_ANALYZER_NAME: "bundler-audit"
|
||||
DS_MAJOR_VERSION: 2
|
||||
script:
|
||||
- echo "This job was deprecated in GitLab 14.8 and removed in GitLab 15.0"
|
||||
- echo "For more information see https://gitlab.com/gitlab-org/gitlab/-/issues/347491"
|
||||
- exit 1
|
||||
rules:
|
||||
- when: never
|
||||
|
||||
retire-js-dependency_scanning:
|
||||
extends: .ds-analyzer
|
||||
variables:
|
||||
DS_ANALYZER_NAME: "retire.js"
|
||||
DS_MAJOR_VERSION: 2
|
||||
script:
|
||||
- echo "This job was deprecated in GitLab 14.8 and removed in GitLab 15.0"
|
||||
- echo "For more information see https://gitlab.com/gitlab-org/gitlab/-/issues/289830"
|
||||
- exit 1
|
||||
rules:
|
||||
- when: never
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
# To contribute improvements to CI/CD templates, please follow the Development guide at:
|
||||
# https://docs.gitlab.com/ee/development/cicd/templates.html
|
||||
# This specific template is located at:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/License-Scanning.gitlab-ci.yml
|
||||
|
||||
# Read more about this feature here: https://docs.gitlab.com/ee/user/compliance/license_compliance/index.html
|
||||
#
|
||||
# Configure license scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/index.html).
|
||||
# List of available variables: https://docs.gitlab.com/ee/user/compliance/license_compliance/#available-variables
|
||||
|
||||
variables:
|
||||
# Setting this variable will affect all Security templates
|
||||
# (SAST, Dependency Scanning, ...)
|
||||
SECURE_ANALYZERS_PREFIX: "$CI_TEMPLATE_REGISTRY_HOST/security-products"
|
||||
|
||||
LICENSE_MANAGEMENT_SETUP_CMD: '' # If needed, specify a command to setup your environment with a custom package manager.
|
||||
LICENSE_MANAGEMENT_VERSION: 4
|
||||
|
||||
license_scanning:
|
||||
stage: test
|
||||
image:
|
||||
name: "$SECURE_ANALYZERS_PREFIX/license-finder:$LICENSE_MANAGEMENT_VERSION"
|
||||
entrypoint: [""]
|
||||
variables:
|
||||
LM_REPORT_VERSION: '2.1'
|
||||
SETUP_CMD: $LICENSE_MANAGEMENT_SETUP_CMD
|
||||
allow_failure: true
|
||||
script:
|
||||
- /run.sh analyze .
|
||||
artifacts:
|
||||
reports:
|
||||
license_scanning: gl-license-scanning-report.json
|
||||
dependencies: []
|
||||
rules:
|
||||
- if: $LICENSE_MANAGEMENT_DISABLED
|
||||
when: never
|
||||
|
||||
# Add the job to merge request pipelines if there's an open merge request.
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$GITLAB_FEATURES =~ /\blicense_scanning\b/
|
||||
|
||||
# Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
|
||||
- if: $CI_OPEN_MERGE_REQUESTS
|
||||
when: never
|
||||
|
||||
# Add the job to branch pipelines.
|
||||
- if: $CI_COMMIT_BRANCH &&
|
||||
$GITLAB_FEATURES =~ /\blicense_scanning\b/
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
# To contribute improvements to CI/CD templates, please follow the Development guide at:
|
||||
# https://docs.gitlab.com/ee/development/cicd/templates.html
|
||||
# This specific template is located at:
|
||||
# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Security/Container-Scanning.gitlab-ci.yml
|
||||
|
||||
# Use this template to enable container scanning in your project.
|
||||
# You should add this template to an existing `.gitlab-ci.yml` file by using the `include:`
|
||||
# keyword.
|
||||
# The template should work without modifications but you can customize the template settings if
|
||||
# needed: https://docs.gitlab.com/ee/user/application_security/container_scanning/#customizing-the-container-scanning-settings
|
||||
#
|
||||
# Requirements:
|
||||
# - A `test` stage to be present in the pipeline.
|
||||
# - You must define the image to be scanned in the CS_IMAGE variable. If CS_IMAGE is the
|
||||
# same as $CI_APPLICATION_REPOSITORY:$CI_APPLICATION_TAG, you can skip this.
|
||||
# - Container registry credentials defined by `CS_REGISTRY_USER` and `CS_REGISTRY_PASSWORD` variables if the
|
||||
# image to be scanned is in a private registry.
|
||||
# - For auto-remediation, a readable Dockerfile in the root of the project or as defined by the
|
||||
# CS_DOCKERFILE_PATH variable.
|
||||
#
|
||||
# Configure container scanning with CI/CD variables (https://docs.gitlab.com/ee/ci/variables/index.html).
|
||||
# List of available variables: https://docs.gitlab.com/ee/user/application_security/container_scanning/#available-variables
|
||||
|
||||
variables:
|
||||
CS_ANALYZER_IMAGE: "$CI_TEMPLATE_REGISTRY_HOST/security-products/container-scanning:5"
|
||||
|
||||
container_scanning:
|
||||
image: "$CS_ANALYZER_IMAGE$CS_IMAGE_SUFFIX"
|
||||
stage: test
|
||||
variables:
|
||||
# To provide a `vulnerability-allowlist.yml` file, override the GIT_STRATEGY variable in your
|
||||
# `.gitlab-ci.yml` file and set it to `fetch`.
|
||||
# For details, see the following links:
|
||||
# https://docs.gitlab.com/ee/user/application_security/container_scanning/index.html#overriding-the-container-scanning-template
|
||||
# https://docs.gitlab.com/ee/user/application_security/container_scanning/#vulnerability-allowlisting
|
||||
GIT_STRATEGY: none
|
||||
allow_failure: true
|
||||
artifacts:
|
||||
reports:
|
||||
container_scanning: gl-container-scanning-report.json
|
||||
dependency_scanning: gl-dependency-scanning-report.json
|
||||
paths: [gl-container-scanning-report.json, gl-dependency-scanning-report.json]
|
||||
dependencies: []
|
||||
script:
|
||||
- gtcs scan
|
||||
rules:
|
||||
- if: $CONTAINER_SCANNING_DISABLED
|
||||
when: never
|
||||
|
||||
# Add the job to merge request pipelines if there's an open merge request.
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event" &&
|
||||
$CI_GITLAB_FIPS_MODE == "true" &&
|
||||
$CS_ANALYZER_IMAGE !~ /-(fips|ubi)\z/
|
||||
variables:
|
||||
CS_IMAGE_SUFFIX: -fips
|
||||
- if: $CI_PIPELINE_SOURCE == "merge_request_event"
|
||||
|
||||
# Don't add it to a *branch* pipeline if it's already in a merge request pipeline.
|
||||
- if: $CI_OPEN_MERGE_REQUESTS
|
||||
when: never
|
||||
|
||||
# Add the job to branch pipelines.
|
||||
- if: $CI_COMMIT_BRANCH &&
|
||||
$CI_GITLAB_FIPS_MODE == "true" &&
|
||||
$CS_ANALYZER_IMAGE !~ /-(fips|ubi)\z/
|
||||
variables:
|
||||
CS_IMAGE_SUFFIX: -fips
|
||||
- if: $CI_COMMIT_BRANCH
|
||||
|
|
@ -6,26 +6,26 @@ module Gitlab
|
|||
module Helpers
|
||||
class << self
|
||||
def merge_variables(current_vars, new_vars)
|
||||
current_vars = transform_from_yaml_variables(current_vars)
|
||||
new_vars = transform_from_yaml_variables(new_vars)
|
||||
return current_vars if new_vars.blank?
|
||||
|
||||
transform_to_yaml_variables(
|
||||
current_vars.merge(new_vars)
|
||||
)
|
||||
current_vars = transform_to_array(current_vars) if current_vars.is_a?(Hash)
|
||||
new_vars = transform_to_array(new_vars) if new_vars.is_a?(Hash)
|
||||
|
||||
(new_vars + current_vars).uniq { |var| var[:key] }
|
||||
end
|
||||
|
||||
def transform_to_yaml_variables(vars)
|
||||
vars.to_h.map do |key, value|
|
||||
{ key: key.to_s, value: value }
|
||||
def transform_to_array(vars)
|
||||
return [] if vars.blank?
|
||||
|
||||
vars.map do |key, data|
|
||||
if data.is_a?(Hash)
|
||||
{ key: key.to_s, **data.except(:key) }
|
||||
else
|
||||
{ key: key.to_s, value: data }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def transform_from_yaml_variables(vars)
|
||||
return vars.stringify_keys.transform_values(&:to_s) if vars.is_a?(Hash)
|
||||
|
||||
vars.to_a.to_h { |var| [var[:key].to_s, var[:value]] }
|
||||
end
|
||||
|
||||
def inherit_yaml_variables(from:, to:, inheritance:)
|
||||
merge_variables(apply_inheritance(from, inheritance), to)
|
||||
end
|
||||
|
|
@ -35,7 +35,7 @@ module Gitlab
|
|||
def apply_inheritance(variables, inheritance)
|
||||
case inheritance
|
||||
when true then variables
|
||||
when false then {}
|
||||
when false then []
|
||||
when Array then variables.select { |var| inheritance.include?(var[:key]) }
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ module Gitlab
|
|||
end
|
||||
|
||||
def root_variables
|
||||
@root_variables ||= transform_to_yaml_variables(variables)
|
||||
@root_variables ||= transform_to_array(variables)
|
||||
end
|
||||
|
||||
def jobs
|
||||
|
|
@ -70,7 +70,7 @@ module Gitlab
|
|||
environment: job[:environment_name],
|
||||
coverage_regex: job[:coverage],
|
||||
# yaml_variables is calculated with using job_variables in Seed::Build
|
||||
job_variables: transform_to_yaml_variables(job[:job_variables]),
|
||||
job_variables: transform_to_array(job[:job_variables]),
|
||||
root_variables_inheritance: job[:root_variables_inheritance],
|
||||
needs_attributes: job.dig(:needs, :job),
|
||||
interruptible: job[:interruptible],
|
||||
|
|
@ -114,7 +114,7 @@ module Gitlab
|
|||
|
||||
Gitlab::Ci::Variables::Helpers.inherit_yaml_variables(
|
||||
from: root_variables,
|
||||
to: transform_to_yaml_variables(job[:job_variables]),
|
||||
to: job[:job_variables],
|
||||
inheritance: job.fetch(:root_variables_inheritance, true)
|
||||
)
|
||||
end
|
||||
|
|
@ -137,8 +137,8 @@ module Gitlab
|
|||
job[:release]
|
||||
end
|
||||
|
||||
def transform_to_yaml_variables(variables)
|
||||
::Gitlab::Ci::Variables::Helpers.transform_to_yaml_variables(variables)
|
||||
def transform_to_array(variables)
|
||||
::Gitlab::Ci::Variables::Helpers.transform_to_array(variables)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -139,6 +139,10 @@
|
|||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_security_container_scanning_latest
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_security_api_fuzzing
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
|
|
@ -323,6 +327,10 @@
|
|||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_jobs_license_scanning_latest
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_jobs_deploy
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
|
|
@ -335,6 +343,10 @@
|
|||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_jobs_dependency_scanning_latest
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_jobs_test
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
|
|
@ -527,6 +539,10 @@
|
|||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_implicit_jobs_license_scanning_latest
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_implicit_jobs_deploy
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
|
|
@ -539,6 +555,10 @@
|
|||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_implicit_jobs_dependency_scanning_latest
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_implicit_jobs_test
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
|
|
@ -639,6 +659,10 @@
|
|||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_implicit_security_container_scanning_latest
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
aggregation: weekly
|
||||
- name: p_ci_templates_implicit_security_api_fuzzing
|
||||
category: ci_templates
|
||||
redis_slot: ci_templates
|
||||
|
|
|
|||
|
|
@ -404,3 +404,28 @@
|
|||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
## License Compliance
|
||||
- name: i_code_review_merge_request_widget_license_compliance_view
|
||||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
- name: i_code_review_merge_request_widget_license_compliance_full_report_clicked
|
||||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
- name: i_code_review_merge_request_widget_license_compliance_expand
|
||||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
- name: i_code_review_merge_request_widget_license_compliance_expand_success
|
||||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
- name: i_code_review_merge_request_widget_license_compliance_expand_warning
|
||||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
- name: i_code_review_merge_request_widget_license_compliance_expand_failed
|
||||
redis_slot: code_review
|
||||
category: code_review
|
||||
aggregation: weekly
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ module Gitlab
|
|||
class MergeRequestWidgetExtensionCounter < BaseCounter
|
||||
KNOWN_EVENTS = %w[view full_report_clicked expand expand_success expand_warning expand_failed].freeze
|
||||
PREFIX = 'i_code_review_merge_request_widget'
|
||||
WIDGETS = %w[accessibility code_quality status_checks terraform test_summary metrics].freeze
|
||||
WIDGETS = %w[accessibility code_quality license_compliance status_checks terraform test_summary metrics].freeze
|
||||
|
||||
class << self
|
||||
private
|
||||
|
|
|
|||
|
|
@ -7,6 +7,21 @@ module GitlabEdition
|
|||
Pathname.new(File.expand_path('..', __dir__))
|
||||
end
|
||||
|
||||
def self.path_glob(path)
|
||||
"#{root}/#{extension_path_prefixes}#{path}"
|
||||
end
|
||||
|
||||
def self.extension_path_prefixes
|
||||
path_prefixes = extensions
|
||||
return '' if path_prefixes.empty?
|
||||
|
||||
path_prefixes.map! { "#{_1}/" }
|
||||
path_prefixes.unshift ''
|
||||
|
||||
# For example `{,ee/,jh/}`
|
||||
"{#{path_prefixes.join(',')}}"
|
||||
end
|
||||
|
||||
def self.extensions
|
||||
if jh?
|
||||
%w[ee jh]
|
||||
|
|
|
|||
|
|
@ -25681,6 +25681,9 @@ msgstr ""
|
|||
msgid "Milestones|Use milestones to track issues and merge requests over a fixed period of time"
|
||||
msgstr ""
|
||||
|
||||
msgid "Milestone|%{percentage}%{percent} complete"
|
||||
msgstr ""
|
||||
|
||||
msgid "Min Value"
|
||||
msgstr ""
|
||||
|
||||
|
|
@ -34614,9 +34617,6 @@ msgstr ""
|
|||
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} actions for the %{scopes} %{branches}"
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanExecutionPolicy|%{ifLabelStart}if%{ifLabelEnd} %{rules} for the %{branches} branch(es)"
|
||||
msgstr ""
|
||||
|
||||
msgid "ScanExecutionPolicy|%{period} %{days} at %{time}"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,16 @@ module RuboCop
|
|||
#
|
||||
# # bad
|
||||
#
|
||||
# Feature.get(:x)
|
||||
# Feature.get(:x).enable
|
||||
# Feature.get(:x).enable_percentage_of_time(100)
|
||||
# Feature.get(:x).remove
|
||||
#
|
||||
# # good
|
||||
#
|
||||
# stub_feature_flags(x: true)
|
||||
# Feature.enable(:x)
|
||||
# Feature.enable_percentage_of_time(:x, 100)
|
||||
# Feature.remove(:x)
|
||||
#
|
||||
class AvoidFeatureGet < RuboCop::Cop::Cop
|
||||
MSG = 'Use `stub_feature_flags` method instead of `Feature.get`. ' \
|
||||
|
|
|
|||
|
|
@ -5,12 +5,7 @@ import Frontmatter from '~/content_editor/extensions/frontmatter';
|
|||
import Bold from '~/content_editor/extensions/bold';
|
||||
import { VARIANT_DANGER } from '~/flash';
|
||||
import eventHubFactory from '~/helpers/event_hub_factory';
|
||||
import {
|
||||
ALERT_EVENT,
|
||||
LOADING_CONTENT_EVENT,
|
||||
LOADING_SUCCESS_EVENT,
|
||||
LOADING_ERROR_EVENT,
|
||||
} from '~/content_editor/constants';
|
||||
import { ALERT_EVENT } from '~/content_editor/constants';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { createTestEditor, createDocBuilder, waitUntilNextDocTransaction } from '../test_utils';
|
||||
|
||||
|
|
@ -115,13 +110,6 @@ describe('content_editor/extensions/paste_markdown', () => {
|
|||
|
||||
expect(tiptapEditor.state.doc.toJSON()).toEqual(expectedDoc.toJSON());
|
||||
});
|
||||
|
||||
it(`triggers ${LOADING_SUCCESS_EVENT}`, async () => {
|
||||
await triggerPasteEventHandlerAndWaitForTransaction(buildClipboardEvent());
|
||||
|
||||
expect(eventHub.$emit).toHaveBeenCalledWith(LOADING_CONTENT_EVENT);
|
||||
expect(eventHub.$emit).toHaveBeenCalledWith(LOADING_SUCCESS_EVENT);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when rendering markdown fails', () => {
|
||||
|
|
@ -129,13 +117,6 @@ describe('content_editor/extensions/paste_markdown', () => {
|
|||
renderMarkdown.mockRejectedValueOnce();
|
||||
});
|
||||
|
||||
it(`triggers ${LOADING_ERROR_EVENT} event`, async () => {
|
||||
await triggerPasteEventHandler(buildClipboardEvent());
|
||||
await waitForPromises();
|
||||
|
||||
expect(eventHub.$emit).toHaveBeenCalledWith(LOADING_ERROR_EVENT);
|
||||
});
|
||||
|
||||
it(`triggers ${ALERT_EVENT} event`, async () => {
|
||||
await triggerPasteEventHandler(buildClipboardEvent());
|
||||
await waitForPromises();
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
// Jest Snapshot v1, https://goo.gl/fbAQLP
|
||||
|
||||
exports[`TotalTime with a blank object should render -- 1`] = `"<span class=\\"total-time\\"> -- </span>"`;
|
||||
exports[`TotalTime with a blank object should render -- 1`] = `"<span> -- </span>"`;
|
||||
|
||||
exports[`TotalTime with a valid time object with {"days": 3, "mins": 47, "seconds": 3} 1`] = `
|
||||
"<span class=\\"total-time\\">
|
||||
"<span>
|
||||
3 <span>days</span></span>"
|
||||
`;
|
||||
|
||||
exports[`TotalTime with a valid time object with {"hours": 7, "mins": 20, "seconds": 10} 1`] = `
|
||||
"<span class=\\"total-time\\">
|
||||
"<span>
|
||||
7 <span>hrs</span></span>"
|
||||
`;
|
||||
|
||||
exports[`TotalTime with a valid time object with {"hours": 23, "mins": 10} 1`] = `
|
||||
"<span class=\\"total-time\\">
|
||||
"<span>
|
||||
23 <span>hrs</span></span>"
|
||||
`;
|
||||
|
||||
exports[`TotalTime with a valid time object with {"mins": 47, "seconds": 3} 1`] = `
|
||||
"<span class=\\"total-time\\">
|
||||
"<span>
|
||||
47 <span>mins</span></span>"
|
||||
`;
|
||||
|
||||
exports[`TotalTime with a valid time object with {"seconds": 35} 1`] = `
|
||||
"<span class=\\"total-time\\">
|
||||
"<span>
|
||||
35 <span>s</span></span>"
|
||||
`;
|
||||
|
|
|
|||
|
|
@ -11,7 +11,7 @@ exports[`Design management list item component when item appears in view after i
|
|||
exports[`Design management list item component with notes renders item with multiple comments 1`] = `
|
||||
<router-link-stub
|
||||
ariacurrentvalue="page"
|
||||
class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
|
||||
class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new gl-mb-0"
|
||||
event="click"
|
||||
tag="a"
|
||||
to="[object Object]"
|
||||
|
|
@ -88,7 +88,7 @@ exports[`Design management list item component with notes renders item with mult
|
|||
exports[`Design management list item component with notes renders item with single comment 1`] = `
|
||||
<router-link-stub
|
||||
ariacurrentvalue="page"
|
||||
class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new"
|
||||
class="card gl-cursor-pointer text-plain js-design-list-item design-list-item design-list-item-new gl-mb-0"
|
||||
event="click"
|
||||
tag="a"
|
||||
to="[object Object]"
|
||||
|
|
|
|||
|
|
@ -9,9 +9,7 @@ exports[`Design management index page designs renders error 1`] = `
|
|||
|
||||
<!---->
|
||||
|
||||
<div
|
||||
class="gl-mt-6"
|
||||
>
|
||||
<div>
|
||||
<gl-alert-stub
|
||||
dismisslabel="Dismiss"
|
||||
primarybuttonlink=""
|
||||
|
|
@ -43,9 +41,7 @@ exports[`Design management index page designs renders loading icon 1`] = `
|
|||
|
||||
<!---->
|
||||
|
||||
<div
|
||||
class="gl-mt-6"
|
||||
>
|
||||
<div>
|
||||
<gl-loading-icon-stub
|
||||
color="dark"
|
||||
label="Loading"
|
||||
|
|
|
|||
|
|
@ -254,7 +254,7 @@ describe('Design management index page', () => {
|
|||
'gl-flex-direction-column',
|
||||
'col-md-6',
|
||||
'col-lg-3',
|
||||
'gl-mb-3',
|
||||
'gl-mt-5',
|
||||
]);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -63,12 +63,26 @@ describe('locale', () => {
|
|||
it('does not escape parameters for escapeParameters = false', () => {
|
||||
const input = 'contains %{safeContent}';
|
||||
const parameters = {
|
||||
safeContent: '<strong>bold attempt</strong>',
|
||||
safeContent: '15',
|
||||
};
|
||||
|
||||
const output = sprintf(input, parameters, false);
|
||||
|
||||
expect(output).toBe('contains <strong>bold attempt</strong>');
|
||||
expect(output).toBe('contains 15');
|
||||
});
|
||||
|
||||
describe('replaces duplicated % in input', () => {
|
||||
it('removes duplicated percentage signs', () => {
|
||||
const input = 'contains duplicated %{safeContent}%%';
|
||||
|
||||
const parameters = {
|
||||
safeContent: '15',
|
||||
};
|
||||
|
||||
const output = sprintf(input, parameters, false);
|
||||
|
||||
expect(output).toBe('contains duplicated 15%');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -17,7 +17,8 @@ import { loadViewer } from '~/repository/components/blob_viewers';
|
|||
import DownloadViewer from '~/repository/components/blob_viewers/download_viewer.vue';
|
||||
import EmptyViewer from '~/repository/components/blob_viewers/empty_viewer.vue';
|
||||
import SourceViewer from '~/vue_shared/components/source_viewer/source_viewer.vue';
|
||||
import blobInfoQuery from '~/repository/queries/blob_info.query.graphql';
|
||||
import blobInfoQuery from 'shared_queries/repository/blob_info.query.graphql';
|
||||
import projectInfoQuery from '~/repository/queries/project_info.query.graphql';
|
||||
import userInfoQuery from '~/repository/queries/user_info.query.graphql';
|
||||
import applicationInfoQuery from '~/repository/queries/application_info.query.graphql';
|
||||
import CodeIntelligence from '~/code_navigation/components/app.vue';
|
||||
|
|
@ -45,8 +46,9 @@ jest.mock('~/lib/utils/common_utils');
|
|||
jest.mock('~/blob/line_highlighter');
|
||||
|
||||
let wrapper;
|
||||
let mockResolver;
|
||||
let blobInfoMockResolver;
|
||||
let userInfoMockResolver;
|
||||
let projectInfoMockResolver;
|
||||
let applicationInfoMockResolver;
|
||||
|
||||
const mockAxios = new MockAdapter(axios);
|
||||
|
|
@ -74,22 +76,40 @@ const createComponent = async (mockData = {}, mountFn = shallowMount, mockRoute
|
|||
highlightJs = true,
|
||||
} = mockData;
|
||||
|
||||
const project = {
|
||||
const blobInfo = {
|
||||
...projectMock,
|
||||
userPermissions: {
|
||||
pushCode,
|
||||
forkProject,
|
||||
downloadCode,
|
||||
createMergeRequestIn,
|
||||
},
|
||||
repository: {
|
||||
empty,
|
||||
blobs: { nodes: [blob] },
|
||||
},
|
||||
};
|
||||
|
||||
mockResolver = jest.fn().mockResolvedValue({
|
||||
data: { isBinary, project },
|
||||
const projectInfo = {
|
||||
__typename: 'Project',
|
||||
id: '123',
|
||||
userPermissions: {
|
||||
pushCode,
|
||||
forkProject,
|
||||
downloadCode,
|
||||
createMergeRequestIn,
|
||||
},
|
||||
pathLocks: {
|
||||
nodes: [
|
||||
{
|
||||
id: 'test',
|
||||
path: 'locked_file.js',
|
||||
user: { id: '123', username: 'root' },
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
||||
|
||||
projectInfoMockResolver = jest.fn().mockResolvedValue({
|
||||
data: { project: projectInfo },
|
||||
});
|
||||
|
||||
blobInfoMockResolver = jest.fn().mockResolvedValue({
|
||||
data: { isBinary, project: blobInfo },
|
||||
});
|
||||
|
||||
userInfoMockResolver = jest.fn().mockResolvedValue({
|
||||
|
|
@ -101,8 +121,9 @@ const createComponent = async (mockData = {}, mountFn = shallowMount, mockRoute
|
|||
});
|
||||
|
||||
const fakeApollo = createMockApollo([
|
||||
[blobInfoQuery, mockResolver],
|
||||
[blobInfoQuery, blobInfoMockResolver],
|
||||
[userInfoQuery, userInfoMockResolver],
|
||||
[projectInfoQuery, projectInfoMockResolver],
|
||||
[applicationInfoQuery, applicationInfoMockResolver],
|
||||
]);
|
||||
|
||||
|
|
@ -129,7 +150,7 @@ const createComponent = async (mockData = {}, mountFn = shallowMount, mockRoute
|
|||
|
||||
// setData usage is discouraged. See https://gitlab.com/groups/gitlab-org/-/epics/7330 for details
|
||||
// eslint-disable-next-line no-restricted-syntax
|
||||
wrapper.setData({ project, isBinary });
|
||||
wrapper.setData({ project: blobInfo, isBinary });
|
||||
|
||||
await waitForPromises();
|
||||
};
|
||||
|
|
@ -504,14 +525,16 @@ describe('Blob content viewer component', () => {
|
|||
async ({ highlightJs, shouldFetchRawText }) => {
|
||||
await createComponent({ highlightJs });
|
||||
|
||||
expect(mockResolver).toHaveBeenCalledWith(expect.objectContaining({ shouldFetchRawText }));
|
||||
expect(blobInfoMockResolver).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ shouldFetchRawText }),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
it('is called with originalBranch value if the prop has a value', async () => {
|
||||
await createComponent({ inject: { originalBranch: 'some-branch' } });
|
||||
|
||||
expect(mockResolver).toHaveBeenCalledWith(
|
||||
expect(blobInfoMockResolver).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
ref: 'some-branch',
|
||||
}),
|
||||
|
|
@ -521,7 +544,7 @@ describe('Blob content viewer component', () => {
|
|||
it('is called with ref value if the originalBranch prop has no value', async () => {
|
||||
await createComponent();
|
||||
|
||||
expect(mockResolver).toHaveBeenCalledWith(
|
||||
expect(blobInfoMockResolver).toHaveBeenCalledWith(
|
||||
expect.objectContaining({
|
||||
ref: 'default-ref',
|
||||
}),
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
export const simpleViewerMock = {
|
||||
__typename: 'RepositoryBlob',
|
||||
id: '1',
|
||||
name: 'some_file.js',
|
||||
size: 123,
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ exports[`Upload dropzone component correctly overrides description and drop mess
|
|||
class="gl-w-full gl-relative"
|
||||
>
|
||||
<button
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
|
|
@ -86,7 +86,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
|
|||
class="gl-w-full gl-relative"
|
||||
>
|
||||
<button
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
|
|
@ -171,7 +171,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
|
|||
class="gl-w-full gl-relative"
|
||||
>
|
||||
<button
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
|
|
@ -256,7 +256,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
|
|||
class="gl-w-full gl-relative"
|
||||
>
|
||||
<button
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
|
|
@ -342,7 +342,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
|
|||
class="gl-w-full gl-relative"
|
||||
>
|
||||
<button
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
|
|
@ -428,7 +428,7 @@ exports[`Upload dropzone component when dragging renders correct template when d
|
|||
class="gl-w-full gl-relative"
|
||||
>
|
||||
<button
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
|
|
@ -514,7 +514,7 @@ exports[`Upload dropzone component when no slot provided renders default dropzon
|
|||
class="gl-w-full gl-relative"
|
||||
>
|
||||
<button
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4"
|
||||
class="card upload-dropzone-card upload-dropzone-border gl-w-full gl-h-full gl-align-items-center gl-justify-content-center gl-p-4 gl-mb-0"
|
||||
type="button"
|
||||
>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -142,6 +142,10 @@ describe('WorkItemDetail component', () => {
|
|||
expect(findWorkItemState().exists()).toBe(true);
|
||||
expect(findWorkItemTitle().exists()).toBe(true);
|
||||
});
|
||||
|
||||
it('updates the document title', () => {
|
||||
expect(document.title).toEqual('Updated title · Task · test-project-path');
|
||||
});
|
||||
});
|
||||
|
||||
describe('close button', () => {
|
||||
|
|
|
|||
|
|
@ -27,6 +27,10 @@ describe('content_editor', () => {
|
|||
await nextTick();
|
||||
};
|
||||
|
||||
const mockRenderMarkdownResponse = (response) => {
|
||||
renderMarkdown.mockImplementation((markdown) => (markdown ? response : null));
|
||||
};
|
||||
|
||||
beforeEach(() => {
|
||||
renderMarkdown = jest.fn();
|
||||
});
|
||||
|
|
@ -34,7 +38,7 @@ describe('content_editor', () => {
|
|||
describe('when loading initial content', () => {
|
||||
describe('when the initial content is empty', () => {
|
||||
it('still hides the loading indicator', async () => {
|
||||
renderMarkdown.mockResolvedValue('');
|
||||
mockRenderMarkdownResponse('');
|
||||
|
||||
buildWrapper();
|
||||
|
||||
|
|
@ -47,9 +51,11 @@ describe('content_editor', () => {
|
|||
describe('when the initial content is not empty', () => {
|
||||
const initialContent = '<p><strong>bold text</strong></p>';
|
||||
beforeEach(async () => {
|
||||
renderMarkdown.mockResolvedValue(initialContent);
|
||||
mockRenderMarkdownResponse(initialContent);
|
||||
|
||||
buildWrapper();
|
||||
buildWrapper({
|
||||
markdown: '**bold text**',
|
||||
});
|
||||
|
||||
await waitUntilContentIsLoaded();
|
||||
});
|
||||
|
|
@ -129,4 +135,38 @@ This reference tag is a mix of letters and numbers [^footnote].
|
|||
expect(wrapper.findByTestId('table-of-contents').text()).toContain('Heading 1');
|
||||
expect(wrapper.findByTestId('table-of-contents').text()).toContain('Heading 2');
|
||||
});
|
||||
|
||||
describe('when pasting content', () => {
|
||||
const buildClipboardData = (data = {}) => ({
|
||||
clipboardData: {
|
||||
getData(mimeType) {
|
||||
return data[mimeType];
|
||||
},
|
||||
types: Object.keys(data),
|
||||
},
|
||||
});
|
||||
|
||||
describe('when the clipboard does not contain text/html data', () => {
|
||||
it('processes the clipboard content as markdown', async () => {
|
||||
const processedMarkdown = '<strong>bold text</strong>';
|
||||
|
||||
buildWrapper();
|
||||
|
||||
await waitUntilContentIsLoaded();
|
||||
|
||||
mockRenderMarkdownResponse(processedMarkdown);
|
||||
|
||||
wrapper.find('[contenteditable]').trigger(
|
||||
'paste',
|
||||
buildClipboardData({
|
||||
'text/plain': '**bold text**',
|
||||
}),
|
||||
);
|
||||
|
||||
await waitUntilContentIsLoaded();
|
||||
|
||||
expect(wrapper.find('[contenteditable]').html()).toContain(processedMarkdown);
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -155,7 +155,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
|
|||
services: [{ name: "postgres:9.1" }, { name: "mysql:5.5" }],
|
||||
cache: [{ key: "k", untracked: true, paths: ["public/"], policy: "pull-push", when: 'on_success' }],
|
||||
only: { refs: %w(branches tags) },
|
||||
job_variables: { 'VAR' => 'job' },
|
||||
job_variables: { 'VAR' => { value: 'job' } },
|
||||
root_variables_inheritance: true,
|
||||
after_script: [],
|
||||
ignore: false,
|
||||
|
|
@ -215,7 +215,7 @@ RSpec.describe Gitlab::Ci::Config::Entry::Root do
|
|||
services: [{ name: 'postgres:9.1' }, { name: 'mysql:5.5' }],
|
||||
stage: 'test',
|
||||
cache: [{ key: 'k', untracked: true, paths: ['public/'], policy: 'pull-push', when: 'on_success' }],
|
||||
job_variables: { 'VAR' => 'job' },
|
||||
job_variables: { 'VAR' => { value: 'job' } },
|
||||
root_variables_inheritance: true,
|
||||
ignore: false,
|
||||
after_script: ['make clean'],
|
||||
|
|
|
|||
|
|
@ -104,8 +104,8 @@ RSpec.describe Gitlab::Ci::Pipeline::Seed::Build do
|
|||
|
||||
it do
|
||||
is_expected.to include(yaml_variables: [{ key: 'VAR1', value: 'new var 1' },
|
||||
{ key: 'VAR2', value: 'var 2' },
|
||||
{ key: 'VAR3', value: 'var 3' }])
|
||||
{ key: 'VAR3', value: 'var 3' },
|
||||
{ key: 'VAR2', value: 'var 2' }])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@ require 'spec_helper'
|
|||
|
||||
RSpec.describe Gitlab::Ci::Trace::Archive do
|
||||
context 'with transactional fixtures' do
|
||||
let_it_be(:job) { create(:ci_build, :success, :trace_live) }
|
||||
let_it_be_with_reload(:job) { create(:ci_build, :success, :trace_live) }
|
||||
let_it_be_with_reload(:trace_metadata) { create(:ci_build_trace_metadata, build: job) }
|
||||
let_it_be(:src_checksum) do
|
||||
job.trace.read { |stream| Digest::MD5.hexdigest(stream.raw) }
|
||||
|
|
|
|||
|
|
@ -22,14 +22,14 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
|
|||
|
||||
subject { described_class.merge_variables(current_variables, new_variables) }
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
it { is_expected.to match_array(result) }
|
||||
|
||||
context 'when new variables is a hash' do
|
||||
let(:new_variables) do
|
||||
{ 'key2' => 'value22', 'key3' => 'value3' }
|
||||
end
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
it { is_expected.to match_array(result) }
|
||||
end
|
||||
|
||||
context 'when new variables is a hash with symbol keys' do
|
||||
|
|
@ -37,7 +37,7 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
|
|||
{ key2: 'value22', key3: 'value3' }
|
||||
end
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
it { is_expected.to match_array(result) }
|
||||
end
|
||||
|
||||
context 'when new variables is nil' do
|
||||
|
|
@ -47,69 +47,58 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
|
|||
{ key: 'key2', value: 'value2' }]
|
||||
end
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
it { is_expected.to match_array(result) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.transform_to_yaml_variables' do
|
||||
let(:variables) do
|
||||
{ 'key1' => 'value1', 'key2' => 'value2' }
|
||||
describe '.transform_to_array' do
|
||||
subject { described_class.transform_to_array(variables) }
|
||||
|
||||
context 'when values are strings' do
|
||||
let(:variables) do
|
||||
{ 'key1' => 'value1', 'key2' => 'value2' }
|
||||
end
|
||||
|
||||
let(:result) do
|
||||
[{ key: 'key1', value: 'value1' },
|
||||
{ key: 'key2', value: 'value2' }]
|
||||
end
|
||||
|
||||
it { is_expected.to match_array(result) }
|
||||
end
|
||||
|
||||
let(:result) do
|
||||
[{ key: 'key1', value: 'value1' },
|
||||
{ key: 'key2', value: 'value2' }]
|
||||
end
|
||||
|
||||
subject { described_class.transform_to_yaml_variables(variables) }
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
|
||||
context 'when variables is nil' do
|
||||
let(:variables) {}
|
||||
|
||||
it { is_expected.to eq([]) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.transform_from_yaml_variables' do
|
||||
let(:variables) do
|
||||
[{ key: 'key1', value: 'value1' },
|
||||
{ key: 'key2', value: 'value2' }]
|
||||
it { is_expected.to match_array([]) }
|
||||
end
|
||||
|
||||
let(:result) do
|
||||
{ 'key1' => 'value1', 'key2' => 'value2' }
|
||||
end
|
||||
|
||||
subject { described_class.transform_from_yaml_variables(variables) }
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
|
||||
context 'when variables is nil' do
|
||||
let(:variables) {}
|
||||
|
||||
it { is_expected.to eq({}) }
|
||||
end
|
||||
|
||||
context 'when variables is a hash' do
|
||||
context 'when values are hashes' do
|
||||
let(:variables) do
|
||||
{ key1: 'value1', 'key2' => 'value2' }
|
||||
{ 'key1' => { value: 'value1', description: 'var 1' }, 'key2' => { value: 'value2' } }
|
||||
end
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
end
|
||||
|
||||
context 'when variables contain integers and symbols' do
|
||||
let(:variables) do
|
||||
{ key1: 1, key2: :value2 }
|
||||
let(:result) do
|
||||
[{ key: 'key1', value: 'value1', description: 'var 1' },
|
||||
{ key: 'key2', value: 'value2' }]
|
||||
end
|
||||
|
||||
let(:result1) do
|
||||
{ 'key1' => '1', 'key2' => 'value2' }
|
||||
end
|
||||
it { is_expected.to match_array(result) }
|
||||
|
||||
it { is_expected.to eq(result1) }
|
||||
context 'when a value data has `key` as a key' do
|
||||
let(:variables) do
|
||||
{ 'key1' => { value: 'value1', key: 'new_key1' }, 'key2' => { value: 'value2' } }
|
||||
end
|
||||
|
||||
let(:result) do
|
||||
[{ key: 'key1', value: 'value1' },
|
||||
{ key: 'key2', value: 'value2' }]
|
||||
end
|
||||
|
||||
it 'ignores the key set with "key"' do
|
||||
is_expected.to match_array(result)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -134,7 +123,7 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
|
|||
|
||||
subject { described_class.inherit_yaml_variables(from: from, to: to, inheritance: inheritance) }
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
it { is_expected.to match_array(result) }
|
||||
|
||||
context 'when inheritance is false' do
|
||||
let(:inheritance) { false }
|
||||
|
|
@ -144,7 +133,7 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
|
|||
{ key: 'key3', value: 'value3' }]
|
||||
end
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
it { is_expected.to match_array(result) }
|
||||
end
|
||||
|
||||
context 'when inheritance is array' do
|
||||
|
|
@ -155,7 +144,7 @@ RSpec.describe Gitlab::Ci::Variables::Helpers do
|
|||
{ key: 'key3', value: 'value3' }]
|
||||
end
|
||||
|
||||
it { is_expected.to eq(result) }
|
||||
it { is_expected.to match_array(result) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'fast_spec_helper'
|
||||
require 'rspec-parameterized'
|
||||
|
||||
RSpec.describe GitlabEdition do
|
||||
def remove_instance_variable(ivar)
|
||||
|
|
@ -27,7 +28,57 @@ RSpec.describe GitlabEdition do
|
|||
end
|
||||
end
|
||||
|
||||
describe 'extensions' do
|
||||
describe '.path_glob' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
let(:root) { described_class.root.to_s }
|
||||
|
||||
subject { described_class.path_glob(path) }
|
||||
|
||||
before do
|
||||
allow(described_class).to receive(:jh?).and_return(jh)
|
||||
allow(described_class).to receive(:ee?).and_return(ee)
|
||||
end
|
||||
|
||||
where(:ee, :jh, :path, :expected) do
|
||||
false | false | nil | ''
|
||||
true | false | nil | '{,ee/}'
|
||||
true | true | nil | '{,ee/,jh/}'
|
||||
false | true | nil | '{,ee/,jh/}'
|
||||
false | false | 'app/models' | 'app/models'
|
||||
true | false | 'app/models' | '{,ee/}app/models'
|
||||
true | true | 'app/models' | '{,ee/,jh/}app/models'
|
||||
false | true | 'app/models' | '{,ee/,jh/}app/models'
|
||||
end
|
||||
|
||||
with_them do
|
||||
it { is_expected.to eq("#{root}/#{expected}") }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.extension_path_prefixes' do
|
||||
using RSpec::Parameterized::TableSyntax
|
||||
|
||||
subject { described_class.extension_path_prefixes }
|
||||
|
||||
before do
|
||||
allow(described_class).to receive(:jh?).and_return(jh)
|
||||
allow(described_class).to receive(:ee?).and_return(ee)
|
||||
end
|
||||
|
||||
where(:ee, :jh, :expected) do
|
||||
false | false | ''
|
||||
true | false | '{,ee/}'
|
||||
true | true | '{,ee/,jh/}'
|
||||
false | true | '{,ee/,jh/}'
|
||||
end
|
||||
|
||||
with_them do
|
||||
it { is_expected.to eq(expected) }
|
||||
end
|
||||
end
|
||||
|
||||
describe '.extensions' do
|
||||
context 'when .jh? is true' do
|
||||
before do
|
||||
allow(described_class).to receive(:jh?).and_return(true)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,44 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe 'Mailer previews' do
|
||||
# Setup needed for email previews
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be(:project) { create(:project, :repository, :import_failed, group: group, import_last_error: 'some error') }
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:pipeline) { create(:ci_pipeline, project: project) }
|
||||
let_it_be(:merge_request) { create(:merge_request, source_project: project) }
|
||||
let_it_be(:milestone) { create(:milestone, project: project) }
|
||||
let_it_be(:issue) { create(:issue, project: project, milestone: milestone) }
|
||||
let_it_be(:remote_mirror) { create(:remote_mirror, project: project) }
|
||||
let_it_be(:member) { create(:project_member, :maintainer, project: project, created_by: user) }
|
||||
|
||||
Gitlab.ee do
|
||||
let_it_be(:epic) { create(:epic, group: group) }
|
||||
end
|
||||
|
||||
let(:expected_kind) { [Mail::Message, ActionMailer::MessageDelivery] }
|
||||
|
||||
let(:pending_failures) do
|
||||
{
|
||||
'NotifyPreview#note_merge_request_email_for_diff_discussion' =>
|
||||
'https://gitlab.com/gitlab-org/gitlab/-/issues/372885'
|
||||
}
|
||||
end
|
||||
|
||||
subject { preview.call(email) }
|
||||
|
||||
where(:preview, :email) do
|
||||
ActionMailer::Preview.all.flat_map { |preview| preview.emails.map { |email| [preview, email] } }
|
||||
end
|
||||
|
||||
with_them do
|
||||
it do
|
||||
issue_link = pending_failures["#{preview.name}##{email}"]
|
||||
pending "See #{issue_link}" if issue_link
|
||||
|
||||
is_expected.to be_kind_of(Mail::Message).or(be_kind_of(ActionMailer::MessageDelivery))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -8,6 +8,8 @@ RSpec.describe Ci::JobArtifact do
|
|||
describe "Associations" do
|
||||
it { is_expected.to belong_to(:project) }
|
||||
it { is_expected.to belong_to(:job) }
|
||||
it { is_expected.to validate_presence_of(:job) }
|
||||
it { is_expected.to validate_presence_of(:partition_id) }
|
||||
end
|
||||
|
||||
it { is_expected.to respond_to(:file) }
|
||||
|
|
@ -758,4 +760,26 @@ RSpec.describe Ci::JobArtifact do
|
|||
let!(:model) { create(:ci_job_artifact, project: parent) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'with partition_id' do
|
||||
let(:job) { build(:ci_build, partition_id: 123) }
|
||||
let(:artifact) { build(:ci_job_artifact, job: job, partition_id: nil) }
|
||||
|
||||
it 'copies the partition_id from job' do
|
||||
expect { artifact.valid? }.to change(artifact, :partition_id).from(nil).to(123)
|
||||
end
|
||||
|
||||
context 'when the job is missing' do
|
||||
let(:artifact) do
|
||||
build(:ci_job_artifact,
|
||||
project: build_stubbed(:project),
|
||||
job: nil,
|
||||
partition_id: nil)
|
||||
end
|
||||
|
||||
it 'does not change the partition_id value' do
|
||||
expect { artifact.valid? }.not_to change(artifact, :partition_id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue