Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2023-02-06 18:08:52 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2023-02-06 18:08:52 +0300
commit7b69a22d499787378aa30561822ef797a99c22e5 (patch)
tree630c757f4b55abd7ee445def6577587ec57e860d
parentd75e21489f113731bfe02b6c88e58879b5859103 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--.gitlab/ci/docs.gitlab-ci.yml10
-rw-r--r--.gitlab/ci/review-apps/main.gitlab-ci.yml26
-rw-r--r--.gitlab/ci/review.gitlab-ci.yml18
-rw-r--r--.gitlab/ci/rules.gitlab-ci.yml25
-rw-r--r--app/assets/javascripts/deprecated_notes.js33
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue2
-rw-r--r--app/controllers/projects/cycle_analytics_controller.rb2
-rw-r--r--app/finders/protected_branches_finder.rb14
-rw-r--r--app/models/analytics/cycle_analytics/project_level.rb4
-rw-r--r--app/models/analytics/cycle_analytics/project_stage.rb33
-rw-r--r--app/models/analytics/cycle_analytics/project_value_stream.rb22
-rw-r--r--app/models/analytics/cycle_analytics/stage_event_hash.rb7
-rw-r--r--app/models/issue.rb13
-rw-r--r--app/models/project.rb3
-rw-r--r--app/workers/projects/refresh_build_artifacts_size_statistics_worker.rb1
-rw-r--r--db/docs/analytics_cycle_analytics_project_stages.yml3
-rw-r--r--db/docs/analytics_cycle_analytics_project_value_streams.yml3
-rw-r--r--db/post_migrate/20230112141236_schedule_vulnerabilities_feedback_migration2.rb17
-rw-r--r--db/post_migrate/20230119123256_add_fk_index_to_ci_resources_on_partition_id_and_build_id.rb17
-rw-r--r--db/post_migrate/20230119123257_add_fk_to_ci_resources_on_partition_id_and_build_id.rb32
-rw-r--r--db/post_migrate/20230119123258_validate_fk_on_ci_resources_partition_id_and_build_id.rb15
-rw-r--r--db/post_migrate/20230119123259_remove_fk_to_ci_builds_ci_resources_on_build_id.rb30
-rw-r--r--db/post_migrate/20230203122602_schedule_vulnerabilities_feedback_migration3.rb45
-rw-r--r--db/schema_migrations/202301191232561
-rw-r--r--db/schema_migrations/202301191232571
-rw-r--r--db/schema_migrations/202301191232581
-rw-r--r--db/schema_migrations/202301191232591
-rw-r--r--db/schema_migrations/202302031226021
-rw-r--r--db/structure.sql4
-rw-r--r--doc/administration/logs/index.md13
-rw-r--r--doc/api/api_resources.md1
-rw-r--r--doc/api/draft_notes.md43
-rw-r--r--doc/api/member_roles.md116
-rw-r--r--doc/architecture/blueprints/_template.md4
-rw-r--r--doc/architecture/blueprints/object_storage/index.md2
-rw-r--r--doc/architecture/blueprints/rate_limiting/index.md2
-rw-r--r--doc/architecture/blueprints/runner_tokens/index.md2
-rw-r--r--doc/development/gitlab_shell/index.md2
-rw-r--r--doc/development/secure_coding_guidelines.md2
-rw-r--r--doc/development/value_stream_analytics.md2
-rw-r--r--doc/operations/metrics/embed_grafana.md8
-rw-r--r--doc/topics/plan_and_track.md1
-rw-r--r--doc/topics/your_work.md18
-rw-r--r--doc/user/project/issues/crosslinking_issues.md7
-rw-r--r--doc/user/project/repository/vscode.md3
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb4
-rw-r--r--lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb2
-rw-r--r--lib/gitlab/analytics/cycle_analytics/data_collector.rb2
-rw-r--r--lib/gitlab/analytics/cycle_analytics/default_stages.rb2
-rw-r--r--lib/gitlab/analytics/cycle_analytics/request_params.rb2
-rw-r--r--locale/gitlab.pot3
-rwxr-xr-xscripts/lint-docs-blueprints.rb86
-rw-r--r--spec/db/schema_spec.rb3
-rw-r--r--spec/factories/analytics/cycle_analytics/project_stages.rb16
-rw-r--r--spec/factories/analytics/cycle_analytics/project_value_streams.rb9
-rw-r--r--spec/factories/analytics/cycle_analytics/stages.rb8
-rw-r--r--spec/finders/analytics/cycle_analytics/stage_finder_spec.rb2
-rw-r--r--spec/finders/protected_branches_finder_spec.rb56
-rw-r--r--spec/frontend/notes/deprecated_notes_spec.js46
-rw-r--r--spec/lib/banzai/filter/references/issue_reference_filter_spec.rb50
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/average_spec.rb2
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb4
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb4
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb8
-rw-r--r--spec/lib/gitlab/analytics/cycle_analytics/sorting_spec.rb2
-rw-r--r--spec/migrations/20230203122602_schedule_vulnerabilities_feedback_migration3_spec.rb (renamed from spec/migrations/20230112141236_schedule_vulnerabilities_feedback_migration2_spec.rb)2
-rw-r--r--spec/models/analytics/cycle_analytics/project_stage_spec.rb50
-rw-r--r--spec/models/analytics/cycle_analytics/project_value_stream_spec.rb39
-rw-r--r--spec/models/analytics/cycle_analytics/stage_event_hash_spec.rb3
-rw-r--r--spec/models/cycle_analytics/project_level_stage_adapter_spec.rb9
-rw-r--r--spec/models/project_spec.rb2
-rw-r--r--spec/serializers/analytics/cycle_analytics/stage_entity_spec.rb2
-rw-r--r--spec/support/helpers/ci/template_helpers.rb23
-rw-r--r--spec/support/rspec_order_todo.yml2
-rw-r--r--spec/workers/projects/refresh_build_artifacts_size_statistics_worker_spec.rb2
77 files changed, 735 insertions, 324 deletions
diff --git a/.gitlab/ci/docs.gitlab-ci.yml b/.gitlab/ci/docs.gitlab-ci.yml
index d47650e0f83..f7783cc1d33 100644
--- a/.gitlab/ci/docs.gitlab-ci.yml
+++ b/.gitlab/ci/docs.gitlab-ci.yml
@@ -70,6 +70,16 @@ docs-lint markdown:
script:
- scripts/lint-doc.sh
+docs-lint blueprint:
+ extends:
+ - .default-retry
+ - .docs:rules:docs-blueprints-lint
+ image: ${GITLAB_DEPENDENCY_PROXY_ADDRESS}ruby:${RUBY_VERSION}-slim
+ stage: lint
+ needs: []
+ script:
+ - scripts/lint-docs-blueprints.rb
+
docs code_quality:
extends:
- .reports:rules:code_quality
diff --git a/.gitlab/ci/review-apps/main.gitlab-ci.yml b/.gitlab/ci/review-apps/main.gitlab-ci.yml
index a9ebf3b1120..2b22d96fc2d 100644
--- a/.gitlab/ci/review-apps/main.gitlab-ci.yml
+++ b/.gitlab/ci/review-apps/main.gitlab-ci.yml
@@ -100,7 +100,7 @@ review-build-cng:
environment:
name: review/${CI_COMMIT_REF_SLUG}${SCHEDULE_TYPE} # No separator for SCHEDULE_TYPE so it's compatible as before and looks nice without it
url: https://gitlab-${CI_ENVIRONMENT_SLUG}.${REVIEW_APPS_DOMAIN}
- on_stop: review-stop
+ on_stop: trigger-review-stop
review-deploy:
extends:
@@ -173,12 +173,6 @@ review-deploy-sample-projects:
# because some repos are private and CI_JOB_TOKEN cannot access files.
# See https://gitlab.com/gitlab-org/gitlab/issues/191273
GIT_DEPTH: 1
- before_script:
- - source ./scripts/utils.sh
- - source ./scripts/review_apps/review-apps.sh
- - !reference [".use-kube-context", before_script]
- script:
- - retry delete_helm_release
review-delete-deployment:
extends:
@@ -186,11 +180,23 @@ review-delete-deployment:
- .review:rules:review-delete-deployment
dependencies: []
stage: prepare
+ before_script:
+ - source ./scripts/utils.sh
+ - source ./scripts/review_apps/review-apps.sh
+ - !reference [".use-kube-context", before_script]
+ script:
+ - retry delete_helm_release
-review-stop:
+trigger-review-stop:
extends:
- .review-stop-base
- - .review:rules:review-stop
- resource_group: review/${CI_COMMIT_REF_SLUG}${SCHEDULE_TYPE} # CI_ENVIRONMENT_SLUG is not available here and we want this to be the same as the environment
+ - .review:rules:trigger-review-stop
stage: deploy
needs: []
+ before_script:
+ - source ./scripts/utils.sh
+ - install_gitlab_gem
+ script:
+ - review_stop_job_id="$(scripts/api/get_job_id.rb --pipeline-id "${PARENT_PIPELINE_ID}" --job-name "review-stop")"
+ - |
+ curl --request POST --header "Private-Token: ${PROJECT_TOKEN_FOR_CI_SCRIPTS_API_USAGE}" "${CI_API_V4_URL}/projects/${CI_PROJECT_ID}/jobs/${review_stop_job_id}/play"
diff --git a/.gitlab/ci/review.gitlab-ci.yml b/.gitlab/ci/review.gitlab-ci.yml
index 20e4dec7dbf..f0e87e0161a 100644
--- a/.gitlab/ci/review.gitlab-ci.yml
+++ b/.gitlab/ci/review.gitlab-ci.yml
@@ -4,9 +4,12 @@ review-cleanup:
- .review:rules:review-cleanup
image: ${REVIEW_APPS_IMAGE}
stage: prepare
+ needs: []
environment:
name: review/regular-cleanup
action: access
+ variables:
+ GIT_DEPTH: 1
before_script:
- source scripts/utils.sh
- !reference [".use-kube-context", before_script]
@@ -15,6 +18,21 @@ review-cleanup:
script:
- scripts/review_apps/automated_cleanup.rb || (scripts/slack review-apps-monitoring "☠️ \`${CI_JOB_NAME}\` failed! ☠️ See ${CI_JOB_URL} - <https://gitlab.com/gitlab-org/quality/engineering-productivity/team/-/blob/main/runbooks/review-apps.md#review-cleanup-job-failed|📗 RUNBOOK 📕>" warning "GitLab Bot" && exit 1);
+review-stop:
+ extends:
+ - review-cleanup
+ - .review:rules:review-stop
+ environment:
+ name: review/${CI_COMMIT_REF_SLUG}${SCHEDULE_TYPE} # No separator for SCHEDULE_TYPE so it's compatible as before and looks nice without it
+ action: stop
+ resource_group: review/${CI_COMMIT_REF_SLUG}${SCHEDULE_TYPE} # CI_ENVIRONMENT_SLUG is not available here and we want this to be the same as the environment
+ before_script:
+ - source ./scripts/utils.sh
+ - source ./scripts/review_apps/review-apps.sh
+ - !reference [".use-kube-context", before_script]
+ script:
+ - retry delete_helm_release
+
.base-review-checks:
extends:
- .default-retry
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml
index ebc8cd49968..ced63024fc3 100644
--- a/.gitlab/ci/rules.gitlab-ci.yml
+++ b/.gitlab/ci/rules.gitlab-ci.yml
@@ -228,6 +228,11 @@
- "scripts/lint-doc.sh"
- ".gitlab/ci/docs.gitlab-ci.yml"
+.docs-blueprints-patterns: &docs-blueprints-patterns
+ - "doc/architecture/blueprints/**/*"
+ - "scripts/lint-docs-blueprints.rb"
+ - ".gitlab/ci/docs.gitlab-ci.yml"
+
.docs-deprecations-and-removals-patterns: &docs-deprecations-and-removals-patterns
- "doc/update/deprecations.md"
- "doc/update/removals.md"
@@ -851,6 +856,11 @@
- <<: *if-default-refs
changes: *docs-patterns
+.docs:rules:docs-blueprints-lint:
+ rules:
+ - <<: *if-default-refs
+ changes: *docs-blueprints-patterns
+
.docs:rules:deprecations-and-removals:
rules:
- <<: *if-default-refs
@@ -2060,7 +2070,7 @@
# The following rules needs to be the same as the one for .review:rules:start-review-app-pipeline
# except that:
# - all rules have `when: manual` and `allow_failure: true` here
-.review:rules:review-cleanup:
+.review:rules:review-stop-merge-requests:
rules:
- <<: *if-not-ee
when: never
@@ -2097,9 +2107,20 @@
changes: *code-patterns
when: manual
allow_failure: true
+
+.review:rules:review-cleanup:
+ rules:
+ - !reference [".review:rules:review-stop-merge-requests", rules]
- <<: *if-dot-com-ee-schedule-default-branch-maintenance
allow_failure: true
+.review:rules:review-stop:
+ rules:
+ - !reference [".review:rules:review-stop-merge-requests", rules]
+ - <<: *if-dot-com-gitlab-org-schedule
+ when: manual
+ allow_failure: true
+
.review:rules:review-k8s-resources-count-checks:
rules:
- <<: *if-dot-com-ee-schedule-default-branch-maintenance
@@ -2118,7 +2139,7 @@
- "scripts/review_apps/gcp-quotas-checks.rb"
allow_failure: true
-.review:rules:review-stop:
+.review:rules:trigger-review-stop:
rules:
- when: manual
allow_failure: true
diff --git a/app/assets/javascripts/deprecated_notes.js b/app/assets/javascripts/deprecated_notes.js
index 8019a10a042..7503df9194b 100644
--- a/app/assets/javascripts/deprecated_notes.js
+++ b/app/assets/javascripts/deprecated_notes.js
@@ -17,6 +17,7 @@ import { escape, uniqueId } from 'lodash';
import Vue from 'vue';
import { renderGFM } from '~/behaviors/markdown/render_gfm';
import { createAlert, VARIANT_INFO } from '~/flash';
+import { sanitize } from '~/lib/dompurify';
import '~/lib/utils/jquery_at_who';
import AjaxCache from '~/lib/utils/ajax_cache';
import { loadingIconForLegacyJS } from '~/loading_icon_for_legacy_js';
@@ -517,8 +518,36 @@ export default class Notes {
if (discussionContainer.length === 0) {
if (noteEntity.diff_discussion_html) {
const discussionElement = document.createElement('table');
- // eslint-disable-next-line no-unsanitized/method
- discussionElement.insertAdjacentHTML('afterbegin', noteEntity.diff_discussion_html);
+ let internalNote;
+ let discussionDOM;
+
+ if (!noteEntity.on_image) {
+ /*
+ DOMPurify will strip table-less <tr>/<td>, so to get it to stop deleting
+ nodes (since our note HTML starts with a table-less <tr>), we need to wrap
+ the noteEntity discussion HTML in a <table> to perform the other
+ sanitization.
+ */
+ internalNote = sanitize(`<table>${noteEntity.diff_discussion_html}</table>`, {
+ RETURN_DOM: true,
+ });
+ /*
+ Since we wrapped the <tr> in a <table>, we need to extract the <tr> back out.
+ DOMPurify returns a Body Element, so we have to start there, then get the
+ wrapping table, and then get the content we actually want.
+ Curiously, DOMPurify **ADDS** a totally novel <tbody>, so we're actually
+ inserting a completely as-yet-unseen <tbody> element here.
+ */
+ discussionDOM = internalNote.querySelector('table').firstChild;
+ } else {
+ // Image comments don't need <table> manipulation, they're already <div>s
+ internalNote = sanitize(noteEntity.diff_discussion_html, {
+ RETURN_DOM: true,
+ });
+ discussionDOM = internalNote.firstChild;
+ }
+
+ discussionElement.insertAdjacentElement('afterbegin', discussionDOM);
renderGFM(discussionElement);
const $discussion = $(discussionElement).unwrap();
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue
index 7c283c42a03..697d953874c 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/approvals/approvals_summary.vue
@@ -67,7 +67,7 @@ export default {
rulesLeft() {
return getApprovalRuleNamesLeft(
this.multipleApprovalRulesAvailable,
- (this.approvalState.approvalState?.rules || []).filter((r) => r.approvalsRequired !== 0),
+ (this.approvalState.approvalState?.rules || []).filter((r) => !r.approved),
);
},
approvalLeftMessage() {
diff --git a/app/controllers/projects/cycle_analytics_controller.rb b/app/controllers/projects/cycle_analytics_controller.rb
index 63c1378ad11..9fe44659250 100644
--- a/app/controllers/projects/cycle_analytics_controller.rb
+++ b/app/controllers/projects/cycle_analytics_controller.rb
@@ -48,7 +48,7 @@ class Projects::CycleAnalyticsController < Projects::ApplicationController
end
def load_value_stream
- @value_stream = Analytics::CycleAnalytics::ProjectValueStream.build_default_value_stream(@project)
+ @value_stream = Analytics::CycleAnalytics::ValueStream.build_default_value_stream(@project.project_namespace)
end
def cycle_analytics_json
diff --git a/app/finders/protected_branches_finder.rb b/app/finders/protected_branches_finder.rb
index a452a1f993b..dfc9a64737d 100644
--- a/app/finders/protected_branches_finder.rb
+++ b/app/finders/protected_branches_finder.rb
@@ -11,15 +11,21 @@
class ProtectedBranchesFinder
LIMIT = 100
- attr_accessor :project, :params
+ attr_accessor :project_or_group, :params
- def initialize(project, params = {})
- @project = project
+ def initialize(project_or_group, params = {})
+ @project_or_group = project_or_group
@params = params
end
def execute
- protected_branches = project.limited_protected_branches(LIMIT)
+ protected_branches = if project_or_group.is_a?(Group)
+ project_or_group.protected_branches
+ else
+ project_or_group.all_protected_branches
+ end
+
+ protected_branches = protected_branches.limit(LIMIT)
by_name(protected_branches)
end
diff --git a/app/models/analytics/cycle_analytics/project_level.rb b/app/models/analytics/cycle_analytics/project_level.rb
index d43793f60c9..813263fe833 100644
--- a/app/models/analytics/cycle_analytics/project_level.rb
+++ b/app/models/analytics/cycle_analytics/project_level.rb
@@ -33,8 +33,8 @@ module Analytics
private
def build_stage(stage_name)
- stage_params = stage_params_by_name(stage_name).merge(project: project)
- Analytics::CycleAnalytics::ProjectStage.new(stage_params)
+ stage_params = stage_params_by_name(stage_name).merge(namespace: project.project_namespace)
+ Analytics::CycleAnalytics::Stage.new(stage_params)
end
def stage_params_by_name(name)
diff --git a/app/models/analytics/cycle_analytics/project_stage.rb b/app/models/analytics/cycle_analytics/project_stage.rb
deleted file mode 100644
index 7e121399b1e..00000000000
--- a/app/models/analytics/cycle_analytics/project_stage.rb
+++ /dev/null
@@ -1,33 +0,0 @@
-# frozen_string_literal: true
-
-module Analytics
- module CycleAnalytics
- class ProjectStage < ApplicationRecord
- include Analytics::CycleAnalytics::Stageable
-
- belongs_to :project, optional: false
- belongs_to :value_stream, class_name: 'Analytics::CycleAnalytics::ProjectValueStream', foreign_key: :project_value_stream_id
-
- alias_attribute :value_stream_id, :project_value_stream_id
-
- delegate :group, to: :project
- alias_attribute :parent, :project
- alias_attribute :parent_id, :project_id
-
- validate :validate_project_group_for_label_events, if: -> { start_event_label_based? || end_event_label_based? }
-
- def self.distinct_stages_within_hierarchy(group)
- with_preloaded_labels
- .where(project_id: group.all_projects.select(:id))
- .select("DISTINCT ON(stage_event_hash_id) #{quoted_table_name}.*")
- end
-
- private
-
- # Project should belong to a group when the stage has Label based events since only GroupLabels are allowed.
- def validate_project_group_for_label_events
- errors.add(:project, s_('CycleAnalyticsStage|should be under a group')) unless project.group
- end
- end
- end
-end
diff --git a/app/models/analytics/cycle_analytics/project_value_stream.rb b/app/models/analytics/cycle_analytics/project_value_stream.rb
deleted file mode 100644
index 3eba7e87b17..00000000000
--- a/app/models/analytics/cycle_analytics/project_value_stream.rb
+++ /dev/null
@@ -1,22 +0,0 @@
-# frozen_string_literal: true
-
-class Analytics::CycleAnalytics::ProjectValueStream < ApplicationRecord
- belongs_to :project
-
- has_many :stages, class_name: 'Analytics::CycleAnalytics::ProjectStage'
-
- validates :project, :name, presence: true
- validates :name, length: { minimum: 3, maximum: 100, allow_nil: false }, uniqueness: { scope: :project_id }
-
- def custom?
- false
- end
-
- def stages
- []
- end
-
- def self.build_default_value_stream(project)
- new(name: Analytics::CycleAnalytics::Stages::BaseService::DEFAULT_VALUE_STREAM_NAME, project: project)
- end
-end
diff --git a/app/models/analytics/cycle_analytics/stage_event_hash.rb b/app/models/analytics/cycle_analytics/stage_event_hash.rb
index 043a5d45e3d..6443a970945 100644
--- a/app/models/analytics/cycle_analytics/stage_event_hash.rb
+++ b/app/models/analytics/cycle_analytics/stage_event_hash.rb
@@ -3,7 +3,6 @@
module Analytics
module CycleAnalytics
class StageEventHash < ApplicationRecord
- has_many :cycle_analytics_project_stages, class_name: 'Analytics::CycleAnalytics::ProjectStage', inverse_of: :stage_event_hash
has_many :cycle_analytics_stages, class_name: 'Analytics::CycleAnalytics::Stage', inverse_of: :stage_event_hash
validates :hash_sha256, presence: true
@@ -34,13 +33,9 @@ module Analytics
end
def self.unused_hashes_for(id)
- project_stage_exists_query = Analytics::CycleAnalytics::ProjectStage.where(stage_event_hash_id: id).select('1').limit(1)
stage_exists_query = ::Analytics::CycleAnalytics::Stage.where(stage_event_hash_id: id).select('1').limit(1)
- where
- .not('EXISTS (?)', project_stage_exists_query)
- .where
- .not('EXISTS (?)', stage_exists_query)
+ where.not('EXISTS (?)', stage_exists_query)
end
end
end
diff --git a/app/models/issue.rb b/app/models/issue.rb
index ff5fb61146e..8b4477d4fcb 100644
--- a/app/models/issue.rb
+++ b/app/models/issue.rb
@@ -329,13 +329,22 @@ class Issue < ApplicationRecord
'#'
end
+ # Alternative prefix for situations where the standard prefix would be
+ # interpreted as a comment, most notably to begin commit messages with
+ # (e.g. "GL-123: My commit")
+ def self.alternative_reference_prefix
+ 'GL-'
+ end
+
# Pattern used to extract `#123` issue references from text
#
# This pattern supports cross-project references.
def self.reference_pattern
@reference_pattern ||= %r{
- (#{Project.reference_pattern})?
- #{Regexp.escape(reference_prefix)}#{Gitlab::Regex.issue}
+ (?:
+ (#{Project.reference_pattern})?#{Regexp.escape(reference_prefix)} |
+ #{Regexp.escape(alternative_reference_prefix)}
+ )#{Gitlab::Regex.issue}
}x
end
diff --git a/app/models/project.rb b/app/models/project.rb
index 1941397b846..ef30a61229e 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -396,9 +396,6 @@ class Project < ApplicationRecord
has_one :ci_cd_settings, class_name: 'ProjectCiCdSetting', inverse_of: :project, autosave: true, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :remote_mirrors, inverse_of: :project
- has_many :cycle_analytics_stages, class_name: 'Analytics::CycleAnalytics::ProjectStage', inverse_of: :project
- has_many :value_streams, class_name: 'Analytics::CycleAnalytics::ProjectValueStream', inverse_of: :project
-
has_many :external_pull_requests, inverse_of: :project
has_many :sourced_pipelines, class_name: 'Ci::Sources::Pipeline', foreign_key: :source_project_id
diff --git a/app/workers/projects/refresh_build_artifacts_size_statistics_worker.rb b/app/workers/projects/refresh_build_artifacts_size_statistics_worker.rb
index ec23bde5898..065d103fe07 100644
--- a/app/workers/projects/refresh_build_artifacts_size_statistics_worker.rb
+++ b/app/workers/projects/refresh_build_artifacts_size_statistics_worker.rb
@@ -19,6 +19,7 @@ module Projects
refresh = Projects::RefreshBuildArtifactsSizeStatisticsService.new.execute
return unless refresh
+ log_extra_metadata_on_done(:refresh_id, refresh.id)
log_extra_metadata_on_done(:project_id, refresh.project_id)
log_extra_metadata_on_done(:last_job_artifact_id, refresh.last_job_artifact_id)
log_extra_metadata_on_done(:last_batch, refresh.destroyed?)
diff --git a/db/docs/analytics_cycle_analytics_project_stages.yml b/db/docs/analytics_cycle_analytics_project_stages.yml
index dc5b1db16cd..4d6baab5a00 100644
--- a/db/docs/analytics_cycle_analytics_project_stages.yml
+++ b/db/docs/analytics_cycle_analytics_project_stages.yml
@@ -1,10 +1,9 @@
---
table_name: analytics_cycle_analytics_project_stages
classes:
-- Analytics::CycleAnalytics::ProjectStage
feature_categories:
- value_stream_management
-description: Persists project level value stream analytics stages.
+description: Persists project level value stream analytics stages. Scheduled for removal in https://gitlab.com/gitlab-org/gitlab/-/issues/390194
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/15061
milestone: '12.2'
gitlab_schema: gitlab_main
diff --git a/db/docs/analytics_cycle_analytics_project_value_streams.yml b/db/docs/analytics_cycle_analytics_project_value_streams.yml
index 5881c048d3b..839b49f1bed 100644
--- a/db/docs/analytics_cycle_analytics_project_value_streams.yml
+++ b/db/docs/analytics_cycle_analytics_project_value_streams.yml
@@ -1,10 +1,9 @@
---
table_name: analytics_cycle_analytics_project_value_streams
classes:
-- Analytics::CycleAnalytics::ProjectValueStream
feature_categories:
- value_stream_management
-description: Used to store the value stream configurations for projects
+description: Used to store the value stream configurations for projects. Scheduled for removal in https://gitlab.com/gitlab-org/gitlab/-/issues/390194
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60925
milestone: '13.12'
gitlab_schema: gitlab_main
diff --git a/db/post_migrate/20230112141236_schedule_vulnerabilities_feedback_migration2.rb b/db/post_migrate/20230112141236_schedule_vulnerabilities_feedback_migration2.rb
index 08ceea1022c..7d8cba96a91 100644
--- a/db/post_migrate/20230112141236_schedule_vulnerabilities_feedback_migration2.rb
+++ b/db/post_migrate/20230112141236_schedule_vulnerabilities_feedback_migration2.rb
@@ -14,23 +14,10 @@ class ScheduleVulnerabilitiesFeedbackMigration2 < Gitlab::Database::Migration[2.
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
- queue_batched_background_migration(
- MIGRATION,
- TABLE_NAME,
- BATCH_COLUMN,
- job_interval: DELAY_INTERVAL,
- batch_size: BATCH_SIZE,
- max_batch_size: MAX_BATCH_SIZE,
- sub_batch_size: SUB_BATCH_SIZE
- )
+ # rescheduled by 20230203122602_schedule_vulnerabilities_feedback_migration3.rb
end
def down
- delete_batched_background_migration(
- MIGRATION,
- TABLE_NAME,
- BATCH_COLUMN,
- []
- )
+ # no-op
end
end
diff --git a/db/post_migrate/20230119123256_add_fk_index_to_ci_resources_on_partition_id_and_build_id.rb b/db/post_migrate/20230119123256_add_fk_index_to_ci_resources_on_partition_id_and_build_id.rb
new file mode 100644
index 00000000000..8c1b8c81235
--- /dev/null
+++ b/db/post_migrate/20230119123256_add_fk_index_to_ci_resources_on_partition_id_and_build_id.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class AddFkIndexToCiResourcesOnPartitionIdAndBuildId < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ INDEX_NAME = :index_ci_resources_on_partition_id_build_id
+ TABLE_NAME = :ci_resources
+ COLUMNS = [:partition_id, :build_id]
+
+ def up
+ add_concurrent_index(TABLE_NAME, COLUMNS, name: INDEX_NAME)
+ end
+
+ def down
+ remove_concurrent_index_by_name(TABLE_NAME, INDEX_NAME)
+ end
+end
diff --git a/db/post_migrate/20230119123257_add_fk_to_ci_resources_on_partition_id_and_build_id.rb b/db/post_migrate/20230119123257_add_fk_to_ci_resources_on_partition_id_and_build_id.rb
new file mode 100644
index 00000000000..8279def779e
--- /dev/null
+++ b/db/post_migrate/20230119123257_add_fk_to_ci_resources_on_partition_id_and_build_id.rb
@@ -0,0 +1,32 @@
+# frozen_string_literal: true
+
+class AddFkToCiResourcesOnPartitionIdAndBuildId < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ SOURCE_TABLE_NAME = :ci_resources
+ TARGET_TABLE_NAME = :ci_builds
+ COLUMN = :build_id
+ TARGET_COLUMN = :id
+ FK_NAME = :fk_e169a8e3d5_p
+ PARTITION_COLUMN = :partition_id
+
+ def up
+ add_concurrent_foreign_key(
+ SOURCE_TABLE_NAME,
+ TARGET_TABLE_NAME,
+ column: [PARTITION_COLUMN, COLUMN],
+ target_column: [PARTITION_COLUMN, TARGET_COLUMN],
+ validate: false,
+ reverse_lock_order: true,
+ on_update: :cascade,
+ on_delete: :nullify,
+ name: FK_NAME
+ )
+ end
+
+ def down
+ with_lock_retries do
+ remove_foreign_key_if_exists(SOURCE_TABLE_NAME, name: FK_NAME)
+ end
+ end
+end
diff --git a/db/post_migrate/20230119123258_validate_fk_on_ci_resources_partition_id_and_build_id.rb b/db/post_migrate/20230119123258_validate_fk_on_ci_resources_partition_id_and_build_id.rb
new file mode 100644
index 00000000000..3df7f27d921
--- /dev/null
+++ b/db/post_migrate/20230119123258_validate_fk_on_ci_resources_partition_id_and_build_id.rb
@@ -0,0 +1,15 @@
+# frozen_string_literal: true
+
+class ValidateFkOnCiResourcesPartitionIdAndBuildId < Gitlab::Database::Migration[2.1]
+ TABLE_NAME = :ci_resources
+ FK_NAME = :fk_e169a8e3d5_p
+ COLUMNS = [:partition_id, :build_id]
+
+ def up
+ validate_foreign_key(TABLE_NAME, COLUMNS, name: FK_NAME)
+ end
+
+ def down
+ # no-op
+ end
+end
diff --git a/db/post_migrate/20230119123259_remove_fk_to_ci_builds_ci_resources_on_build_id.rb b/db/post_migrate/20230119123259_remove_fk_to_ci_builds_ci_resources_on_build_id.rb
new file mode 100644
index 00000000000..fcf6989f30d
--- /dev/null
+++ b/db/post_migrate/20230119123259_remove_fk_to_ci_builds_ci_resources_on_build_id.rb
@@ -0,0 +1,30 @@
+# frozen_string_literal: true
+
+class RemoveFkToCiBuildsCiResourcesOnBuildId < Gitlab::Database::Migration[2.1]
+ disable_ddl_transaction!
+
+ SOURCE_TABLE_NAME = :ci_resources
+ TARGET_TABLE_NAME = :ci_builds
+ COLUMN = :build_id
+ TARGET_COLUMN = :id
+ FK_NAME = :fk_e169a8e3d5
+
+ def up
+ with_lock_retries do
+ remove_foreign_key_if_exists(SOURCE_TABLE_NAME, name: FK_NAME)
+ end
+ end
+
+ def down
+ add_concurrent_foreign_key(
+ SOURCE_TABLE_NAME,
+ TARGET_TABLE_NAME,
+ column: COLUMN,
+ target_column: TARGET_COLUMN,
+ validate: true,
+ reverse_lock_order: true,
+ on_delete: :nullify,
+ name: FK_NAME
+ )
+ end
+end
diff --git a/db/post_migrate/20230203122602_schedule_vulnerabilities_feedback_migration3.rb b/db/post_migrate/20230203122602_schedule_vulnerabilities_feedback_migration3.rb
new file mode 100644
index 00000000000..1d960c22b72
--- /dev/null
+++ b/db/post_migrate/20230203122602_schedule_vulnerabilities_feedback_migration3.rb
@@ -0,0 +1,45 @@
+# frozen_string_literal: true
+
+class ScheduleVulnerabilitiesFeedbackMigration3 < Gitlab::Database::Migration[2.1]
+ MIGRATION = 'MigrateVulnerabilitiesFeedbackToVulnerabilitiesStateTransition'
+ TABLE_NAME = :vulnerability_feedback
+ BATCH_COLUMN = :id
+ DELAY_INTERVAL = 5.minutes
+ BATCH_SIZE = 250
+ MAX_BATCH_SIZE = 250
+ SUB_BATCH_SIZE = 50
+
+ disable_ddl_transaction!
+
+ restrict_gitlab_migration gitlab_schema: :gitlab_main
+
+ def up
+ # Delete the previous jobs
+ delete_batched_background_migration(
+ MIGRATION,
+ TABLE_NAME,
+ BATCH_COLUMN,
+ []
+ )
+
+ # Reschedule the migration
+ queue_batched_background_migration(
+ MIGRATION,
+ TABLE_NAME,
+ BATCH_COLUMN,
+ job_interval: DELAY_INTERVAL,
+ batch_size: BATCH_SIZE,
+ max_batch_size: MAX_BATCH_SIZE,
+ sub_batch_size: SUB_BATCH_SIZE
+ )
+ end
+
+ def down
+ delete_batched_background_migration(
+ MIGRATION,
+ TABLE_NAME,
+ BATCH_COLUMN,
+ []
+ )
+ end
+end
diff --git a/db/schema_migrations/20230119123256 b/db/schema_migrations/20230119123256
new file mode 100644
index 00000000000..3a2db3c1d76
--- /dev/null
+++ b/db/schema_migrations/20230119123256
@@ -0,0 +1 @@
+bbf6542b726466ae98323f1e7dd636874e01228ec584166ab617a917822b3fa1 \ No newline at end of file
diff --git a/db/schema_migrations/20230119123257 b/db/schema_migrations/20230119123257
new file mode 100644
index 00000000000..78d75e164c0
--- /dev/null
+++ b/db/schema_migrations/20230119123257
@@ -0,0 +1 @@
+e69eabf71bfdfc9c5aa50829d08b3ef1473e5359d01e08e1bdc94fcbb7c58e6e \ No newline at end of file
diff --git a/db/schema_migrations/20230119123258 b/db/schema_migrations/20230119123258
new file mode 100644
index 00000000000..0bb155c2106
--- /dev/null
+++ b/db/schema_migrations/20230119123258
@@ -0,0 +1 @@
+6af88109e5186a6a2f18418f441e232757ee0b03cb8af62e72c86ca4d12075c9 \ No newline at end of file
diff --git a/db/schema_migrations/20230119123259 b/db/schema_migrations/20230119123259
new file mode 100644
index 00000000000..c4ffc37f790
--- /dev/null
+++ b/db/schema_migrations/20230119123259
@@ -0,0 +1 @@
+49e256cdd550386c989cb6edea22873547b96120cfd8b5652de532dbbe21928c \ No newline at end of file
diff --git a/db/schema_migrations/20230203122602 b/db/schema_migrations/20230203122602
new file mode 100644
index 00000000000..a03143094f5
--- /dev/null
+++ b/db/schema_migrations/20230203122602
@@ -0,0 +1 @@
+bb8b177385489eeefda9b8c1e9534398ec759d95fbf46ee3af02a3964a03e1ae \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 23f7d581dfc..2fd40d7e085 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -29246,6 +29246,8 @@ CREATE UNIQUE INDEX index_ci_resource_groups_on_project_id_and_key ON ci_resourc
CREATE INDEX index_ci_resources_on_build_id ON ci_resources USING btree (build_id);
+CREATE INDEX index_ci_resources_on_partition_id_build_id ON ci_resources USING btree (partition_id, build_id);
+
CREATE UNIQUE INDEX index_ci_resources_on_resource_group_id_and_build_id ON ci_resources USING btree (resource_group_id, build_id);
CREATE INDEX index_ci_runner_machines_on_contacted_at_desc_and_id_desc ON ci_runner_machines USING btree (contacted_at DESC, id DESC);
@@ -34347,7 +34349,7 @@ ALTER TABLE ONLY issues
ADD CONSTRAINT fk_df75a7c8b8 FOREIGN KEY (promoted_to_epic_id) REFERENCES epics(id) ON DELETE SET NULL;
ALTER TABLE ONLY ci_resources
- ADD CONSTRAINT fk_e169a8e3d5 FOREIGN KEY (build_id) REFERENCES ci_builds(id) ON DELETE SET NULL;
+ ADD CONSTRAINT fk_e169a8e3d5_p FOREIGN KEY (partition_id, build_id) REFERENCES ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE SET NULL;
ALTER TABLE ONLY ci_sources_pipelines
ADD CONSTRAINT fk_e1bad85861 FOREIGN KEY (pipeline_id) REFERENCES ci_pipelines(id) ON DELETE CASCADE;
diff --git a/doc/administration/logs/index.md b/doc/administration/logs/index.md
index 9893c6935a3..eab4c9b7d83 100644
--- a/doc/administration/logs/index.md
+++ b/doc/administration/logs/index.md
@@ -866,6 +866,19 @@ Depending on your installation method, this file is located at:
- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/database_load_balancing.log`
- Installations from source: `/home/git/gitlab/log/database_load_balancing.log`
+## `zoekt.log` **(PREMIUM SELF)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/110980) in GitLab 15.9.
+
+This file logs information related to the
+[Exact code search](../../user/search/exact_code_search.md) feature which is
+powered by Zoekt.
+
+Depending on your installation method, this file is located at:
+
+- Omnibus GitLab: `/var/log/gitlab/gitlab-rails/zoekt.log`
+- Installations from source: `/home/git/gitlab/log/zoekt.log`
+
## `elasticsearch.log` **(PREMIUM SELF)**
> Introduced in GitLab 12.6.
diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md
index 0b39e30885e..b7c1def0ba4 100644
--- a/doc/api/api_resources.md
+++ b/doc/api/api_resources.md
@@ -135,6 +135,7 @@ The following API resources are available in the group context:
| [Issues](issues.md) | `/groups/:id/issues` (also available for projects and standalone) |
| [Issues Statistics](issues_statistics.md) | `/groups/:id/issues_statistics` (also available for projects and standalone) |
| [Linked epics](linked_epics.md) | `/groups/:id/epics/.../related_epics` |
+| [Member Roles](member_roles.md) | `/groups/:id/member_roles` |
| [Members](members.md) | `/groups/:id/members` (also available for projects) |
| [Merge requests](merge_requests.md) | `/groups/:id/merge_requests` (also available for projects and standalone) |
| [Notes](notes.md) (comments) | `/groups/:id/epics/.../notes` (also available for projects) |
diff --git a/doc/api/draft_notes.md b/doc/api/draft_notes.md
index f1749346dc2..e8047d737dd 100644
--- a/doc/api/draft_notes.md
+++ b/doc/api/draft_notes.md
@@ -50,3 +50,46 @@ GET /projects/:id/merge_requests/:merge_request_iid/draft_notes
curl --header "PRIVATE-TOKEN: <your_access_token>" \
"https://gitlab.example.com/api/v4/projects/14/merge_requests/11/draft_notes"
```
+
+## Get a single draft note
+
+Returns a single draft note for a given merge request.
+
+```plaintext
+GET /projects/:id/merge_requests/:merge_request_iid/draft_notes/:draft_note_id
+```
+
+| Attribute | Type | Required | Description |
+| ------------------- | ---------------- | ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------- |
+| `id` | integer or string | yes | The ID or [URL-encoded path of the project](rest/index.md#namespaced-path-encoding).
+| `draft_note_id` | integer | yes | The ID of a draft note.
+| `merge_request_iid` | integer | yes | The IID of a project merge request.
+
+```json
+{
+ id: 5,
+ author_id: 23,
+ merge_request_id: 11,
+ resolve_discussion: false,
+ discussion_id: nil,
+ note: "Example title",
+ commit_id: nil,
+ line_code: nil,
+ position:
+ {
+ base_sha: nil,
+ start_sha: nil,
+ head_sha: nil,
+ old_path: nil,
+ new_path: nil,
+ position_type: "text",
+ old_line: nil,
+ new_line: nil,
+ line_range: nil
+ }
+}
+```
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/14/merge_requests/11/draft_notes/5"
+```
diff --git a/doc/api/member_roles.md b/doc/api/member_roles.md
new file mode 100644
index 00000000000..693dfb49c82
--- /dev/null
+++ b/doc/api/member_roles.md
@@ -0,0 +1,116 @@
+---
+stage: Manage
+group: Authentication and Authorization
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Member roles API **(ULTIMATE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96996) in GitLab 15.4. [Deployed behind the `customizable_roles` flag](../administration/feature_flags.md), disabled by default.
+
+## List all member roles of a group
+
+Gets a list of group member roles viewable by the authenticated user.
+
+```plaintext
+GET /groups/:id/member_roles
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](rest/index.md#namespaced-path-encoding) owned by the authenticated user |
+
+If successful, returns [`200`](rest/index.md#status-codes) and the following response attributes:
+
+| Attribute | Type | Description |
+|:-------------------------|:---------|:----------------------|
+| `[].id` | integer | The ID of the member role. |
+| `[].group_id` | integer | The ID of the group that the member role belongs to. |
+| `[].base_access_level` | integer | Base access level for member role. |
+| `[].read_code` | boolean | Permission to read code. |
+
+Example request:
+
+```shell
+curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/member_roles"
+```
+
+Example response:
+
+```json
+[
+ {
+ "id": 2,
+ "group_id": 84,
+ "base_access_level": 10,
+ "read_code": true
+ },
+ {
+ "id": 3,
+ "group_id": 84,
+ "base_access_level": 10,
+ "read_code": false
+ }
+]
+```
+
+## Add a member role to a group
+
+Adds a member role to a group.
+
+```plaintext
+POST /groups/:id/member_roles
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](rest/index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `base_access-level` | integer | yes | Base access level for configured role. |
+| `read_code` | boolean | no | Permission to read code. |
+
+If successful, returns [`201`](rest/index.md#status-codes) and the following attributes:
+
+| Attribute | Type | Description |
+|:-------------------------|:---------|:----------------------|
+| `id` | integer | The ID of the member role. |
+| `group_id` | integer | The ID of the group that the member role belongs to. |
+| `base_access_level` | integer | Base access level for member role. |
+| `read_code` | boolean | Permission to read code. |
+
+Example request:
+
+```shell
+ curl --request POST --header "Content-Type: application/json" --header "Authorization: Bearer $YOUR_ACCESS_TOKEN" --data '{"base_access_level" : 10, "read_code" : true}' "https://example.gitlab.com/api/v4/groups/:id/member_roles"
+```
+
+Example response:
+
+```json
+{
+ "id": 3,
+ "group_id": 84,
+ "base_access_level": 10,
+ "read_code": true
+}
+```
+
+### Remove member role of a group
+
+Deletes a member role of a group.
+
+```plaintext
+DELETE /groups/:id/member_roles/:member_role_id
+```
+
+| Attribute | Type | Required | Description |
+| --------- | ---- | -------- | ----------- |
+| `id` | integer/string | yes | The ID or [URL-encoded path of the group](rest/index.md#namespaced-path-encoding) owned by the authenticated user. |
+| `member_role_id` | integer | yes | The ID of the member role. |
+
+If successful, returns [`204`](rest/index.md#status-codes) and an empty response.
+
+Example request:
+
+```shell
+curl --request DELETE --header "Content-Type: application/json" --header "Authorization: Bearer $YOUR_ACCESS_TOKEN" "https://example.gitlab.com/api/v4/groups/:group_id/member_roles/:member_role_id"
+```
diff --git a/doc/architecture/blueprints/_template.md b/doc/architecture/blueprints/_template.md
index 11a312b3334..f7dea60e9b7 100644
--- a/doc/architecture/blueprints/_template.md
+++ b/doc/architecture/blueprints/_template.md
@@ -47,13 +47,11 @@ of this file) is [here](/doc/architecture/blueprints/_template.md).
Blueprint statuses you can use:
- "proposed"
-- "ongoing"
- "accepted"
+- "ongoing"
- "implemented"
- "rejected"
-Any other one-word status should be fine, see which ones have colors defined:
-https://gitlab.com/gitlab-org/gitlab-docs/-/blob/main/content/assets/stylesheets/labels.scss#L22
-->
# {+ Title of Blueprint +}
diff --git a/doc/architecture/blueprints/object_storage/index.md b/doc/architecture/blueprints/object_storage/index.md
index 950a5f13c38..4a8eeaf86a9 100644
--- a/doc/architecture/blueprints/object_storage/index.md
+++ b/doc/architecture/blueprints/object_storage/index.md
@@ -1,5 +1,5 @@
---
-status: ready
+status: accepted
creation-date: "2021-11-18"
authors: [ "@nolith" ]
coach: "@glopezfernandez"
diff --git a/doc/architecture/blueprints/rate_limiting/index.md b/doc/architecture/blueprints/rate_limiting/index.md
index 26114fce7f2..b466a54e922 100644
--- a/doc/architecture/blueprints/rate_limiting/index.md
+++ b/doc/architecture/blueprints/rate_limiting/index.md
@@ -1,5 +1,5 @@
---
-status: ready
+status: accepted
creation-date: "2022-09-08"
authors: [ "@grzesiek", "@marshall007", "@fabiopitino", "@hswimelar" ]
coach: "@andrewn"
diff --git a/doc/architecture/blueprints/runner_tokens/index.md b/doc/architecture/blueprints/runner_tokens/index.md
index f63e453bfae..f676ac5dc81 100644
--- a/doc/architecture/blueprints/runner_tokens/index.md
+++ b/doc/architecture/blueprints/runner_tokens/index.md
@@ -1,5 +1,5 @@
---
-status: ready
+status: ongoing
creation-date: "2022-10-27"
authors: [ "@pedropombeiro", "@tmaczukin" ]
coach: "@ayufan"
diff --git a/doc/development/gitlab_shell/index.md b/doc/development/gitlab_shell/index.md
index 7f2c113fa0c..7097fd48cea 100644
--- a/doc/development/gitlab_shell/index.md
+++ b/doc/development/gitlab_shell/index.md
@@ -21,7 +21,7 @@ Ruby to build and test, but not to run.
GitLab Shell runs on `port 22` on an Omnibus installation. To use a regular SSH
service, configure it on an alternative port.
-Download and install the current version of Go from [golang.org](https://golang.org/dl/).
+Download and install the current version of Go from [golang.org](https://go.dev/dl/).
We follow the [Golang Release Policy](https://golang.org/doc/devel/release.html#policy)
and support:
diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md
index 3791cd4861e..876def53b2d 100644
--- a/doc/development/secure_coding_guidelines.md
+++ b/doc/development/secure_coding_guidelines.md
@@ -1270,7 +1270,7 @@ This sensitive data must be handled carefully to avoid leaks which could lead to
- The [Gitleaks Git hook](https://gitlab.com/gitlab-com/gl-security/security-research/gitleaks-endpoint-installer) is recommended for preventing credentials from being committed.
- Never log credentials under any circumstance. Issue [#353857](https://gitlab.com/gitlab-org/gitlab/-/issues/353857) is an example of credential leaks through log file.
- When credentials are required in a CI/CD job, use [masked variables](../ci/variables/index.md#mask-a-cicd-variable) to help prevent accidental exposure in the job logs. Be aware that when [debug logging](../ci/variables/index.md#enable-debug-logging) is enabled, all masked CI/CD variables are visible in job logs. Also consider using [protected variables](../ci/variables/index.md#protect-a-cicd-variable) when possible so that sensitive CI/CD variables are only available to pipelines running on protected branches or protected tags.
-- Proper scanners must be enabled depending on what data those credentials are protecting. See the [Application Security Inventory Policy](https://about.gitlab.com/handbook/security/security-engineering-and-research/application-security/inventory.html#policies) and our [Data Classification Standards](https://about.gitlab.com/handbook/security/data-classification-standard.html#data-classification-standards).
+- Proper scanners must be enabled depending on what data those credentials are protecting. See the [Application Security Inventory Policy](https://about.gitlab.com/handbook/security/security-engineering/application-security/inventory.html#policies) and our [Data Classification Standards](https://about.gitlab.com/handbook/security/data-classification-standard.html#data-classification-standards).
- To store and/or share credentials between teams, refer to [1Password for Teams](https://about.gitlab.com/handbook/security/#1password-for-teams) and follow [the 1Password Guidelines](https://about.gitlab.com/handbook/security/#1password-guidelines).
- If you need to share a secret with a team member, use 1Password. Do not share a secret over email, Slack, or other service on the Internet.
diff --git a/doc/development/value_stream_analytics.md b/doc/development/value_stream_analytics.md
index 33a6744d5cd..77a32b62e32 100644
--- a/doc/development/value_stream_analytics.md
+++ b/doc/development/value_stream_analytics.md
@@ -261,7 +261,7 @@ considered legacy, which will be phased out at some point.
- Rails Controller (`Analytics::CycleAnalytics` module): Value stream analytics exposes its data via JSON endpoints, implemented within the `analytics` workspace. Configuring the stages are also implements JSON endpoints (CRUD).
- Services (`Analytics::CycleAnalytics` module): All `Stage` related actions are delegated to respective service objects.
-- Models (`Analytics::CycleAnalytics` module): Models are used to persist the `Stage` objects `ProjectStage` and `Stage`.
+- Models (`Analytics::CycleAnalytics` module): Models are used to persist the `Stage` objects.
- Feature classes (`Gitlab::Analytics::CycleAnalytics` module):
- Responsible for composing queries and define feature specific business logic.
- `DataCollector`, `Event`, `StageEvents`, etc.
diff --git a/doc/operations/metrics/embed_grafana.md b/doc/operations/metrics/embed_grafana.md
index 9b2a381fcf6..7bc88165b95 100644
--- a/doc/operations/metrics/embed_grafana.md
+++ b/doc/operations/metrics/embed_grafana.md
@@ -3,8 +3,13 @@ stage: Monitor
group: Respond
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
+<!--- start_remove The following content will be removed on remove_date: '2023-08-22' -->
+# Embed Grafana panels in Markdown (deprecated) **(FREE)**
-# Embed Grafana panels in Markdown **(FREE)**
+WARNING:
+This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/110290) in GitLab 15.9
+and is planned for removal in 16.0. We intend to replace this feature with the ability to [embed charts](https://gitlab.com/groups/gitlab-org/opstrace/-/epics/33) with the [GitLab Observability UI](https://gitlab.com/gitlab-org/opstrace/opstrace-ui).
+This change is a breaking change.
Grafana panels can be embedded in [GitLab Flavored Markdown](../../user/markdown.md). You can
embed Grafana panels using either:
@@ -83,3 +88,4 @@ To generate a link to a panel:
See the following example of a rendered panel.
![GitLab Rendered Grafana Panel](img/rendered_grafana_embed_v12_5.png)
+<!--- end_remove -->
diff --git a/doc/topics/plan_and_track.md b/doc/topics/plan_and_track.md
index d79a8ad066b..67d5e996837 100644
--- a/doc/topics/plan_and_track.md
+++ b/doc/topics/plan_and_track.md
@@ -54,6 +54,7 @@ Align your work across teams.
Use these day-to-day planning features.
+- [Your work sidebar](../topics/your_work.md)
- [Keyboard shortcuts](../user/shortcuts.md)
- [Quick actions](../user/project/quick_actions.md)
- [Markdown](../user/markdown.md)
diff --git a/doc/topics/your_work.md b/doc/topics/your_work.md
new file mode 100644
index 00000000000..862f9ae8430
--- /dev/null
+++ b/doc/topics/your_work.md
@@ -0,0 +1,18 @@
+---
+stage: Manage
+group: Foundations
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
+---
+
+# Your work sidebar
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/384342) in GitLab 15.9.
+
+The **Your work** left sidebar provides access to your:
+
+- [Projects](../user/project/working_with_projects.md#view-projects)
+- [Groups](../user/group/index.md)
+- [Issues](../user/project/issues/index.md)
+- [Merge requests](../user/project/merge_requests/index.md)
+- [To-do List](../user/todos.md)
+- [Milestones](../user/project/milestones/index.md)
diff --git a/doc/user/project/issues/crosslinking_issues.md b/doc/user/project/issues/crosslinking_issues.md
index 0b5605bb767..52da1acd32a 100644
--- a/doc/user/project/issues/crosslinking_issues.md
+++ b/doc/user/project/issues/crosslinking_issues.md
@@ -24,6 +24,13 @@ add `#xxx` to the commit message, where `xxx` is the issue number.
git commit -m "this is my commit message. Ref #xxx"
```
+Since commit messages cannot usually begin with a `#` character, you may use
+the alternative `GL-xxx` notation as well:
+
+```shell
+git commit -m "GL-xxx: this is my commit message"
+```
+
If they are in different projects, but in the same group,
add `projectname#xxx` to the commit message.
diff --git a/doc/user/project/repository/vscode.md b/doc/user/project/repository/vscode.md
index 257f98155d8..9260d59bc3a 100644
--- a/doc/user/project/repository/vscode.md
+++ b/doc/user/project/repository/vscode.md
@@ -15,8 +15,9 @@ do more day-to-day tasks in Visual Studio Code, such as:
from the Visual Studio Code [command palette](https://code.visualstudio.com/docs/getstarted/userinterface#_command-palette).
- Create and [review](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#merge-request-reviews)
merge requests directly from Visual Studio Code.
-- [Validate your GitLab CI configuration](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#validate-gitlab-ci-configuration).
+- [Validate your GitLab CI/CD configuration](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#validate-gitlab-cicd-configuration).
- [View the status of your pipeline](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#information-about-your-branch-pipelines-mr-closing-issue).
+- [View the output of CI/CD jobs](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#view-the-job-output).
- [Create](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#create-snippet)
and paste snippets to, and from, your editor.
- [Browse repositories](https://marketplace.visualstudio.com/items?itemName=GitLab.gitlab-workflow#browse-a-repository-without-cloning)
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb
index dd8149aba94..41f94e79f91 100644
--- a/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder.rb
@@ -24,7 +24,7 @@ module Gitlab
def initialize(stage:, params: {})
@stage = stage
@params = params
- @root_ancestor = stage.parent.root_ancestor
+ @root_ancestor = stage.namespace.root_ancestor
@stage_event_model = MODEL_CLASSES.fetch(stage.subject_class.to_s)
end
@@ -90,7 +90,7 @@ module Gitlab
end
def filter_by_stage_parent(query)
- query.by_project_id(stage.parent_id)
+ query.by_project_id(stage.namespace.project.id)
end
def base_query
diff --git a/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb b/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb
index 3abf380d461..8b40a8c2b26 100644
--- a/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb
+++ b/lib/gitlab/analytics/cycle_analytics/aggregated/data_collector.rb
@@ -5,7 +5,7 @@ module Gitlab
module CycleAnalytics
module Aggregated
# Arguments:
- # stage - an instance of CycleAnalytics::ProjectStage or CycleAnalytics::Stage
+ # stage - an instance of CycleAnalytics::Stage
# params:
# current_user: an instance of User
# from: DateTime
diff --git a/lib/gitlab/analytics/cycle_analytics/data_collector.rb b/lib/gitlab/analytics/cycle_analytics/data_collector.rb
index 0db027b9861..ffafafda4ac 100644
--- a/lib/gitlab/analytics/cycle_analytics/data_collector.rb
+++ b/lib/gitlab/analytics/cycle_analytics/data_collector.rb
@@ -4,7 +4,7 @@ module Gitlab
module Analytics
module CycleAnalytics
# Arguments:
- # stage - an instance of CycleAnalytics::ProjectStage or CycleAnalytics::Stage
+ # stage - an instance of CycleAnalytics::Stage
# params:
# current_user: an instance of User
# from: DateTime
diff --git a/lib/gitlab/analytics/cycle_analytics/default_stages.rb b/lib/gitlab/analytics/cycle_analytics/default_stages.rb
index 43683ae174e..0f1380125fa 100644
--- a/lib/gitlab/analytics/cycle_analytics/default_stages.rb
+++ b/lib/gitlab/analytics/cycle_analytics/default_stages.rb
@@ -6,7 +6,7 @@
# Example:
#
# params = Gitlab::Analytics::CycleAnalytics::DefaultStages.params_for_issue_stage
-# Analytics::CycleAnalytics::ProjectStage.new(params)
+# Analytics::CycleAnalytics::Stage.new(params)
module Gitlab
module Analytics
module CycleAnalytics
diff --git a/lib/gitlab/analytics/cycle_analytics/request_params.rb b/lib/gitlab/analytics/cycle_analytics/request_params.rb
index d058782ae87..2df3680db5f 100644
--- a/lib/gitlab/analytics/cycle_analytics/request_params.rb
+++ b/lib/gitlab/analytics/cycle_analytics/request_params.rb
@@ -196,7 +196,7 @@ module Gitlab
return unless value_stream
strong_memoize(:stage) do
- ::Analytics::CycleAnalytics::StageFinder.new(parent: project || group, stage_id: stage_id).execute if stage_id
+ ::Analytics::CycleAnalytics::StageFinder.new(parent: project&.project_namespace || group, stage_id: stage_id).execute if stage_id
end
end
end
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index e98cb7bdf17..68cbb209d5a 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -12276,9 +12276,6 @@ msgstr ""
msgid "CycleAnalyticsStage|is not available for the selected group"
msgstr ""
-msgid "CycleAnalyticsStage|should be under a group"
-msgstr ""
-
msgid "CycleAnalytics|%{selectedLabelsCount} selected (%{maxLabels} max)"
msgstr ""
diff --git a/scripts/lint-docs-blueprints.rb b/scripts/lint-docs-blueprints.rb
new file mode 100755
index 00000000000..35e0013cb34
--- /dev/null
+++ b/scripts/lint-docs-blueprints.rb
@@ -0,0 +1,86 @@
+#!/usr/bin/env ruby
+
+# frozen_string_literal: true
+
+# Taken from Jekyll
+# https://github.com/jekyll/jekyll/blob/3.5-stable/lib/jekyll/document.rb#L13
+YAML_FRONT_MATTER_REGEXP = /\A(---\s*\n.*?\n?)^((---|\.\.\.)\s*$\n?)/m.freeze
+READ_LIMIT_BYTES = 1024
+
+require 'yaml'
+
+def extract_front_matter(path)
+ File.open(path, 'r') do |f|
+ data = if match = YAML_FRONT_MATTER_REGEXP.match(f.read(READ_LIMIT_BYTES))
+ YAML.safe_load(match[1])
+ else
+ {}
+ end
+
+ BlueprintFrontMatter.new(data)
+ end
+end
+
+class BlueprintFrontMatter
+ STATUSES = %w[proposed accepted ongoing implemented rejected]
+
+ attr_reader :errors
+
+ def initialize(metadata)
+ @metadata = metadata
+ @errors = []
+ end
+
+ def validate
+ validate_status
+ validate_authors
+ validate_creation_date
+ end
+
+ private
+
+ def validate_status
+ status = @metadata['status']
+
+ add_error('Missing status') unless status
+
+ return if STATUSES.include?(status)
+
+ add_error("Unsupported status '#{status}': expected one of '#{STATUSES.join(', ')}'")
+ end
+
+ def validate_authors
+ authors = @metadata['authors']
+
+ add_error('Missing authors') unless authors
+ add_error('Authors must be an array') unless authors.is_a?(Array)
+ end
+
+ def validate_creation_date
+ return if @metadata['creation-date'] =~ /\d{4}-[01]\d-[0123]\d/
+
+ add_error("Invalid creation-date: the date format must be 'yyyy-mm-dd'")
+ end
+
+ def add_error(msg)
+ @errors << msg
+ end
+end
+
+if $PROGRAM_NAME == __FILE__
+ exit_code = 0
+
+ Dir['doc/architecture/blueprints/*/index.md'].each do |blueprint|
+ meta = extract_front_matter(blueprint)
+ meta.validate
+
+ next if meta.errors.empty?
+
+ exit_code = 1
+
+ puts("✖ ERROR: Invalid #{blueprint}:")
+ meta.errors.each { |e| puts(" - #{e}") }
+ end
+
+ exit(exit_code)
+end
diff --git a/spec/db/schema_spec.rb b/spec/db/schema_spec.rb
index 0875bb4e92a..5a02d712117 100644
--- a/spec/db/schema_spec.rb
+++ b/spec/db/schema_spec.rb
@@ -46,7 +46,7 @@ RSpec.describe 'Database schema', feature_category: :database do
ci_pending_builds: %w[partition_id],
ci_pipeline_variables: %w[partition_id],
ci_pipelines: %w[partition_id],
- ci_resources: %w[partition_id],
+ ci_resources: %w[partition_id build_id],
ci_runner_projects: %w[runner_id],
ci_running_builds: %w[partition_id],
ci_sources_pipelines: %w[partition_id source_partition_id],
@@ -187,7 +187,6 @@ RSpec.describe 'Database schema', feature_category: :database do
# These pre-existing enums have limits > 2 bytes
IGNORED_LIMIT_ENUMS = {
'Analytics::CycleAnalytics::Stage' => %w[start_event_identifier end_event_identifier],
- 'Analytics::CycleAnalytics::ProjectStage' => %w[start_event_identifier end_event_identifier],
'Ci::Bridge' => %w[failure_reason],
'Ci::Build' => %w[failure_reason],
'Ci::BuildMetadata' => %w[timeout_source],
diff --git a/spec/factories/analytics/cycle_analytics/project_stages.rb b/spec/factories/analytics/cycle_analytics/project_stages.rb
deleted file mode 100644
index e673c4957b0..00000000000
--- a/spec/factories/analytics/cycle_analytics/project_stages.rb
+++ /dev/null
@@ -1,16 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :cycle_analytics_project_stage, class: 'Analytics::CycleAnalytics::ProjectStage' do
- project
- sequence(:name) { |n| "Stage ##{n}" }
- hidden { false }
- issue_stage
- value_stream { association(:cycle_analytics_project_value_stream, project: project) }
-
- trait :issue_stage do
- start_event_identifier { Gitlab::Analytics::CycleAnalytics::StageEvents::IssueCreated.identifier }
- end_event_identifier { Gitlab::Analytics::CycleAnalytics::StageEvents::IssueStageEnd.identifier }
- end
- end
-end
diff --git a/spec/factories/analytics/cycle_analytics/project_value_streams.rb b/spec/factories/analytics/cycle_analytics/project_value_streams.rb
deleted file mode 100644
index 45a6470b0aa..00000000000
--- a/spec/factories/analytics/cycle_analytics/project_value_streams.rb
+++ /dev/null
@@ -1,9 +0,0 @@
-# frozen_string_literal: true
-
-FactoryBot.define do
- factory :cycle_analytics_project_value_stream, class: 'Analytics::CycleAnalytics::ProjectValueStream' do
- sequence(:name) { |n| "Value Stream ##{n}" }
-
- project
- end
-end
diff --git a/spec/factories/analytics/cycle_analytics/stages.rb b/spec/factories/analytics/cycle_analytics/stages.rb
index abf051f9a69..4f6f38f6f33 100644
--- a/spec/factories/analytics/cycle_analytics/stages.rb
+++ b/spec/factories/analytics/cycle_analytics/stages.rb
@@ -2,11 +2,19 @@
FactoryBot.define do
factory :cycle_analytics_stage, class: 'Analytics::CycleAnalytics::Stage' do
+ transient do
+ project { nil }
+ end
+
sequence(:name) { |n| "Stage ##{n}" }
start_event_identifier { Gitlab::Analytics::CycleAnalytics::StageEvents::MergeRequestCreated.identifier }
end_event_identifier { Gitlab::Analytics::CycleAnalytics::StageEvents::MergeRequestMerged.identifier }
namespace { association(:group) }
value_stream { association(:cycle_analytics_value_stream, namespace: namespace) }
+
+ after(:build) do |stage, evaluator|
+ stage.namespace = evaluator.project.reload.project_namespace if evaluator.project
+ end
end
end
diff --git a/spec/finders/analytics/cycle_analytics/stage_finder_spec.rb b/spec/finders/analytics/cycle_analytics/stage_finder_spec.rb
index 0275205028a..3e10ed78ab9 100644
--- a/spec/finders/analytics/cycle_analytics/stage_finder_spec.rb
+++ b/spec/finders/analytics/cycle_analytics/stage_finder_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Analytics::CycleAnalytics::StageFinder do
let(:stage_id) { { id: Gitlab::Analytics::CycleAnalytics::DefaultStages.names.first } }
- subject { described_class.new(parent: project, stage_id: stage_id[:id]).execute }
+ subject { described_class.new(parent: project.project_namespace, stage_id: stage_id[:id]).execute }
context 'when looking up in-memory default stage by name exists' do
it { expect(subject).not_to be_persisted }
diff --git a/spec/finders/protected_branches_finder_spec.rb b/spec/finders/protected_branches_finder_spec.rb
index 487d1be697a..5926891ac9d 100644
--- a/spec/finders/protected_branches_finder_spec.rb
+++ b/spec/finders/protected_branches_finder_spec.rb
@@ -3,35 +3,57 @@
require 'spec_helper'
RSpec.describe ProtectedBranchesFinder do
- let(:project) { create(:project) }
- let!(:protected_branch) { create(:protected_branch, project: project) }
- let!(:another_protected_branch) { create(:protected_branch, project: project) }
+ let_it_be(:group) { create(:group) }
+ let_it_be(:project) { create(:project, namespace: group) }
+
+ let!(:project_protected_branch) { create(:protected_branch, project: project) }
+ let!(:another_project_protected_branch) { create(:protected_branch, project: project) }
+ let!(:group_protected_branch) { create(:protected_branch, project: nil, group: group) }
+ let!(:another_group_protected_branch) { create(:protected_branch, project: nil, group: group) }
let!(:other_protected_branch) { create(:protected_branch) }
+
let(:params) { {} }
+ subject { described_class.new(entity, params).execute }
+
describe '#execute' do
- subject { described_class.new(project, params).execute }
+ shared_examples 'execute by entity' do
+ it 'returns all protected branches of project by default' do
+ expect(subject).to match_array(expected_branches)
+ end
- it 'returns all protected branches of project by default' do
- expect(subject).to match_array([protected_branch, another_protected_branch])
- end
+ context 'when search param is present' do
+ let(:params) { { search: group_protected_branch.name } }
- context 'when search param is present' do
- let(:params) { { search: protected_branch.name } }
+ it 'filters by search param' do
+ expect(subject).to eq([group_protected_branch])
+ end
+ end
+
+ context 'when there are more protected branches than the limit' do
+ before do
+ stub_const("#{described_class}::LIMIT", 1)
+ end
- it 'filters by search param' do
- expect(subject).to eq([protected_branch])
+ it 'returns limited protected branches of project' do
+ expect(subject.count).to eq(1)
+ end
end
end
- context 'when there are more protected branches than the limit' do
- before do
- stub_const("#{described_class}::LIMIT", 1)
+ it_behaves_like 'execute by entity' do
+ let(:entity) { project }
+ let(:expected_branches) do
+ [
+ project_protected_branch, another_project_protected_branch,
+ group_protected_branch, another_group_protected_branch
+ ]
end
+ end
- it 'returns limited protected branches of project' do
- expect(subject.count).to eq(1)
- end
+ it_behaves_like 'execute by entity' do
+ let(:entity) { group }
+ let(:expected_branches) { [group_protected_branch, another_group_protected_branch] }
end
end
end
diff --git a/spec/frontend/notes/deprecated_notes_spec.js b/spec/frontend/notes/deprecated_notes_spec.js
index 4756a107a15..6d3bc19bd45 100644
--- a/spec/frontend/notes/deprecated_notes_spec.js
+++ b/spec/frontend/notes/deprecated_notes_spec.js
@@ -28,6 +28,10 @@ window.gl = window.gl || {};
gl.utils = gl.utils || {};
gl.utils.disableButtonIfEmptyField = () => {};
+function wrappedDiscussionNote(note) {
+ return `<table><tbody>${note}</tbody></table>`;
+}
+
// the following test is unreliable and failing in main 2-3 times a day
// see https://gitlab.com/gitlab-org/gitlab/issues/206906#note_290602581
// eslint-disable-next-line jest/no-disabled-tests
@@ -436,22 +440,40 @@ describe.skip('Old Notes (~/deprecated_notes.js)', () => {
);
});
- it('should append to row selected with line_code', () => {
- $form.length = 0;
- note.discussion_line_code = 'line_code';
- note.diff_discussion_html = '<tr></tr>';
+ describe('HTML output', () => {
+ let line;
- const line = document.createElement('div');
- line.id = note.discussion_line_code;
- document.body.appendChild(line);
+ beforeEach(() => {
+ $form.length = 0;
+ note.discussion_line_code = 'line_code';
+ note.diff_discussion_html = '<tr></tr>';
- // Override mocks for this single test
- $form.closest.mockReset();
- $form.closest.mockReturnValue($form);
+ line = document.createElement('div');
+ line.id = note.discussion_line_code;
+ document.body.appendChild(line);
- Notes.prototype.renderDiscussionNote.call(notes, note, $form);
+ // Override mocks for these tests
+ $form.closest.mockReset();
+ $form.closest.mockReturnValue($form);
+ });
- expect(line.nextSibling.outerHTML).toEqual(note.diff_discussion_html);
+ it('should append to row selected with line_code', () => {
+ Notes.prototype.renderDiscussionNote.call(notes, note, $form);
+
+ expect(line.nextSibling.outerHTML).toEqual(
+ wrappedDiscussionNote(note.diff_discussion_html),
+ );
+ });
+
+ it('sanitizes the output html without stripping leading <tr> or <td> elements', () => {
+ const sanitizedDiscussion = '<tr><td><a>I am a dolphin!</a></td></tr>';
+ note.diff_discussion_html =
+ '<tr><td><a href="javascript:alert(1)">I am a dolphin!</a></td></tr>';
+
+ Notes.prototype.renderDiscussionNote.call(notes, note, $form);
+
+ expect(line.nextSibling.outerHTML).toEqual(wrappedDiscussionNote(sanitizedDiscussion));
+ });
});
});
diff --git a/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb b/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
index 37fdd3ec806..d8a97c6c3dc 100644
--- a/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
+++ b/spec/lib/banzai/filter/references/issue_reference_filter_spec.rb
@@ -47,57 +47,55 @@ RSpec.describe Banzai::Filter::References::IssueReferenceFilter, feature_categor
end
end
- context 'internal reference' do
- let(:reference) { "##{issue.iid}" }
-
+ shared_examples 'an internal reference' do
it_behaves_like 'a reference containing an element node'
it_behaves_like 'a reference with issue type information'
it 'links to a valid reference' do
- doc = reference_filter("Fixed #{reference}")
+ doc = reference_filter("Fixed #{written_reference}")
expect(doc.css('a').first.attr('href'))
.to eq issue_url
end
it 'links with adjacent text' do
- doc = reference_filter("Fixed (#{reference}.)")
+ doc = reference_filter("Fixed (#{written_reference}.)")
expect(doc.text).to eql("Fixed (#{reference}.)")
end
it 'ignores invalid issue IDs' do
- invalid = invalidate_reference(reference)
+ invalid = invalidate_reference(written_reference)
exp = act = "Fixed #{invalid}"
expect(reference_filter(act).to_html).to eq exp
end
it 'includes a title attribute' do
- doc = reference_filter("Issue #{reference}")
+ doc = reference_filter("Issue #{written_reference}")
expect(doc.css('a').first.attr('title')).to eq issue.title
end
it 'escapes the title attribute' do
issue.update_attribute(:title, %{"></a>whatever<a title="})
- doc = reference_filter("Issue #{reference}")
+ doc = reference_filter("Issue #{written_reference}")
expect(doc.text).to eq "Issue #{reference}"
end
it 'renders non-HTML tooltips' do
- doc = reference_filter("Issue #{reference}")
+ doc = reference_filter("Issue #{written_reference}")
expect(doc.at_css('a')).not_to have_attribute('data-html')
end
it 'includes default classes' do
- doc = reference_filter("Issue #{reference}")
+ doc = reference_filter("Issue #{written_reference}")
expect(doc.css('a').first.attr('class')).to eq 'gfm gfm-issue'
end
it 'includes a data-project attribute' do
- doc = reference_filter("Issue #{reference}")
+ doc = reference_filter("Issue #{written_reference}")
link = doc.css('a').first
expect(link).to have_attribute('data-project')
@@ -105,7 +103,7 @@ RSpec.describe Banzai::Filter::References::IssueReferenceFilter, feature_categor
end
it 'includes a data-issue attribute' do
- doc = reference_filter("See #{reference}")
+ doc = reference_filter("See #{written_reference}")
link = doc.css('a').first
expect(link).to have_attribute('data-issue')
@@ -113,7 +111,7 @@ RSpec.describe Banzai::Filter::References::IssueReferenceFilter, feature_categor
end
it 'includes data attributes for issuable popover' do
- doc = reference_filter("See #{reference}")
+ doc = reference_filter("See #{written_reference}")
link = doc.css('a').first
expect(link.attr('data-project-path')).to eq project.full_path
@@ -121,21 +119,21 @@ RSpec.describe Banzai::Filter::References::IssueReferenceFilter, feature_categor
end
it 'includes a data-original attribute' do
- doc = reference_filter("See #{reference}")
+ doc = reference_filter("See #{written_reference}")
link = doc.css('a').first
expect(link).to have_attribute('data-original')
- expect(link.attr('data-original')).to eq reference
+ expect(link.attr('data-original')).to eq written_reference
end
it 'does not escape the data-original attribute' do
inner_html = 'element <code>node</code> inside'
- doc = reference_filter(%{<a href="#{reference}">#{inner_html}</a>})
+ doc = reference_filter(%{<a href="#{written_reference}">#{inner_html}</a>})
expect(doc.children.first.attr('data-original')).to eq inner_html
end
it 'includes a data-reference-format attribute' do
- doc = reference_filter("Issue #{reference}+")
+ doc = reference_filter("Issue #{written_reference}+")
link = doc.css('a').first
expect(link).to have_attribute('data-reference-format')
@@ -153,7 +151,7 @@ RSpec.describe Banzai::Filter::References::IssueReferenceFilter, feature_categor
end
it 'supports an :only_path context' do
- doc = reference_filter("Issue #{reference}", only_path: true)
+ doc = reference_filter("Issue #{written_reference}", only_path: true)
link = doc.css('a').first.attr('href')
expect(link).not_to match %r(https?://)
@@ -161,7 +159,7 @@ RSpec.describe Banzai::Filter::References::IssueReferenceFilter, feature_categor
end
it 'does not process links containing issue numbers followed by text' do
- href = "#{reference}st"
+ href = "#{written_reference}st"
doc = reference_filter("<a href='#{href}'></a>")
link = doc.css('a').first.attr('href')
@@ -169,6 +167,20 @@ RSpec.describe Banzai::Filter::References::IssueReferenceFilter, feature_categor
end
end
+ context 'standard internal reference' do
+ let(:written_reference) { "##{issue.iid}" }
+ let(:reference) { "##{issue.iid}" }
+
+ it_behaves_like 'an internal reference'
+ end
+
+ context 'alternative internal_reference' do
+ let(:written_reference) { "GL-#{issue.iid}" }
+ let(:reference) { "##{issue.iid}" }
+
+ it_behaves_like 'an internal reference'
+ end
+
context 'cross-project / cross-namespace complete reference' do
let(:reference) { "#{project2.full_path}##{issue.iid}" }
let(:issue) { create(:issue, project: project2) }
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder_spec.rb
index bf2f8d8159b..bd6af4269b4 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/aggregated/base_query_builder_spec.rb
@@ -17,7 +17,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Aggregated::BaseQueryBuilder d
let_it_be(:issue_outside_project) { create(:issue) }
let_it_be(:stage) do
- create(:cycle_analytics_project_stage,
+ create(:cycle_analytics_stage,
project: project,
start_event_identifier: :issue_created,
end_event_identifier: :issue_deployed_to_production
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb
index 7e36d89a2a1..aa0a1b66eef 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/aggregated/records_fetcher_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Aggregated::RecordsFetcher do
let_it_be(:issue_2) { create(:issue, project: project) }
let_it_be(:issue_3) { create(:issue, project: project) }
- let_it_be(:stage) { create(:cycle_analytics_project_stage, start_event_identifier: :issue_created, end_event_identifier: :issue_deployed_to_production, project: project) }
+ let_it_be(:stage) { create(:cycle_analytics_stage, start_event_identifier: :issue_created, end_event_identifier: :issue_deployed_to_production, namespace: project.reload.project_namespace) }
let_it_be(:stage_event_1) { create(:cycle_analytics_issue_stage_event, stage_event_hash_id: stage.stage_event_hash_id, project_id: project.id, issue_id: issue_1.id, start_event_timestamp: 2.years.ago, end_event_timestamp: 1.year.ago) } # duration: 1 year
let_it_be(:stage_event_2) { create(:cycle_analytics_issue_stage_event, stage_event_hash_id: stage.stage_event_hash_id, project_id: project.id, issue_id: issue_2.id, start_event_timestamp: 5.years.ago, end_event_timestamp: 2.years.ago) } # duration: 3 years
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/average_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/average_spec.rb
index e2fdd4918d5..de325454b34 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/average_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/average_spec.rb
@@ -21,7 +21,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Average do
let(:stage) do
build(
- :cycle_analytics_project_stage,
+ :cycle_analytics_stage,
start_event_identifier: Gitlab::Analytics::CycleAnalytics::StageEvents::IssueCreated.identifier,
end_event_identifier: Gitlab::Analytics::CycleAnalytics::StageEvents::IssueFirstMentionedInCommit.identifier,
project: project
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb
index e83ee0c6b75..59b2bacea50 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/base_query_builder_spec.rb
@@ -10,10 +10,10 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::BaseQueryBuilder do
let(:params) { { current_user: user } }
let(:records) do
- stage = build(:cycle_analytics_project_stage, {
+ stage = build(:cycle_analytics_stage, {
start_event_identifier: :merge_request_created,
end_event_identifier: :merge_request_merged,
- project: project
+ namespace: project.reload.project_namespace
})
described_class.new(stage: stage, params: params).build.to_a
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
index 4db5d64164e..39cfab49f54 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/median_spec.rb
@@ -9,10 +9,10 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::Median do
let(:stage) do
build(
- :cycle_analytics_project_stage,
+ :cycle_analytics_stage,
start_event_identifier: Gitlab::Analytics::CycleAnalytics::StageEvents::MergeRequestCreated.identifier,
end_event_identifier: Gitlab::Analytics::CycleAnalytics::StageEvents::MergeRequestMerged.identifier,
- project: project
+ namespace: project.reload.project_namespace
)
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
index 7f70a4cfc4e..e9a9dfeca82 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/records_fetcher_spec.rb
@@ -58,7 +58,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RecordsFetcher do
let_it_be(:issue2) { create(:issue, project: project, confidential: true) }
let(:stage) do
- build(:cycle_analytics_project_stage, {
+ build(:cycle_analytics_stage, {
start_event_identifier: :plan_stage_start,
end_event_identifier: :issue_first_mentioned_in_commit,
project: project
@@ -88,7 +88,7 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RecordsFetcher do
let(:mr1) { create(:merge_request, created_at: 5.days.ago, source_project: project, allow_broken: true) }
let(:mr2) { create(:merge_request, created_at: 4.days.ago, source_project: project, allow_broken: true) }
let(:stage) do
- build(:cycle_analytics_project_stage, {
+ build(:cycle_analytics_stage, {
start_event_identifier: :merge_request_created,
end_event_identifier: :merge_request_merged,
project: project
@@ -110,10 +110,10 @@ RSpec.describe Gitlab::Analytics::CycleAnalytics::RecordsFetcher do
let_it_be(:issue3) { create(:issue, project: project) }
let(:stage) do
- build(:cycle_analytics_project_stage, {
+ build(:cycle_analytics_stage, {
start_event_identifier: :plan_stage_start,
end_event_identifier: :issue_first_mentioned_in_commit,
- project: project
+ namespace: project.project_namespace
})
end
diff --git a/spec/lib/gitlab/analytics/cycle_analytics/sorting_spec.rb b/spec/lib/gitlab/analytics/cycle_analytics/sorting_spec.rb
index daf85ea379a..d0ada3d195b 100644
--- a/spec/lib/gitlab/analytics/cycle_analytics/sorting_spec.rb
+++ b/spec/lib/gitlab/analytics/cycle_analytics/sorting_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Gitlab::Analytics::CycleAnalytics::Sorting do
- let(:stage) { build(:cycle_analytics_project_stage, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) }
+ let(:stage) { build(:cycle_analytics_stage, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) }
subject(:order_values) { described_class.new(query: MergeRequest.joins(:metrics), stage: stage).apply(sort, direction).order_values }
diff --git a/spec/migrations/20230112141236_schedule_vulnerabilities_feedback_migration2_spec.rb b/spec/migrations/20230203122602_schedule_vulnerabilities_feedback_migration3_spec.rb
index 0e0f08fea0e..91604b1f57c 100644
--- a/spec/migrations/20230112141236_schedule_vulnerabilities_feedback_migration2_spec.rb
+++ b/spec/migrations/20230203122602_schedule_vulnerabilities_feedback_migration3_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
require_migration!
-RSpec.describe ScheduleVulnerabilitiesFeedbackMigration2, feature_category: :vulnerability_management do
+RSpec.describe ScheduleVulnerabilitiesFeedbackMigration3, feature_category: :vulnerability_management do
let(:migration) { described_class::MIGRATION }
describe '#up' do
diff --git a/spec/models/analytics/cycle_analytics/project_stage_spec.rb b/spec/models/analytics/cycle_analytics/project_stage_spec.rb
deleted file mode 100644
index 1e7335987a4..00000000000
--- a/spec/models/analytics/cycle_analytics/project_stage_spec.rb
+++ /dev/null
@@ -1,50 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Analytics::CycleAnalytics::ProjectStage do
- describe 'associations' do
- it { is_expected.to belong_to(:project).required }
- end
-
- it 'default stages must be valid' do
- project = build(:project)
-
- Gitlab::Analytics::CycleAnalytics::DefaultStages.all.each do |params|
- stage = described_class.new(params.merge(project: project))
- expect(stage).to be_valid
- end
- end
-
- it_behaves_like 'value stream analytics stage' do
- let(:factory) { :cycle_analytics_project_stage }
- let(:parent) { build(:project) }
- let(:parent_name) { :project }
- end
-
- describe '.distinct_stages_within_hierarchy' do
- let_it_be(:top_level_group) { create(:group) }
- let_it_be(:sub_group_1) { create(:group, parent: top_level_group) }
- let_it_be(:sub_group_2) { create(:group, parent: sub_group_1) }
-
- let_it_be(:project_1) { create(:project, group: sub_group_1) }
- let_it_be(:project_2) { create(:project, group: sub_group_2) }
- let_it_be(:project_3) { create(:project, group: top_level_group) }
-
- let_it_be(:stage1) { create(:cycle_analytics_project_stage, project: project_1, start_event_identifier: :issue_created, end_event_identifier: :issue_deployed_to_production) }
- let_it_be(:stage2) { create(:cycle_analytics_project_stage, project: project_3, start_event_identifier: :issue_created, end_event_identifier: :issue_deployed_to_production) }
-
- let_it_be(:stage3) { create(:cycle_analytics_project_stage, project: project_1, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) }
- let_it_be(:stage4) { create(:cycle_analytics_project_stage, project: project_3, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) }
-
- subject(:distinct_start_and_end_event_identifiers) { described_class.distinct_stages_within_hierarchy(top_level_group).to_a.pluck(:start_event_identifier, :end_event_identifier) }
-
- it 'returns distinct stages by start and end events (using stage_event_hash_id)' do
- expect(distinct_start_and_end_event_identifiers).to match_array(
- [
- %w[issue_created issue_deployed_to_production],
- %w[merge_request_created merge_request_merged]
- ])
- end
- end
-end
diff --git a/spec/models/analytics/cycle_analytics/project_value_stream_spec.rb b/spec/models/analytics/cycle_analytics/project_value_stream_spec.rb
deleted file mode 100644
index d84ecedc634..00000000000
--- a/spec/models/analytics/cycle_analytics/project_value_stream_spec.rb
+++ /dev/null
@@ -1,39 +0,0 @@
-# frozen_string_literal: true
-
-require 'spec_helper'
-
-RSpec.describe Analytics::CycleAnalytics::ProjectValueStream, type: :model do
- describe 'associations' do
- it { is_expected.to belong_to(:project) }
- it { is_expected.to have_many(:stages) }
- end
-
- describe 'validations' do
- it { is_expected.to validate_presence_of(:project) }
- it { is_expected.to validate_presence_of(:name) }
- it { is_expected.to validate_length_of(:name).is_at_most(100) }
-
- it 'validates uniqueness of name' do
- project = create(:project)
- create(:cycle_analytics_project_value_stream, name: 'test', project: project)
-
- value_stream = build(:cycle_analytics_project_value_stream, name: 'test', project: project)
-
- expect(value_stream).to be_invalid
- expect(value_stream.errors.messages).to eq(name: [I18n.t('errors.messages.taken')])
- end
- end
-
- it 'is not custom' do
- expect(described_class.new).not_to be_custom
- end
-
- describe '.build_default_value_stream' do
- it 'builds the default value stream' do
- project = build(:project)
-
- value_stream = described_class.build_default_value_stream(project)
- expect(value_stream.name).to eq('default')
- end
- end
-end
diff --git a/spec/models/analytics/cycle_analytics/stage_event_hash_spec.rb b/spec/models/analytics/cycle_analytics/stage_event_hash_spec.rb
index a24f237fa9d..43db610af5c 100644
--- a/spec/models/analytics/cycle_analytics/stage_event_hash_spec.rb
+++ b/spec/models/analytics/cycle_analytics/stage_event_hash_spec.rb
@@ -7,7 +7,6 @@ RSpec.describe Analytics::CycleAnalytics::StageEventHash, type: :model do
let(:hash_sha256) { 'does_not_matter' }
describe 'associations' do
- it { is_expected.to have_many(:cycle_analytics_project_stages) }
it { is_expected.to have_many(:cycle_analytics_stages) }
end
@@ -31,7 +30,7 @@ RSpec.describe Analytics::CycleAnalytics::StageEventHash, type: :model do
end
describe '.cleanup_if_unused' do
- it 'removes the record if there is no project or group stages with given stage events hash' do
+ it 'removes the record if there is no stages with given stage events hash' do
described_class.cleanup_if_unused(stage_event_hash.id)
expect(described_class.find_by_id(stage_event_hash.id)).to be_nil
diff --git a/spec/models/cycle_analytics/project_level_stage_adapter_spec.rb b/spec/models/cycle_analytics/project_level_stage_adapter_spec.rb
index ee13aae50dc..1516de8defd 100644
--- a/spec/models/cycle_analytics/project_level_stage_adapter_spec.rb
+++ b/spec/models/cycle_analytics/project_level_stage_adapter_spec.rb
@@ -10,11 +10,14 @@ RSpec.describe CycleAnalytics::ProjectLevelStageAdapter, type: :model do
end
end
- let_it_be(:project) { merge_request.target_project }
+ let_it_be(:project) { merge_request.target_project.reload }
let(:stage) do
- params = Gitlab::Analytics::CycleAnalytics::DefaultStages.find_by_name!(stage_name).merge(project: project)
- Analytics::CycleAnalytics::ProjectStage.new(params)
+ params = Gitlab::Analytics::CycleAnalytics::DefaultStages
+ .find_by_name!(stage_name)
+ .merge(namespace: project.project_namespace)
+
+ Analytics::CycleAnalytics::Stage.new(params)
end
around do |example|
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 9d6ab7d6137..cd7b46d40ae 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -121,8 +121,6 @@ RSpec.describe Project, factory_default: :keep, feature_category: :projects do
it { is_expected.to have_many(:lfs_file_locks) }
it { is_expected.to have_many(:project_deploy_tokens) }
it { is_expected.to have_many(:deploy_tokens).through(:project_deploy_tokens) }
- it { is_expected.to have_many(:cycle_analytics_stages).inverse_of(:project) }
- it { is_expected.to have_many(:value_streams).inverse_of(:project) }
it { is_expected.to have_many(:external_pull_requests) }
it { is_expected.to have_many(:sourced_pipelines) }
it { is_expected.to have_many(:source_pipelines) }
diff --git a/spec/serializers/analytics/cycle_analytics/stage_entity_spec.rb b/spec/serializers/analytics/cycle_analytics/stage_entity_spec.rb
index 8b45e8a64fc..7c53acbf168 100644
--- a/spec/serializers/analytics/cycle_analytics/stage_entity_spec.rb
+++ b/spec/serializers/analytics/cycle_analytics/stage_entity_spec.rb
@@ -3,7 +3,7 @@
require 'spec_helper'
RSpec.describe Analytics::CycleAnalytics::StageEntity do
- let(:stage) { build(:cycle_analytics_project_stage, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) }
+ let(:stage) { build(:cycle_analytics_stage, start_event_identifier: :merge_request_created, end_event_identifier: :merge_request_merged) }
subject(:entity_json) { described_class.new(Analytics::CycleAnalytics::StagePresenter.new(stage)).as_json }
diff --git a/spec/support/helpers/ci/template_helpers.rb b/spec/support/helpers/ci/template_helpers.rb
index 2cdd242ac22..cd3ab4bd82d 100644
--- a/spec/support/helpers/ci/template_helpers.rb
+++ b/spec/support/helpers/ci/template_helpers.rb
@@ -13,14 +13,21 @@ module Ci
def public_image_manifest(registry, repository, reference)
token = public_image_repository_token(registry, repository)
+ headers = {
+ 'Authorization' => "Bearer #{token}",
+ 'Accept' => 'application/vnd.docker.distribution.manifest.list.v2+json, application/vnd.oci.image.index.v1+json'
+ }
response = with_net_connect_allowed do
- Gitlab::HTTP.get(image_manifest_url(registry, repository, reference),
- headers: { 'Authorization' => "Bearer #{token}" })
+ Gitlab::HTTP.get(image_manifest_url(registry, repository, reference), headers: headers)
end
- return unless response.success?
-
- Gitlab::Json.parse(response.body)
+ if response.success?
+ Gitlab::Json.parse(response.body)
+ elsif response.not_found?
+ nil
+ else
+ raise "Could not retrieve manifest: #{response.body}"
+ end
end
def public_image_repository_token(registry, repository)
@@ -31,17 +38,17 @@ module Ci
Gitlab::HTTP.get(image_manifest_url(registry, repository, 'latest'))
end
- return unless response.unauthorized?
+ raise 'Unauthorized' unless response.unauthorized?
www_authenticate = response.headers['www-authenticate']
- return unless www_authenticate
+ raise 'Missing www-authenticate' unless www_authenticate
realm, service, scope = www_authenticate.split(',').map { |s| s[/\w+="(.*)"/, 1] }
token_response = with_net_connect_allowed do
Gitlab::HTTP.get(realm, query: { service: service, scope: scope })
end
- return unless token_response.success?
+ raise "Could not get token: #{token_response.body}" unless token_response.success?
token_response['token']
end
diff --git a/spec/support/rspec_order_todo.yml b/spec/support/rspec_order_todo.yml
index 58411fc3c4f..2259a20cd74 100644
--- a/spec/support/rspec_order_todo.yml
+++ b/spec/support/rspec_order_todo.yml
@@ -1636,7 +1636,6 @@
- './ee/spec/models/allowed_email_domain_spec.rb'
- './ee/spec/models/analytics/cycle_analytics/aggregation_context_spec.rb'
- './ee/spec/models/analytics/cycle_analytics/group_level_spec.rb'
-- './ee/spec/models/analytics/cycle_analytics/project_stage_spec.rb'
- './ee/spec/models/analytics/cycle_analytics/runtime_limiter_spec.rb'
- './ee/spec/models/analytics/devops_adoption/enabled_namespace_spec.rb'
- './ee/spec/models/analytics/devops_adoption/snapshot_spec.rb'
@@ -7729,7 +7728,6 @@
- './spec/models/analytics/cycle_analytics/aggregation_spec.rb'
- './spec/models/analytics/cycle_analytics/issue_stage_event_spec.rb'
- './spec/models/analytics/cycle_analytics/merge_request_stage_event_spec.rb'
-- './spec/models/analytics/cycle_analytics/project_stage_spec.rb'
- './spec/models/analytics/cycle_analytics/project_value_stream_spec.rb'
- './spec/models/analytics/cycle_analytics/stage_event_hash_spec.rb'
- './spec/models/analytics/usage_trends/measurement_spec.rb'
diff --git a/spec/workers/projects/refresh_build_artifacts_size_statistics_worker_spec.rb b/spec/workers/projects/refresh_build_artifacts_size_statistics_worker_spec.rb
index 00c45255316..99627ff1ad2 100644
--- a/spec/workers/projects/refresh_build_artifacts_size_statistics_worker_spec.rb
+++ b/spec/workers/projects/refresh_build_artifacts_size_statistics_worker_spec.rb
@@ -17,12 +17,14 @@ RSpec.describe Projects::RefreshBuildArtifactsSizeStatisticsWorker do
build(
:project_build_artifacts_size_refresh,
:running,
+ id: 99,
project_id: 77,
last_job_artifact_id: 123
)
end
it 'logs refresh information' do
+ expect(worker).to receive(:log_extra_metadata_on_done).with(:refresh_id, refresh.id)
expect(worker).to receive(:log_extra_metadata_on_done).with(:project_id, refresh.project_id)
expect(worker).to receive(:log_extra_metadata_on_done).with(:last_job_artifact_id, refresh.last_job_artifact_id)
expect(worker).to receive(:log_extra_metadata_on_done).with(:last_batch, refresh.destroyed?)