diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-13 15:12:17 +0000 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-09-13 15:12:17 +0000 |
commit | 4597f7fe473d9fa622510f8967620006d4bda64e (patch) | |
tree | dafe547a51e57112ad92258f4bf992c014591a88 | |
parent | 37a739daec0d7021b2af6ad03c60d37ac3461d88 (diff) | |
download | gitlab-ce-4597f7fe473d9fa622510f8967620006d4bda64e.tar.gz |
Add latest changes from gitlab-org/gitlab@master
102 files changed, 1767 insertions, 346 deletions
diff --git a/.gitlab/ci/build-images.gitlab-ci.yml b/.gitlab/ci/build-images.gitlab-ci.yml index dbd956214dd..e2c707b6895 100644 --- a/.gitlab/ci/build-images.gitlab-ci.yml +++ b/.gitlab/ci/build-images.gitlab-ci.yml @@ -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} \ diff --git a/.gitlab/ci/rails.gitlab-ci.yml b/.gitlab/ci/rails.gitlab-ci.yml index 967a7ddf924..0f524f03188 100644 --- a/.gitlab/ci/rails.gitlab-ci.yml +++ b/.gitlab/ci/rails.gitlab-ci.yml @@ -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: +db:check-schema: extends: + - .db-job-base - .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 "bundle exec rake db:drop db:create" - 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: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: diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index 8c51b2cb61a..a214959deab 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -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 diff --git a/GITLAB_ELASTICSEARCH_INDEXER_VERSION b/GITLAB_ELASTICSEARCH_INDEXER_VERSION index cb2b00e4f7a..b5021469305 100644 --- a/GITLAB_ELASTICSEARCH_INDEXER_VERSION +++ b/GITLAB_ELASTICSEARCH_INDEXER_VERSION @@ -1 +1 @@ -3.0.1 +3.0.2 diff --git a/app/assets/javascripts/analytics/shared/components/daterange.vue b/app/assets/javascripts/analytics/shared/components/daterange.vue index 7df66d1b2be..5ad4464bc88 100644 --- a/app/assets/javascripts/analytics/shared/components/daterange.vue +++ b/app/assets/javascripts/analytics/shared/components/daterange.vue @@ -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)"> diff --git a/app/assets/javascripts/content_editor/extensions/paste_markdown.js b/app/assets/javascripts/content_editor/extensions/paste_markdown.js index f87e4d8d1dd..848c4c12a9a 100644 --- a/app/assets/javascripts/content_editor/extensions/paste_markdown.js +++ b/app/assets/javascripts/content_editor/extensions/paste_markdown.js @@ -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; diff --git a/app/assets/javascripts/content_editor/services/create_content_editor.js b/app/assets/javascripts/content_editor/services/create_content_editor.js index 7a289df94ea..5ed7f3dc23d 100644 --- a/app/assets/javascripts/content_editor/services/create_content_editor.js +++ b/app/assets/javascripts/content_editor/services/create_content_editor.js @@ -127,7 +127,7 @@ export const createContentEditor = ({ MathInline, OrderedList, Paragraph, - PasteMarkdown, + PasteMarkdown.configure({ eventHub, renderMarkdown }), Reference, ReferenceDefinition, Sourcemap, diff --git a/app/assets/javascripts/cycle_analytics/components/stage_table.vue b/app/assets/javascripts/cycle_analytics/components/stage_table.vue index 85a40b89b77..f1fdffd4b72 100644 --- a/app/assets/javascripts/cycle_analytics/components/stage_table.vue +++ b/app/assets/javascripts/cycle_analytics/components/stage_table.vue @@ -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" diff --git a/app/assets/javascripts/cycle_analytics/components/total_time.vue b/app/assets/javascripts/cycle_analytics/components/total_time.vue index a5a90a56974..725952c3518 100644 --- a/app/assets/javascripts/cycle_analytics/components/total_time.vue +++ b/app/assets/javascripts/cycle_analytics/components/total_time.vue @@ -52,7 +52,7 @@ export default { }; </script> <template> - <span class="total-time"> + <span> <template v-if="hasData"> {{ calculatedTime.duration }} <span>{{ calculatedTime.units }}</span> </template> diff --git a/app/assets/javascripts/design_management/components/list/item.vue b/app/assets/javascripts/design_management/components/list/item.vue index 3092b8554ac..1e36aa686a4 100644 --- a/app/assets/javascripts/design_management/components/list/item.vue +++ b/app/assets/javascripts/design_management/components/list/item.vue @@ -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" diff --git a/app/assets/javascripts/design_management/pages/index.vue b/app/assets/javascripts/design_management/pages/index.vue index 91e35ad3764..07f7a19f7d4 100644 --- a/app/assets/javascripts/design_management/pages/index.vue +++ b/app/assets/javascripts/design_management/pages/index.vue @@ -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" diff --git a/app/assets/javascripts/locale/sprintf.js b/app/assets/javascripts/locale/sprintf.js index e1749331d90..c8c6b51f374 100644 --- a/app/assets/javascripts/locale/sprintf.js +++ b/app/assets/javascripts/locale/sprintf.js @@ -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)); diff --git a/app/assets/javascripts/pages/projects/settings/repository/create_deploy_token/index.js b/app/assets/javascripts/pages/projects/settings/repository/create_deploy_token/index.js index 1dc238b56b4..6a7c6028c95 100644 --- a/app/assets/javascripts/pages/projects/settings/repository/create_deploy_token/index.js +++ b/app/assets/javascripts/pages/projects/settings/repository/create_deploy_token/index.js @@ -1,3 +1 @@ -import initForm from '../form'; - -initForm(); +import '../show/index'; diff --git a/app/assets/javascripts/repository/components/blob_content_viewer.vue b/app/assets/javascripts/repository/components/blob_content_viewer.vue index 78572f11f6f..902077ba3e4 100644 --- a/app/assets/javascripts/repository/components/blob_content_viewer.vue +++ b/app/assets/javascripts/repository/components/blob_content_viewer.vue @@ -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" diff --git a/app/assets/javascripts/repository/components/table/row.vue b/app/assets/javascripts/repository/components/table/row.vue index 49a18f40db9..c8cd64b5311 100644 --- a/app/assets/javascripts/repository/components/table/row.vue +++ b/app/assets/javascripts/repository/components/table/row.vue @@ -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 { diff --git a/app/assets/javascripts/repository/queries/project_info.query.graphql b/app/assets/javascripts/repository/queries/project_info.query.graphql new file mode 100644 index 00000000000..7a380d25bb1 --- /dev/null +++ b/app/assets/javascripts/repository/queries/project_info.query.graphql @@ -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 + } +} diff --git a/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue b/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue index 424cab20c7e..a001b6bdf24 100644 --- a/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue +++ b/app/assets/javascripts/vue_shared/components/upload_dropzone/upload_dropzone.vue @@ -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" > diff --git a/app/assets/javascripts/work_items/components/work_item_detail.vue b/app/assets/javascripts/work_items/components/work_item_detail.vue index 94c37219260..c3733344131 100644 --- a/app/assets/javascripts/work_items/components/work_item_detail.vue +++ b/app/assets/javascripts/work_items/components/work_item_detail.vue @@ -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() { diff --git a/app/assets/javascripts/repository/queries/blob_info.query.graphql b/app/graphql/queries/repository/blob_info.query.graphql index 45a7793e559..fd463436ed4 100644 --- a/app/assets/javascripts/repository/queries/blob_info.query.graphql +++ b/app/graphql/queries/repository/blob_info.query.graphql @@ -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 diff --git a/app/mailers/previews/notify_preview.rb b/app/mailers/previews/notify_preview.rb index 7dfb62dc973..15b6fec3548 100644 --- a/app/mailers/previews/notify_preview.rb +++ b/app/mailers/previews/notify_preview.rb @@ -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 diff --git a/app/models/ci/job_artifact.rb b/app/models/ci/job_artifact.rb index 411ed9805f1..922806a21c3 100644 --- a/app/models/ci/job_artifact.rb +++ b/app/models/ci/job_artifact.rb @@ -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 }) } diff --git a/app/models/concerns/ci/partitionable.rb b/app/models/concerns/ci/partitionable.rb new file mode 100644 index 00000000000..08a4a6c950f --- /dev/null +++ b/app/models/concerns/ci/partitionable.rb @@ -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 diff --git a/app/services/ci/job_artifacts/create_service.rb b/app/services/ci/job_artifacts/create_service.rb index af56eb221d5..3dc097a8603 100644 --- a/app/services/ci/job_artifacts/create_service.rb +++ b/app/services/ci/job_artifacts/create_service.rb @@ -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 } diff --git a/app/views/projects/blob/show.html.haml b/app/views/projects/blob/show.html.haml index 16ecc1cc5a0..33b2229f5d1 100644 --- a/app/views/projects/blob/show.html.haml +++ b/app/views/projects/blob/show.html.haml @@ -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 } } diff --git a/app/views/shared/milestones/_milestone.html.haml b/app/views/shared/milestones/_milestone.html.haml index 59d1537aa2b..01548325c83 100644 --- a/app/views/shared/milestones/_milestone.html.haml +++ b/app/views/shared/milestones/_milestone.html.haml @@ -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 diff --git a/config/environments/development.rb b/config/environments/development.rb index 52ac75dfa2c..5e67ed71954 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -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 diff --git a/config/environments/test.rb b/config/environments/test.rb index f4d3d2ddfda..41413c55ba4 100644 --- a/config/environments/test.rb +++ b/config/environments/test.rb @@ -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 diff --git a/config/metrics/aggregates/code_review.yml b/config/metrics/aggregates/code_review.yml index 7cf61ea9972..e58707b20a5 100644 --- a/config/metrics/aggregates/code_review.yml +++ b/config/metrics/aggregates/code_review.yml @@ -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 diff --git a/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml index 33920c7f312..4d8e4409e73 100644 --- a/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml +++ b/config/metrics/counts_28d/20210216184454_code_review_total_unique_counts_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml index 5224f61c5fc..2c6b21b0f6f 100755 --- a/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml +++ b/config/metrics/counts_28d/20210216184559_ci_templates_total_unique_counts_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20220830104453_i_code_review_merge_request_widget_license_compliance_view_monthly.yml b/config/metrics/counts_28d/20220830104453_i_code_review_merge_request_widget_license_compliance_view_monthly.yml new file mode 100644 index 00000000000..60567037303 --- /dev/null +++ b/config/metrics/counts_28d/20220830104453_i_code_review_merge_request_widget_license_compliance_view_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20220830104500_i_code_review_merge_request_widget_license_compliance_full_report_clicked_monthly.yml b/config/metrics/counts_28d/20220830104500_i_code_review_merge_request_widget_license_compliance_full_report_clicked_monthly.yml new file mode 100644 index 00000000000..3b4c0012495 --- /dev/null +++ b/config/metrics/counts_28d/20220830104500_i_code_review_merge_request_widget_license_compliance_full_report_clicked_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20220830104507_i_code_review_merge_request_widget_license_compliance_expand_monthly.yml b/config/metrics/counts_28d/20220830104507_i_code_review_merge_request_widget_license_compliance_expand_monthly.yml new file mode 100644 index 00000000000..7b0ec9d0518 --- /dev/null +++ b/config/metrics/counts_28d/20220830104507_i_code_review_merge_request_widget_license_compliance_expand_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20220830104514_i_code_review_merge_request_widget_license_compliance_expand_success_monthly.yml b/config/metrics/counts_28d/20220830104514_i_code_review_merge_request_widget_license_compliance_expand_success_monthly.yml new file mode 100644 index 00000000000..c6b7689c844 --- /dev/null +++ b/config/metrics/counts_28d/20220830104514_i_code_review_merge_request_widget_license_compliance_expand_success_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20220830104521_i_code_review_merge_request_widget_license_compliance_expand_warning_monthly.yml b/config/metrics/counts_28d/20220830104521_i_code_review_merge_request_widget_license_compliance_expand_warning_monthly.yml new file mode 100644 index 00000000000..5e164b5c3bf --- /dev/null +++ b/config/metrics/counts_28d/20220830104521_i_code_review_merge_request_widget_license_compliance_expand_warning_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20220830104528_i_code_review_merge_request_widget_license_compliance_expand_failed_monthly.yml b/config/metrics/counts_28d/20220830104528_i_code_review_merge_request_widget_license_compliance_expand_failed_monthly.yml new file mode 100644 index 00000000000..69af6c70299 --- /dev/null +++ b/config/metrics/counts_28d/20220830104528_i_code_review_merge_request_widget_license_compliance_expand_failed_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20220907202807_p_ci_templates_jobs_dependency_scanning_latest_monthly.yml b/config/metrics/counts_28d/20220907202807_p_ci_templates_jobs_dependency_scanning_latest_monthly.yml new file mode 100644 index 00000000000..9cbfee008c3 --- /dev/null +++ b/config/metrics/counts_28d/20220907202807_p_ci_templates_jobs_dependency_scanning_latest_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20220907212005_p_ci_templates_security_container_scanning_latest_monthly.yml b/config/metrics/counts_28d/20220907212005_p_ci_templates_security_container_scanning_latest_monthly.yml new file mode 100644 index 00000000000..fbf263cd6bc --- /dev/null +++ b/config/metrics/counts_28d/20220907212005_p_ci_templates_security_container_scanning_latest_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20220907215635_p_ci_templates_jobs_license_scanning_latest_monthly.yml b/config/metrics/counts_28d/20220907215635_p_ci_templates_jobs_license_scanning_latest_monthly.yml new file mode 100644 index 00000000000..b78e5bc65fa --- /dev/null +++ b/config/metrics/counts_28d/20220907215635_p_ci_templates_jobs_license_scanning_latest_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20220912161240_p_ci_templates_implicit_jobs_dependency_scanning_latest_monthly.yml b/config/metrics/counts_28d/20220912161240_p_ci_templates_implicit_jobs_dependency_scanning_latest_monthly.yml new file mode 100644 index 00000000000..a3a435fca09 --- /dev/null +++ b/config/metrics/counts_28d/20220912161240_p_ci_templates_implicit_jobs_dependency_scanning_latest_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20220912162308_p_ci_templates_implicit_jobs_license_scanning_latest_monthly.yml b/config/metrics/counts_28d/20220912162308_p_ci_templates_implicit_jobs_license_scanning_latest_monthly.yml new file mode 100644 index 00000000000..acc48ff2a44 --- /dev/null +++ b/config/metrics/counts_28d/20220912162308_p_ci_templates_implicit_jobs_license_scanning_latest_monthly.yml @@ -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 diff --git a/config/metrics/counts_28d/20220912162752_p_ci_templates_implicit_security_container_scanning_latest_monthly.yml b/config/metrics/counts_28d/20220912162752_p_ci_templates_implicit_security_container_scanning_latest_monthly.yml new file mode 100644 index 00000000000..2aebbc3a9eb --- /dev/null +++ b/config/metrics/counts_28d/20220912162752_p_ci_templates_implicit_security_container_scanning_latest_monthly.yml @@ -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 diff --git a/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml index 1fe239e7d6f..60619deb786 100644 --- a/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml +++ b/config/metrics/counts_7d/20210216184452_code_review_total_unique_counts_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml index faaf5be63a0..16186a412b8 100755 --- a/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml +++ b/config/metrics/counts_7d/20210216184557_ci_templates_total_unique_counts_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20220830104410_i_code_review_merge_request_widget_license_compliance_view_weekly.yml b/config/metrics/counts_7d/20220830104410_i_code_review_merge_request_widget_license_compliance_view_weekly.yml new file mode 100644 index 00000000000..6e9415bdc42 --- /dev/null +++ b/config/metrics/counts_7d/20220830104410_i_code_review_merge_request_widget_license_compliance_view_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20220830104418_i_code_review_merge_request_widget_license_compliance_full_report_clicked_weekly.yml b/config/metrics/counts_7d/20220830104418_i_code_review_merge_request_widget_license_compliance_full_report_clicked_weekly.yml new file mode 100644 index 00000000000..c3a8d7bfdfb --- /dev/null +++ b/config/metrics/counts_7d/20220830104418_i_code_review_merge_request_widget_license_compliance_full_report_clicked_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20220830104424_i_code_review_merge_request_widget_license_compliance_expand_weekly.yml b/config/metrics/counts_7d/20220830104424_i_code_review_merge_request_widget_license_compliance_expand_weekly.yml new file mode 100644 index 00000000000..69083c5ca2c --- /dev/null +++ b/config/metrics/counts_7d/20220830104424_i_code_review_merge_request_widget_license_compliance_expand_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20220830104431_i_code_review_merge_request_widget_license_compliance_expand_success_weekly.yml b/config/metrics/counts_7d/20220830104431_i_code_review_merge_request_widget_license_compliance_expand_success_weekly.yml new file mode 100644 index 00000000000..d145ae31f38 --- /dev/null +++ b/config/metrics/counts_7d/20220830104431_i_code_review_merge_request_widget_license_compliance_expand_success_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20220830104438_i_code_review_merge_request_widget_license_compliance_expand_warning_weekly.yml b/config/metrics/counts_7d/20220830104438_i_code_review_merge_request_widget_license_compliance_expand_warning_weekly.yml new file mode 100644 index 00000000000..58c3d89497f --- /dev/null +++ b/config/metrics/counts_7d/20220830104438_i_code_review_merge_request_widget_license_compliance_expand_warning_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20220830104446_i_code_review_merge_request_widget_license_compliance_expand_failed_weekly.yml b/config/metrics/counts_7d/20220830104446_i_code_review_merge_request_widget_license_compliance_expand_failed_weekly.yml new file mode 100644 index 00000000000..d8d9637f920 --- /dev/null +++ b/config/metrics/counts_7d/20220830104446_i_code_review_merge_request_widget_license_compliance_expand_failed_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20220907202801_p_ci_templates_jobs_dependency_scanning_latest_weekly.yml b/config/metrics/counts_7d/20220907202801_p_ci_templates_jobs_dependency_scanning_latest_weekly.yml new file mode 100644 index 00000000000..c2a9f72ec8b --- /dev/null +++ b/config/metrics/counts_7d/20220907202801_p_ci_templates_jobs_dependency_scanning_latest_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20220907211959_p_ci_templates_security_container_scanning_latest_weekly.yml b/config/metrics/counts_7d/20220907211959_p_ci_templates_security_container_scanning_latest_weekly.yml new file mode 100644 index 00000000000..8e7c6e8cbaf --- /dev/null +++ b/config/metrics/counts_7d/20220907211959_p_ci_templates_security_container_scanning_latest_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20220907215629_p_ci_templates_jobs_license_scanning_latest_weekly.yml b/config/metrics/counts_7d/20220907215629_p_ci_templates_jobs_license_scanning_latest_weekly.yml new file mode 100644 index 00000000000..f3cb628da5a --- /dev/null +++ b/config/metrics/counts_7d/20220907215629_p_ci_templates_jobs_license_scanning_latest_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20220912161233_p_ci_templates_implicit_jobs_dependency_scanning_latest_weekly.yml b/config/metrics/counts_7d/20220912161233_p_ci_templates_implicit_jobs_dependency_scanning_latest_weekly.yml new file mode 100644 index 00000000000..243d24bcf50 --- /dev/null +++ b/config/metrics/counts_7d/20220912161233_p_ci_templates_implicit_jobs_dependency_scanning_latest_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20220912162301_p_ci_templates_implicit_jobs_license_scanning_latest_weekly.yml b/config/metrics/counts_7d/20220912162301_p_ci_templates_implicit_jobs_license_scanning_latest_weekly.yml new file mode 100644 index 00000000000..8fdd6c15c1d --- /dev/null +++ b/config/metrics/counts_7d/20220912162301_p_ci_templates_implicit_jobs_license_scanning_latest_weekly.yml @@ -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 diff --git a/config/metrics/counts_7d/20220912162745_p_ci_templates_implicit_security_container_scanning_latest_weekly.yml b/config/metrics/counts_7d/20220912162745_p_ci_templates_implicit_security_container_scanning_latest_weekly.yml new file mode 100644 index 00000000000..c3818fb819c --- /dev/null +++ b/config/metrics/counts_7d/20220912162745_p_ci_templates_implicit_security_container_scanning_latest_weekly.yml @@ -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 diff --git a/config/metrics/counts_all/20220825115210_i_merge_request_widget_license_compliance_count_view.yml b/config/metrics/counts_all/20220825115210_i_merge_request_widget_license_compliance_count_view.yml new file mode 100644 index 00000000000..3542f4fd8ac --- /dev/null +++ b/config/metrics/counts_all/20220825115210_i_merge_request_widget_license_compliance_count_view.yml @@ -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 diff --git a/config/metrics/counts_all/20220825115217_i_merge_request_widget_license_compliance_count_full_report_clicked.yml b/config/metrics/counts_all/20220825115217_i_merge_request_widget_license_compliance_count_full_report_clicked.yml new file mode 100644 index 00000000000..580d0d4dff3 --- /dev/null +++ b/config/metrics/counts_all/20220825115217_i_merge_request_widget_license_compliance_count_full_report_clicked.yml @@ -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 diff --git a/config/metrics/counts_all/20220825115224_i_merge_request_widget_license_compliance_count_expand.yml b/config/metrics/counts_all/20220825115224_i_merge_request_widget_license_compliance_count_expand.yml new file mode 100644 index 00000000000..1829e1c87c0 --- /dev/null +++ b/config/metrics/counts_all/20220825115224_i_merge_request_widget_license_compliance_count_expand.yml @@ -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 diff --git a/config/metrics/counts_all/20220825115230_i_merge_request_widget_license_compliance_count_expand_success.yml b/config/metrics/counts_all/20220825115230_i_merge_request_widget_license_compliance_count_expand_success.yml new file mode 100644 index 00000000000..4a8f35a7c5b --- /dev/null +++ b/config/metrics/counts_all/20220825115230_i_merge_request_widget_license_compliance_count_expand_success.yml @@ -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 diff --git a/config/metrics/counts_all/20220825115236_i_merge_request_widget_license_compliance_count_expand_warning.yml b/config/metrics/counts_all/20220825115236_i_merge_request_widget_license_compliance_count_expand_warning.yml new file mode 100644 index 00000000000..1ebc20fca26 --- /dev/null +++ b/config/metrics/counts_all/20220825115236_i_merge_request_widget_license_compliance_count_expand_warning.yml @@ -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 diff --git a/config/metrics/counts_all/20220825115242_i_merge_request_widget_license_compliance_count_expand_failed.yml b/config/metrics/counts_all/20220825115242_i_merge_request_widget_license_compliance_count_expand_failed.yml new file mode 100644 index 00000000000..7fe8263a53e --- /dev/null +++ b/config/metrics/counts_all/20220825115242_i_merge_request_widget_license_compliance_count_expand_failed.yml @@ -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 diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 742f09124fd..a6cc582e12d 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -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. | diff --git a/doc/api/product_analytics.md b/doc/api/product_analytics.md new file mode 100644 index 00000000000..c3114baff8a --- /dev/null +++ b/doc/api/product_analytics.md @@ -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 + } +} +``` diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md index 6999ffe810e..2ff51e765a3 100644 --- a/doc/development/contributing/index.md +++ b/doc/development/contributing/index.md @@ -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! diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md index 89e54183e50..87d2930dcb5 100644 --- a/doc/development/documentation/feature_flags.md +++ b/doc/development/documentation/feature_flags.md @@ -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: diff --git a/doc/development/documentation/versions.md b/doc/development/documentation/versions.md index acc0e870d24..85733603cfe 100644 --- a/doc/development/documentation/versions.md +++ b/doc/development/documentation/versions.md @@ -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 diff --git a/doc/development/testing_guide/flaky_tests.md b/doc/development/testing_guide/flaky_tests.md index 3c8df7d3416..7409f15969d 100644 --- a/doc/development/testing_guide/flaky_tests.md +++ b/doc/development/testing_guide/flaky_tests.md @@ -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> diff --git a/doc/integration/advanced_search/elasticsearch.md b/doc/integration/advanced_search/elasticsearch.md index bab7deb9fec..93118cc7eb2 100644 --- a/doc/integration/advanced_search/elasticsearch.md +++ b/doc/integration/advanced_search/elasticsearch.md @@ -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 diff --git a/doc/user/markdown.md b/doc/user/markdown.md index 03873394aa2..d61190fbd31 100644 --- a/doc/user/markdown.md +++ b/doc/user/markdown.md @@ -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). diff --git a/lib/gitlab/ci/config/entry/processable.rb b/lib/gitlab/ci/config/entry/processable.rb index 6077d70a080..2d2032b1d8c 100644 --- a/lib/gitlab/ci/config/entry/processable.rb +++ b/lib/gitlab/ci/config/entry/processable.rb @@ -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, diff --git a/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.latest.gitlab-ci.yml new file mode 100644 index 00000000000..70f85382967 --- /dev/null +++ b/lib/gitlab/ci/templates/Jobs/Dependency-Scanning.latest.gitlab-ci.yml @@ -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 diff --git a/lib/gitlab/ci/templates/Jobs/License-Scanning.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Jobs/License-Scanning.latest.gitlab-ci.yml new file mode 100644 index 00000000000..e47f669c2e2 --- /dev/null +++ b/lib/gitlab/ci/templates/Jobs/License-Scanning.latest.gitlab-ci.yml @@ -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/ diff --git a/lib/gitlab/ci/templates/Security/Container-Scanning.latest.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/Container-Scanning.latest.gitlab-ci.yml new file mode 100644 index 00000000000..f7b1d12b3b3 --- /dev/null +++ b/lib/gitlab/ci/templates/Security/Container-Scanning.latest.gitlab-ci.yml @@ -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 diff --git a/lib/gitlab/ci/variables/helpers.rb b/lib/gitlab/ci/variables/helpers.rb index a77ca71b9cf..16e3afd8620 100644 --- a/lib/gitlab/ci/variables/helpers.rb +++ b/lib/gitlab/ci/variables/helpers.rb @@ -6,24 +6,24 @@ 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) - ) - end + 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) - def transform_to_yaml_variables(vars) - vars.to_h.map do |key, value| - { key: key.to_s, value: value } - end + (new_vars + current_vars).uniq { |var| var[:key] } end - def transform_from_yaml_variables(vars) - return vars.stringify_keys.transform_values(&:to_s) if vars.is_a?(Hash) + def transform_to_array(vars) + return [] if vars.blank? - vars.to_a.to_h { |var| [var[:key].to_s, var[:value]] } + 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 inherit_yaml_variables(from:, to:, inheritance:) @@ -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 diff --git a/lib/gitlab/ci/yaml_processor/result.rb b/lib/gitlab/ci/yaml_processor/result.rb index 4bd1ac3b67f..f203f88442d 100644 --- a/lib/gitlab/ci/yaml_processor/result.rb +++ b/lib/gitlab/ci/yaml_processor/result.rb @@ -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 diff --git a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml index c4074f70d91..10e36a75a3a 100644 --- a/lib/gitlab/usage_data_counters/known_events/ci_templates.yml +++ b/lib/gitlab/usage_data_counters/known_events/ci_templates.yml @@ -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 diff --git a/lib/gitlab/usage_data_counters/known_events/code_review_events.yml b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml index d8204e81221..f854fcb1771 100644 --- a/lib/gitlab/usage_data_counters/known_events/code_review_events.yml +++ b/lib/gitlab/usage_data_counters/known_events/code_review_events.yml @@ -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 diff --git a/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb b/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb index dafc36ab7ce..f88bbc41c70 100644 --- a/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb +++ b/lib/gitlab/usage_data_counters/merge_request_widget_extension_counter.rb @@ -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 diff --git a/lib/gitlab_edition.rb b/lib/gitlab_edition.rb index 02006148a34..5e3ed35ace4 100644 --- a/lib/gitlab_edition.rb +++ b/lib/gitlab_edition.rb @@ -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] diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 914bc7fdf89..bea2ef2c9c4 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -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 "" diff --git a/rubocop/cop/gitlab/avoid_feature_get.rb b/rubocop/cop/gitlab/avoid_feature_get.rb index abde1383fca..7664f66521a 100644 --- a/rubocop/cop/gitlab/avoid_feature_get.rb +++ b/rubocop/cop/gitlab/avoid_feature_get.rb @@ -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`. ' \ diff --git a/spec/frontend/content_editor/extensions/paste_markdown_spec.js b/spec/frontend/content_editor/extensions/paste_markdown_spec.js index 53efda6aee2..30e798e8817 100644 --- a/spec/frontend/content_editor/extensions/paste_markdown_spec.js +++ b/spec/frontend/content_editor/extensions/paste_markdown_spec.js @@ -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(); diff --git a/spec/frontend/cycle_analytics/__snapshots__/total_time_spec.js.snap b/spec/frontend/cycle_analytics/__snapshots__/total_time_spec.js.snap index 7f211c1028e..92927ef16ec 100644 --- a/spec/frontend/cycle_analytics/__snapshots__/total_time_spec.js.snap +++ b/spec/frontend/cycle_analytics/__snapshots__/total_time_spec.js.snap @@ -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>" `; diff --git a/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap b/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap index 8fe3e92360a..096d776a7d2 100644 --- a/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap +++ b/spec/frontend/design_management/components/list/__snapshots__/item_spec.js.snap @@ -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]" diff --git a/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap b/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap index 9997f02cd01..8cfe11c9040 100644 --- a/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap +++ b/spec/frontend/design_management/pages/__snapshots__/index_spec.js.snap @@ -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" diff --git a/spec/frontend/design_management/pages/index_spec.js b/spec/frontend/design_management/pages/index_spec.js index f90feaadfb0..1033b509419 100644 --- a/spec/frontend/design_management/pages/index_spec.js +++ b/spec/frontend/design_management/pages/index_spec.js @@ -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', ]); }); }); diff --git a/spec/frontend/locale/sprintf_spec.js b/spec/frontend/locale/sprintf_spec.js index 52e903b819f..e0d0e117ea4 100644 --- a/spec/frontend/locale/sprintf_spec.js +++ b/spec/frontend/locale/sprintf_spec.js @@ -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%'); + }); }); }); }); diff --git a/spec/frontend/repository/components/blob_content_viewer_spec.js b/spec/frontend/repository/components/blob_content_viewer_spec.js index 0f7cf4e61b2..6ece72c41bb 100644 --- a/spec/frontend/repository/components/blob_content_viewer_spec.js +++ b/spec/frontend/repository/components/blob_content_viewer_spec.js @@ -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, + repository: { + empty, + blobs: { nodes: [blob] }, + }, + }; + + const projectInfo = { + __typename: 'Project', + id: '123', userPermissions: { pushCode, forkProject, downloadCode, createMergeRequestIn, }, - repository: { - empty, - blobs: { nodes: [blob] }, + pathLocks: { + nodes: [ + { + id: 'test', + path: 'locked_file.js', + user: { id: '123', username: 'root' }, + }, + ], }, }; - mockResolver = jest.fn().mockResolvedValue({ - data: { isBinary, project }, + 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', }), diff --git a/spec/frontend/repository/mock_data.js b/spec/frontend/repository/mock_data.js index 4db295fe0b7..cda47a5b0a5 100644 --- a/spec/frontend/repository/mock_data.js +++ b/spec/frontend/repository/mock_data.js @@ -1,4 +1,5 @@ export const simpleViewerMock = { + __typename: 'RepositoryBlob', id: '1', name: 'some_file.js', size: 123, diff --git a/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap b/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap index 1798ca5ccde..f9d615d4f68 100644 --- a/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap +++ b/spec/frontend/vue_shared/components/upload_dropzone/__snapshots__/upload_dropzone_spec.js.snap @@ -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 diff --git a/spec/frontend/work_items/components/work_item_detail_spec.js b/spec/frontend/work_items/components/work_item_detail_spec.js index 49f7957440d..351a363590c 100644 --- a/spec/frontend/work_items/components/work_item_detail_spec.js +++ b/spec/frontend/work_items/components/work_item_detail_spec.js @@ -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', () => { diff --git a/spec/frontend_integration/content_editor/content_editor_integration_spec.js b/spec/frontend_integration/content_editor/content_editor_integration_spec.js index 7781a463fd6..c0c6b5e5dc8 100644 --- a/spec/frontend_integration/content_editor/content_editor_integration_spec.js +++ b/spec/frontend_integration/content_editor/content_editor_integration_spec.js @@ -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); + }); + }); + }); }); diff --git a/spec/lib/gitlab/ci/config/entry/root_spec.rb b/spec/lib/gitlab/ci/config/entry/root_spec.rb index 19a4c82dcc1..3d19987a0be 100644 --- a/spec/lib/gitlab/ci/config/entry/root_spec.rb +++ b/spec/lib/gitlab/ci/config/entry/root_spec.rb @@ -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'], diff --git a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb index b6cb07bf119..75f6a773c2d 100644 --- a/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb +++ b/spec/lib/gitlab/ci/pipeline/seed/build_spec.rb @@ -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 diff --git a/spec/lib/gitlab/ci/trace/archive_spec.rb b/spec/lib/gitlab/ci/trace/archive_spec.rb index 3ae0e5d1f0e..f91cb03883a 100644 --- a/spec/lib/gitlab/ci/trace/archive_spec.rb +++ b/spec/lib/gitlab/ci/trace/archive_spec.rb @@ -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) } diff --git a/spec/lib/gitlab/ci/variables/helpers_spec.rb b/spec/lib/gitlab/ci/variables/helpers_spec.rb index ece456ee2d3..fb1e66bd605 100644 --- a/spec/lib/gitlab/ci/variables/helpers_spec.rb +++ b/spec/lib/gitlab/ci/variables/helpers_spec.rb @@ -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' } - end + describe '.transform_to_array' do + subject { described_class.transform_to_array(variables) } - 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 + context 'when values are strings' do + let(:variables) do + { 'key1' => 'value1', 'key2' => 'value2' } + end - describe '.transform_from_yaml_variables' do - let(:variables) do - [{ key: 'key1', value: 'value1' }, - { key: 'key2', value: 'value2' }] - end + let(:result) do + [{ key: 'key1', value: 'value1' }, + { key: 'key2', value: 'value2' }] + end - let(:result) do - { 'key1' => 'value1', 'key2' => 'value2' } + it { is_expected.to match_array(result) } 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({}) } + it { is_expected.to match_array([]) } 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) } + + context 'when a value data has `key` as a key' do + let(:variables) do + { 'key1' => { value: 'value1', key: 'new_key1' }, 'key2' => { value: 'value2' } } + end - it { is_expected.to eq(result1) } + 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 diff --git a/spec/lib/gitlab_edition_spec.rb b/spec/lib/gitlab_edition_spec.rb index 0ee63279984..46be1471896 100644 --- a/spec/lib/gitlab_edition_spec.rb +++ b/spec/lib/gitlab_edition_spec.rb @@ -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) diff --git a/spec/mailers/previews_spec.rb b/spec/mailers/previews_spec.rb new file mode 100644 index 00000000000..14bd56e5d40 --- /dev/null +++ b/spec/mailers/previews_spec.rb @@ -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 diff --git a/spec/models/ci/job_artifact_spec.rb b/spec/models/ci/job_artifact_spec.rb index f31edb747bd..1962d232f3d 100644 --- a/spec/models/ci/job_artifact_spec.rb +++ b/spec/models/ci/job_artifact_spec.rb @@ -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 diff --git a/spec/services/ci/job_artifacts/create_service_spec.rb b/spec/services/ci/job_artifacts/create_service_spec.rb index 6809b694b22..a2259f9813b 100644 --- a/spec/services/ci/job_artifacts/create_service_spec.rb +++ b/spec/services/ci/job_artifacts/create_service_spec.rb @@ -181,6 +181,18 @@ RSpec.describe Ci::JobArtifacts::CreateService do end end + context 'with job partitioning' do + let(:job) { create(:ci_build, project: project, partition_id: 123) } + + it 'sets partition_id on artifacts' do + expect { subject }.to change { Ci::JobArtifact.count } + + artifacts_partitions = job.job_artifacts.map(&:partition_id).uniq + + expect(artifacts_partitions).to eq([123]) + end + end + shared_examples 'rescues object storage error' do |klass, message, expected_message| it "handles #{klass}" do allow_next_instance_of(JobArtifactUploader) do |uploader| diff --git a/tests.yml b/tests.yml index d38b05af991..c530ec30416 100644 --- a/tests.yml +++ b/tests.yml @@ -69,3 +69,9 @@ mapping: - source: lib/gitlab/usage_data_counters/known_events/.+\.yml test: spec/lib/gitlab/usage_data_spec.rb + # Mailer previews + - source: (ee/)?app/mailers/previews/.+\.rb + test: spec/mailers/previews_spec.rb + - source: ee/app/mailers/ee/preview/.+\.rb + test: spec/mailers/previews_spec.rb + |