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>2021-02-11 03:08:50 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-02-11 03:08:50 +0300
commitced6c9ae9a9a80c884cafbea9c717b578dfac326 (patch)
tree7cb0e78e0639df4b2b79be94ddae77c304bd3357
parent02c3b2af448be6a5004e8d833cbcbf8e5f185210 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/batch_comments/components/draft_note.vue8
-rw-r--r--app/assets/javascripts/batch_comments/components/preview_item.vue15
-rw-r--r--app/assets/javascripts/diffs/components/diff_line_note_form.vue2
-rw-r--r--app/assets/javascripts/notes/components/discussion_notes.vue8
-rw-r--r--app/assets/javascripts/notes/components/noteable_note.vue4
-rw-r--r--app/assets/javascripts/protected_tags/protected_tag_edit.js9
-rw-r--r--app/assets/stylesheets/framework/tables.scss3
-rw-r--r--app/controllers/projects/merge_requests_controller.rb1
-rw-r--r--app/services/ci/create_job_artifacts_service.rb9
-rw-r--r--app/views/projects/protected_tags/shared/_tags_list.html.haml1
-rw-r--r--changelogs/unreleased/ar-fix-border-color.yml5
-rw-r--r--changelogs/unreleased/improve_vuln_tracking-db_add_tracking_table.yml5
-rw-r--r--changelogs/unreleased/rf-update-brakeman-rules.yml5
-rw-r--r--config/feature_flags/development/multiline_comments.yml8
-rw-r--r--config/feature_flags/development/usage_data_i_testing_metrics_report_artifact_uploaders.yml8
-rw-r--r--config/known_invalid_graphql_queries.yml1
-rw-r--r--db/migrate/20201108134919_add_finding_fingerprint_table.rb40
-rw-r--r--db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb2
-rw-r--r--db/schema_migrations/202011081349191
-rw-r--r--db/structure.sql32
-rw-r--r--doc/administration/gitaly/index.md33
-rw-r--r--doc/administration/gitaly/praefect.md58
-rw-r--r--doc/administration/logs.md5
-rw-r--r--doc/development/chatops_on_gitlabcom.md14
-rw-r--r--doc/development/code_review.md5
-rw-r--r--doc/development/documentation/styleguide/index.md16
-rw-r--r--doc/development/fe_guide/icons.md10
-rw-r--r--doc/user/project/merge_requests/code_quality.md34
-rw-r--r--doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md26
-rw-r--r--lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml3
-rw-r--r--lib/gitlab/usage_data_counters/known_events/common.yml5
-rw-r--r--locale/gitlab.pot105
-rw-r--r--rubocop/rubocop-migrations.yml1
-rw-r--r--spec/controllers/projects/security/configuration_controller_spec.rb2
-rw-r--r--spec/frontend/batch_comments/components/draft_note_spec.js21
-rw-r--r--spec/frontend/batch_comments/components/preview_item_spec.js19
-rw-r--r--spec/frontend/diffs/components/diff_line_note_form_spec.js1
-rw-r--r--spec/frontend/notes/components/discussion_notes_spec.js21
-rw-r--r--spec/frontend/notes/components/noteable_note_spec.js9
-rw-r--r--spec/requests/api/generic_packages_spec.rb30
-rw-r--r--spec/requests/api/group_import_spec.rb4
-rw-r--r--spec/requests/api/maven_packages_spec.rb11
-rw-r--r--spec/requests/api/nuget_project_packages_spec.rb14
-rw-r--r--spec/requests/api/project_import_spec.rb5
-rw-r--r--spec/requests/api/pypi_packages_spec.rb18
-rw-r--r--spec/requests/import/gitlab_groups_controller_spec.rb6
-rw-r--r--spec/requests/import/gitlab_projects_controller_spec.rb3
-rw-r--r--spec/services/ci/create_job_artifacts_service_spec.rb28
-rw-r--r--spec/services/ci/create_pipeline_service_spec.rb2
-rw-r--r--spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb6
-rw-r--r--spec/support/shared_contexts/requests/api/workhorse_shared_context.rb6
-rw-r--r--spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb9
-rw-r--r--spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb2
-rw-r--r--spec/support/shared_examples/requests/api/packages_shared_examples.rb10
54 files changed, 480 insertions, 229 deletions
diff --git a/app/assets/javascripts/batch_comments/components/draft_note.vue b/app/assets/javascripts/batch_comments/components/draft_note.vue
index 5564bca6df0..b480cf098f2 100644
--- a/app/assets/javascripts/batch_comments/components/draft_note.vue
+++ b/app/assets/javascripts/batch_comments/components/draft_note.vue
@@ -3,7 +3,6 @@
import { mapActions, mapGetters, mapState } from 'vuex';
import { GlButton } from '@gitlab/ui';
import NoteableNote from '~/notes/components/noteable_note.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import PublishButton from './publish_button.vue';
export default {
@@ -12,7 +11,6 @@ export default {
PublishButton,
GlButton,
},
- mixins: [glFeatureFlagsMixin()],
props: {
draft: {
type: Object,
@@ -63,14 +61,14 @@ export default {
this.isEditingDraft = false;
},
handleMouseEnter(draft) {
- if (this.glFeatures.multilineComments && draft.position) {
+ if (draft.position) {
this.setSelectedCommentPositionHover(draft.position.line_range);
}
},
handleMouseLeave(draft) {
- // Even though position isn't used here we still don't want to unecessarily call a mutation
+ // Even though position isn't used here we still don't want to unnecessarily call a mutation
// The lack of position tells us that highlighting is irrelevant in this context
- if (this.glFeatures.multilineComments && draft.position) {
+ if (draft.position) {
this.setSelectedCommentPositionHover();
}
},
diff --git a/app/assets/javascripts/batch_comments/components/preview_item.vue b/app/assets/javascripts/batch_comments/components/preview_item.vue
index 589734df795..7f3892ae066 100644
--- a/app/assets/javascripts/batch_comments/components/preview_item.vue
+++ b/app/assets/javascripts/batch_comments/components/preview_item.vue
@@ -3,7 +3,6 @@ import { mapGetters } from 'vuex';
import { GlSprintf, GlIcon } from '@gitlab/ui';
import { IMAGE_DIFF_POSITION_TYPE } from '~/diffs/constants';
import { sprintf, __ } from '~/locale';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import {
getStartLineNumber,
getEndLineNumber,
@@ -16,7 +15,7 @@ export default {
GlIcon,
GlSprintf,
},
- mixins: [resolvedStatusMixin, glFeatureFlagsMixin()],
+ mixins: [resolvedStatusMixin],
props: {
draft: {
type: Object,
@@ -71,6 +70,10 @@ export default {
return this.draft.position || this.discussion.position;
},
startLineNumber() {
+ if (this.position?.position_type === IMAGE_DIFF_POSITION_TYPE) {
+ // eslint-disable-next-line @gitlab/require-i18n-strings
+ return `${this.position.x}x ${this.position.y}y`;
+ }
return getStartLineNumber(this.position?.line_range);
},
endLineNumber() {
@@ -90,16 +93,12 @@ export default {
<span>
<span class="review-preview-item-header">
<gl-icon class="flex-shrink-0" :name="iconName" />
- <span
- class="bold text-nowrap"
- :class="{ 'gl-align-items-center': glFeatures.multilineComments }"
- >
+ <span class="bold text-nowrap gl-align-items-center">
<span class="review-preview-item-header-text block-truncated">
{{ titleText }}
</span>
<template v-if="showLinePosition">
- <template v-if="!glFeatures.multilineComments">:{{ linePosition }}</template>
- <template v-else-if="startLineNumber === endLineNumber">
+ <template v-if="startLineNumber === endLineNumber">
:<span :class="getLineClasses(startLineNumber)">{{ startLineNumber }}</span>
</template>
<gl-sprintf v-else :message="__(':%{startLine} to %{endLine}')">
diff --git a/app/assets/javascripts/diffs/components/diff_line_note_form.vue b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
index e4c64bb0e07..4908d600e4f 100644
--- a/app/assets/javascripts/diffs/components/diff_line_note_form.vue
+++ b/app/assets/javascripts/diffs/components/diff_line_note_form.vue
@@ -165,7 +165,7 @@ export default {
<template>
<div class="content discussion-form discussion-form-container discussion-notes">
- <div v-if="glFeatures.multilineComments" class="gl-mb-3 gl-text-gray-500 gl-pb-3">
+ <div class="gl-mb-3 gl-text-gray-500 gl-pb-3">
<multiline-comment-form
v-model="commentLineStart"
:line="line"
diff --git a/app/assets/javascripts/notes/components/discussion_notes.vue b/app/assets/javascripts/notes/components/discussion_notes.vue
index fc82f8e6b89..2d74bd8f74b 100644
--- a/app/assets/javascripts/notes/components/discussion_notes.vue
+++ b/app/assets/javascripts/notes/components/discussion_notes.vue
@@ -4,7 +4,6 @@ import { __ } from '~/locale';
import PlaceholderNote from '~/vue_shared/components/notes/placeholder_note.vue';
import PlaceholderSystemNote from '~/vue_shared/components/notes/placeholder_system_note.vue';
import SystemNote from '~/vue_shared/components/notes/system_note.vue';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { SYSTEM_NOTE } from '../constants';
import NoteableNote from './noteable_note.vue';
import ToggleRepliesWidget from './toggle_replies_widget.vue';
@@ -18,7 +17,6 @@ export default {
NoteEditedText,
DiscussionNotesRepliesWrapper,
},
- mixins: [glFeatureFlagsMixin()],
props: {
discussion: {
type: Object,
@@ -96,14 +94,14 @@ export default {
return note.isPlaceholderNote ? note.notes[0] : note;
},
handleMouseEnter(discussion) {
- if (this.glFeatures.multilineComments && discussion.position) {
+ if (discussion.position) {
this.setSelectedCommentPositionHover(discussion.position.line_range);
}
},
handleMouseLeave(discussion) {
- // Even though position isn't used here we still don't want to unecessarily call a mutation
+ // Even though position isn't used here we still don't want to unnecessarily call a mutation
// The lack of position tells us that highlighting is irrelevant in this context
- if (this.glFeatures.multilineComments && discussion.position) {
+ if (discussion.position) {
this.setSelectedCommentPositionHover();
}
},
diff --git a/app/assets/javascripts/notes/components/noteable_note.vue b/app/assets/javascripts/notes/components/noteable_note.vue
index 22941857f93..2eee932b5cc 100644
--- a/app/assets/javascripts/notes/components/noteable_note.vue
+++ b/app/assets/javascripts/notes/components/noteable_note.vue
@@ -3,7 +3,6 @@ import $ from 'jquery';
import { mapGetters, mapActions } from 'vuex';
import { escape } from 'lodash';
import { GlSprintf, GlSafeHtmlDirective as SafeHtml } from '@gitlab/ui';
-import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
import { truncateSha } from '~/lib/utils/text_utility';
import TimelineEntryItem from '~/vue_shared/components/notes/timeline_entry_item.vue';
import httpStatusCodes from '~/lib/utils/http_status';
@@ -38,7 +37,7 @@ export default {
directives: {
SafeHtml,
},
- mixins: [noteable, resolvable, glFeatureFlagsMixin()],
+ mixins: [noteable, resolvable],
props: {
note: {
type: Object,
@@ -160,7 +159,6 @@ export default {
},
showMultiLineComment() {
if (
- !this.glFeatures.multilineComments ||
!this.discussionRoot ||
this.startLineNumber.length === 0 ||
this.endLineNumber.length === 0
diff --git a/app/assets/javascripts/protected_tags/protected_tag_edit.js b/app/assets/javascripts/protected_tags/protected_tag_edit.js
index 59aa634872f..6b9506c6dfa 100644
--- a/app/assets/javascripts/protected_tags/protected_tag_edit.js
+++ b/app/assets/javascripts/protected_tags/protected_tag_edit.js
@@ -1,4 +1,4 @@
-import { __ } from '~/locale';
+import { s__ } from '~/locale';
import { deprecatedCreateFlash as flash } from '../flash';
import axios from '../lib/utils/axios_utils';
import ProtectedTagAccessDropdown from './protected_tag_access_dropdown';
@@ -48,11 +48,8 @@ export default class ProtectedTagEdit {
.catch(() => {
this.$allowedToCreateDropdownButton.enable();
- flash(
- __('Failed to update tag!'),
- 'alert',
- document.querySelector('.js-protected-tags-list'),
- );
+ window.scrollTo({ top: 0, behavior: 'smooth' });
+ flash(s__('ProjectSettings|Failed to update tag!'));
});
}
}
diff --git a/app/assets/stylesheets/framework/tables.scss b/app/assets/stylesheets/framework/tables.scss
index 89713fdbbea..92405c00c5e 100644
--- a/app/assets/stylesheets/framework/tables.scss
+++ b/app/assets/stylesheets/framework/tables.scss
@@ -69,9 +69,6 @@ table {
}
}
- td {
- border-color: $white-normal;
- }
}
.thead-white {
diff --git a/app/controllers/projects/merge_requests_controller.rb b/app/controllers/projects/merge_requests_controller.rb
index efbb958cbae..c30fc0f5a73 100644
--- a/app/controllers/projects/merge_requests_controller.rb
+++ b/app/controllers/projects/merge_requests_controller.rb
@@ -30,7 +30,6 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
before_action :authenticate_user!, only: [:assign_related_issues]
before_action :check_user_can_push_to_source_branch!, only: [:rebase]
before_action only: [:show] do
- push_frontend_feature_flag(:multiline_comments, @project, default_enabled: true)
push_frontend_feature_flag(:file_identifier_hash)
push_frontend_feature_flag(:batch_suggestions, @project, default_enabled: true)
push_frontend_feature_flag(:approvals_commented_by, @project, default_enabled: true)
diff --git a/app/services/ci/create_job_artifacts_service.rb b/app/services/ci/create_job_artifacts_service.rb
index 5efb3805bf7..f1fdc8e2490 100644
--- a/app/services/ci/create_job_artifacts_service.rb
+++ b/app/services/ci/create_job_artifacts_service.rb
@@ -7,6 +7,7 @@ module Ci
ArtifactsExistError = Class.new(StandardError)
LSIF_ARTIFACT_TYPE = 'lsif'
+ METRICS_REPORT_UPLOAD_EVENT_NAME = 'i_testing_metrics_report_artifact_uploaders'
OBJECT_STORAGE_ERRORS = [
Errno::EIO,
@@ -42,6 +43,8 @@ module Ci
artifact, artifact_metadata = build_artifact(artifacts_file, params, metadata_file)
result = parse_artifact(artifact)
+ track_artifact_uploader(artifact)
+
return result unless result[:status] == :success
persist_artifact(artifact, artifact_metadata, params)
@@ -152,6 +155,12 @@ module Ci
)
end
+ def track_artifact_uploader(artifact)
+ return unless artifact.file_type == 'metrics'
+
+ track_usage_event(METRICS_REPORT_UPLOAD_EVENT_NAME, @job.user_id)
+ end
+
def parse_dotenv_artifact(artifact)
Ci::ParseDotenvArtifactService.new(project, current_user).execute(artifact)
end
diff --git a/app/views/projects/protected_tags/shared/_tags_list.html.haml b/app/views/projects/protected_tags/shared/_tags_list.html.haml
index a5a43072744..f3cf4013898 100644
--- a/app/views/projects/protected_tags/shared/_tags_list.html.haml
+++ b/app/views/projects/protected_tags/shared/_tags_list.html.haml
@@ -23,7 +23,6 @@
%th
%tbody
%tr
- %td.flash-container{ colspan: 4 }
= yield
= paginate @protected_tags, theme: 'gitlab'
diff --git a/changelogs/unreleased/ar-fix-border-color.yml b/changelogs/unreleased/ar-fix-border-color.yml
new file mode 100644
index 00000000000..7558e2ecf79
--- /dev/null
+++ b/changelogs/unreleased/ar-fix-border-color.yml
@@ -0,0 +1,5 @@
+---
+title: Fix protected branches/tags border
+merge_request: 52816
+author:
+type: changed
diff --git a/changelogs/unreleased/improve_vuln_tracking-db_add_tracking_table.yml b/changelogs/unreleased/improve_vuln_tracking-db_add_tracking_table.yml
new file mode 100644
index 00000000000..c66e3afadf8
--- /dev/null
+++ b/changelogs/unreleased/improve_vuln_tracking-db_add_tracking_table.yml
@@ -0,0 +1,5 @@
+---
+title: 'Improve Vulnerability Tracking: Add fingerprints table'
+merge_request: 52720
+author:
+type: added
diff --git a/changelogs/unreleased/rf-update-brakeman-rules.yml b/changelogs/unreleased/rf-update-brakeman-rules.yml
new file mode 100644
index 00000000000..61fa8f0838c
--- /dev/null
+++ b/changelogs/unreleased/rf-update-brakeman-rules.yml
@@ -0,0 +1,5 @@
+---
+title: Update Ruby detection rules for SAST
+merge_request: 53414
+author:
+type: changed
diff --git a/config/feature_flags/development/multiline_comments.yml b/config/feature_flags/development/multiline_comments.yml
deleted file mode 100644
index ed38e1a575f..00000000000
--- a/config/feature_flags/development/multiline_comments.yml
+++ /dev/null
@@ -1,8 +0,0 @@
----
-name: multiline_comments
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37114
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/211255
-milestone: '13.2'
-type: development
-group: group::code review
-default_enabled: true
diff --git a/config/feature_flags/development/usage_data_i_testing_metrics_report_artifact_uploaders.yml b/config/feature_flags/development/usage_data_i_testing_metrics_report_artifact_uploaders.yml
new file mode 100644
index 00000000000..968ab3e63f1
--- /dev/null
+++ b/config/feature_flags/development/usage_data_i_testing_metrics_report_artifact_uploaders.yml
@@ -0,0 +1,8 @@
+---
+name: usage_data_i_testing_metrics_report_artifact_uploaders
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51670
+rollout_issue_url:
+milestone: '13.9'
+type: development
+group: group::testing
+default_enabled: true
diff --git a/config/known_invalid_graphql_queries.yml b/config/known_invalid_graphql_queries.yml
index 770366d76cf..08112132480 100644
--- a/config/known_invalid_graphql_queries.yml
+++ b/config/known_invalid_graphql_queries.yml
@@ -2,3 +2,4 @@
filenames:
- ee/app/assets/javascripts/on_demand_scans/graphql/dast_scan_create.mutation.graphql
- ee/app/assets/javascripts/oncall_schedules/graphql/mutations/update_oncall_schedule_rotation.mutation.graphql
+ - ee/app/assets/javascripts/security_configuration/api_fuzzing/graphql/api_fuzzing_ci_configuration.query.graphql
diff --git a/db/migrate/20201108134919_add_finding_fingerprint_table.rb b/db/migrate/20201108134919_add_finding_fingerprint_table.rb
new file mode 100644
index 00000000000..dd8ffe8e8aa
--- /dev/null
+++ b/db/migrate/20201108134919_add_finding_fingerprint_table.rb
@@ -0,0 +1,40 @@
+# frozen_string_literal: true
+
+class AddFindingFingerprintTable < ActiveRecord::Migration[6.0]
+ include Gitlab::Database::MigrationHelpers
+
+ DOWNTIME = false
+
+ FINGERPRINT_IDX = :idx_vuln_fingerprints_on_occurrences_id_and_fingerprint
+ UNIQ_IDX = :idx_vuln_fingerprints_uniqueness
+
+ def up
+ with_lock_retries do
+ create_table :vulnerability_finding_fingerprints do |t|
+ t.references :finding,
+ index: true,
+ null: false,
+ foreign_key: { to_table: :vulnerability_occurrences, column: :finding_id, on_delete: :cascade }
+
+ t.timestamps_with_timezone null: false
+
+ t.integer :algorithm_type, null: false
+ t.binary :fingerprint_sha256, null: false
+
+ t.index %i[finding_id fingerprint_sha256],
+ name: FINGERPRINT_IDX,
+ unique: true # only one link should exist between occurrence and the fingerprint
+
+ t.index %i[finding_id algorithm_type fingerprint_sha256],
+ name: UNIQ_IDX,
+ unique: true # these should be unique
+ end
+ end
+ end
+
+ def down
+ with_lock_retries do
+ drop_table :vulnerability_finding_fingerprints
+ end
+ end
+end
diff --git a/db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb b/db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb
index 157f0de0821..e944cee24e4 100644
--- a/db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb
+++ b/db/migrate/20201109080646_create_vulnerability_findings_remediations_join_table.rb
@@ -3,6 +3,7 @@
class CreateVulnerabilityFindingsRemediationsJoinTable < ActiveRecord::Migration[6.0]
DOWNTIME = false
+ # rubocop:disable Migration/CreateTableWithForeignKeys
def change
create_table :vulnerability_findings_remediations do |t|
t.references :vulnerability_occurrence, index: false, foreign_key: { on_delete: :cascade }
@@ -13,4 +14,5 @@ class CreateVulnerabilityFindingsRemediationsJoinTable < ActiveRecord::Migration
t.index [:vulnerability_occurrence_id, :vulnerability_remediation_id], unique: true, name: 'index_vulnerability_findings_remediations_on_unique_keys'
end
end
+ # rubocop:enable Migration/CreateTableWithForeignKeys
end
diff --git a/db/schema_migrations/20201108134919 b/db/schema_migrations/20201108134919
new file mode 100644
index 00000000000..10e88ae9359
--- /dev/null
+++ b/db/schema_migrations/20201108134919
@@ -0,0 +1 @@
+6643e5b4c5597d92c94115f392bfbd5cfce9884eb0bcb18f9629855f3711eed0 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index 2f10967b907..e0cc67d365a 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -18141,6 +18141,24 @@ CREATE SEQUENCE vulnerability_feedback_id_seq
ALTER SEQUENCE vulnerability_feedback_id_seq OWNED BY vulnerability_feedback.id;
+CREATE TABLE vulnerability_finding_fingerprints (
+ id bigint NOT NULL,
+ finding_id bigint NOT NULL,
+ created_at timestamp with time zone NOT NULL,
+ updated_at timestamp with time zone NOT NULL,
+ algorithm_type integer NOT NULL,
+ fingerprint_sha256 bytea NOT NULL
+);
+
+CREATE SEQUENCE vulnerability_finding_fingerprints_id_seq
+ START WITH 1
+ INCREMENT BY 1
+ NO MINVALUE
+ NO MAXVALUE
+ CACHE 1;
+
+ALTER SEQUENCE vulnerability_finding_fingerprints_id_seq OWNED BY vulnerability_finding_fingerprints.id;
+
CREATE TABLE vulnerability_finding_links (
id bigint NOT NULL,
created_at timestamp with time zone NOT NULL,
@@ -19382,6 +19400,8 @@ ALTER TABLE ONLY vulnerability_external_issue_links ALTER COLUMN id SET DEFAULT
ALTER TABLE ONLY vulnerability_feedback ALTER COLUMN id SET DEFAULT nextval('vulnerability_feedback_id_seq'::regclass);
+ALTER TABLE ONLY vulnerability_finding_fingerprints ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_fingerprints_id_seq'::regclass);
+
ALTER TABLE ONLY vulnerability_finding_links ALTER COLUMN id SET DEFAULT nextval('vulnerability_finding_links_id_seq'::regclass);
ALTER TABLE ONLY vulnerability_findings_remediations ALTER COLUMN id SET DEFAULT nextval('vulnerability_findings_remediations_id_seq'::regclass);
@@ -20957,6 +20977,9 @@ ALTER TABLE ONLY vulnerability_external_issue_links
ALTER TABLE ONLY vulnerability_feedback
ADD CONSTRAINT vulnerability_feedback_pkey PRIMARY KEY (id);
+ALTER TABLE ONLY vulnerability_finding_fingerprints
+ ADD CONSTRAINT vulnerability_finding_fingerprints_pkey PRIMARY KEY (id);
+
ALTER TABLE ONLY vulnerability_finding_links
ADD CONSTRAINT vulnerability_finding_links_pkey PRIMARY KEY (id);
@@ -21294,6 +21317,10 @@ CREATE INDEX idx_security_scans_on_scan_type ON security_scans USING btree (scan
CREATE UNIQUE INDEX idx_serverless_domain_cluster_on_clusters_applications_knative ON serverless_domain_cluster USING btree (clusters_applications_knative_id);
+CREATE UNIQUE INDEX idx_vuln_fingerprints_on_occurrences_id_and_fingerprint ON vulnerability_finding_fingerprints USING btree (finding_id, fingerprint_sha256);
+
+CREATE UNIQUE INDEX idx_vuln_fingerprints_uniqueness ON vulnerability_finding_fingerprints USING btree (finding_id, algorithm_type, fingerprint_sha256);
+
CREATE UNIQUE INDEX idx_vulnerability_ext_issue_links_on_vulne_id_and_ext_issue ON vulnerability_external_issue_links USING btree (vulnerability_id, external_type, external_project_key, external_issue_key);
CREATE UNIQUE INDEX idx_vulnerability_ext_issue_links_on_vulne_id_and_link_type ON vulnerability_external_issue_links USING btree (vulnerability_id, link_type) WHERE (link_type = 1);
@@ -23596,6 +23623,8 @@ CREATE INDEX index_vulnerability_feedback_on_merge_request_id ON vulnerability_f
CREATE INDEX index_vulnerability_feedback_on_pipeline_id ON vulnerability_feedback USING btree (pipeline_id);
+CREATE INDEX index_vulnerability_finding_fingerprints_on_finding_id ON vulnerability_finding_fingerprints USING btree (finding_id);
+
CREATE INDEX index_vulnerability_findings_remediations_on_remediation_id ON vulnerability_findings_remediations USING btree (vulnerability_remediation_id);
CREATE UNIQUE INDEX index_vulnerability_findings_remediations_on_unique_keys ON vulnerability_findings_remediations USING btree (vulnerability_occurrence_id, vulnerability_remediation_id);
@@ -26119,6 +26148,9 @@ ALTER TABLE ONLY merge_trains
ALTER TABLE ONLY ci_runner_namespaces
ADD CONSTRAINT fk_rails_f9d9ed3308 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
+ALTER TABLE ONLY vulnerability_finding_fingerprints
+ ADD CONSTRAINT fk_rails_fa411253b2 FOREIGN KEY (finding_id) REFERENCES vulnerability_occurrences(id) ON DELETE CASCADE;
+
ALTER TABLE ONLY requirements_management_test_reports
ADD CONSTRAINT fk_rails_fb3308ad55 FOREIGN KEY (requirement_id) REFERENCES requirements(id) ON DELETE CASCADE;
diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md
index 28283beb642..00376679c88 100644
--- a/doc/administration/gitaly/index.md
+++ b/doc/administration/gitaly/index.md
@@ -814,6 +814,39 @@ Though the name of the Prometheus metric contains `rate_limiting`, it is a concu
a rate limiter. If a Gitaly client makes 1000 requests in a row very quickly, concurrency does not
exceed 1 and the concurrency limiter has no effect.
+## Background Repository Optimization
+
+Empty directories and unneeded config settings may accumulate in a repository and
+slow down Git operations. Gitaly can schedule a daily background task with a maximum duration
+to clean up these items and improve performance.
+
+WARNING:
+This is an experimental feature and may place significant load on the host while running.
+Make sure to schedule this during off-peak hours and keep the duration short (for example, 30-60 minutes).
+
+**For Omnibus GitLab**
+
+Edit `/etc/gitlab/gitlab.rb` and add:
+
+```ruby
+gitaly['daily_maintenance_start_hour'] = 4
+gitaly['daily_maintenance_start_minute'] = 30
+gitaly['daily_maintenance_duration'] = '30m'
+gitaly['daily_maintenance_storages'] = ["default"]
+```
+
+**For installations from source**
+
+Edit `/home/git/gitaly/config.toml` and add:
+
+```toml
+[daily_maintenance]
+start_hour = 4
+start_minute = 30
+duration = '30m'
+storages = ["default"]
+```
+
## Rotate Gitaly authentication token
Rotating credentials in a production environment often requires downtime, causes outages, or both.
diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md
index b4fd607c4be..8cb33adbd94 100644
--- a/doc/administration/gitaly/praefect.md
+++ b/doc/administration/gitaly/praefect.md
@@ -1111,7 +1111,7 @@ replication factor offers better redundancy and distribution of read workload, b
in a higher storage cost. By default, Praefect replicates repositories to every storage in a
virtual storage.
-### Variable replication factor
+### Configure replication factors
WARNING:
The feature is not production ready yet. After you set a replication factor, you can't unset it
@@ -1122,36 +1122,50 @@ strategy is not production ready yet.
Praefect supports configuring a replication factor on a per-repository basis, by assigning
specific storage nodes to host a repository.
-[In an upcoming release](https://gitlab.com/gitlab-org/gitaly/-/issues/3362), we intend to
-support configuring a default replication factor for a virtual storage. The default replication factor
-is applied to every newly-created repository.
-
Praefect does not store the actual replication factor, but assigns enough storages to host the repository
so the desired replication factor is met. If a storage node is later removed from the virtual storage,
the replication factor of repositories assigned to the storage is decreased accordingly.
-The only way to configure a repository's replication factor is the `set-replication-factor`
-sub-command. `set-replication-factor` automatically assigns or unassigns random storage nodes as necessary to
-reach the desired replication factor. The repository's primary node is always assigned
-first and is never unassigned.
+You can configure:
+
+- A default replication factor for each virtual storage that is applied to newly-created repositories.
+ The configuration is added to the `/etc/gitlab/gitlab.rb` file:
+
+ ```ruby
+ praefect['virtual_storages'] = {
+ 'default' => {
+ 'default_replication_factor' => 1,
+ # nodes...
+ 'gitaly-1' => {
+ 'address' => 'tcp://GITALY_HOST:8075',
+ 'token' => 'PRAEFECT_INTERNAL_TOKEN',
+ },
+ }
+ }
+ ```
-```shell
-sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage <virtual-storage> -repository <relative-path> -replication-factor <replication-factor>
-```
+- A replication factor for an existing repository using the `set-replication-factor` sub-command.
+ `set-replication-factor` automatically assigns or unassigns random storage nodes as
+ necessary to reach the desired replication factor. The repository's primary node is
+ always assigned first and is never unassigned.
-- `-virtual-storage` is the virtual storage the repository is located in.
-- `-repository` is the repository's relative path in the storage.
-- `-replication-factor` is the desired replication factor of the repository. The minimum value is
- `1`, as the primary needs a copy of the repository. The maximum replication factor is the number of
- storages in the virtual storage.
+ ```shell
+ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage <virtual-storage> -repository <relative-path> -replication-factor <replication-factor>
+ ```
-On success, the assigned host storages are printed. For example:
+ - `-virtual-storage` is the virtual storage the repository is located in.
+ - `-repository` is the repository's relative path in the storage.
+ - `-replication-factor` is the desired replication factor of the repository. The minimum value is
+ `1`, as the primary needs a copy of the repository. The maximum replication factor is the number of
+ storages in the virtual storage.
-```shell
-$ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage default -repository @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git -replication-factor 2
+ On success, the assigned host storages are printed. For example:
-current assignments: gitaly-1, gitaly-2
-```
+ ```shell
+ $ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.toml set-replication-factor -virtual-storage default -repository @hashed/3f/db/3fdba35f04dc8c462986c992bcf875546257113072a909c162f7e470e581e278.git -replication-factor 2
+
+ current assignments: gitaly-1, gitaly-2
+ ```
## Automatic failover and leader election
diff --git a/doc/administration/logs.md b/doc/administration/logs.md
index 3ea8efad51a..5c36f1af960 100644
--- a/doc/administration/logs.md
+++ b/doc/administration/logs.md
@@ -413,11 +413,14 @@ For example:
## Sidekiq Logs
+NOTE:
+In Omnibus GitLab `12.10` or earlier, the Sidekiq log lives in `/var/log/gitlab/gitlab-rails/sidekiq.log`.
+
For Omnibus installations, some Sidekiq logs reside in `/var/log/gitlab/sidekiq/current` and as follows.
### `sidekiq.log`
-This file lives in `/var/log/gitlab/gitlab-rails/sidekiq.log` for
+This file lives in `/var/log/gitlab/sidekiq/current` for
Omnibus GitLab packages or in `/home/git/gitlab/log/sidekiq.log` for
installations from source.
diff --git a/doc/development/chatops_on_gitlabcom.md b/doc/development/chatops_on_gitlabcom.md
index 6cb2c7cc2dc..0341abf5eeb 100644
--- a/doc/development/chatops_on_gitlabcom.md
+++ b/doc/development/chatops_on_gitlabcom.md
@@ -35,14 +35,12 @@ To request access to ChatOps on GitLab.com:
in the `#chat-ops-test` Slack channel, replacing `<username>` with your username:
`/chatops run member add <username> gitlab-com/chatops --ops`
- <!-- vale gitlab.FirstPerson = NO -->
-
- > Hi `__BUDDY_HANDLE__` and `__MANAGER_HANDLE__`, could you please add me to
- > the ChatOps project in Ops by running this command:
- > `/chatops run member add <username> gitlab-com/chatops --ops` in the
- > `#chat-ops-test` Slack channel? Thanks in advance.
-
- <!-- vale gitlab.FirstPerson = YES -->
+ ```plaintext
+ Hi <__BUDDY_HANDLE__> and <__MANAGER_HANDLE__>, could you please add me to
+ the ChatOps project in Ops by running this command:
+ `/chatops run member add <username> gitlab-com/chatops --ops` in the
+ `#chat-ops-test` Slack channel? Thanks in advance.
+ ```
1. Ensure you've set up two-factor authentication.
1. After you're added to the ChatOps project, run this command to check your user
diff --git a/doc/development/code_review.md b/doc/development/code_review.md
index 0090372bb9f..dada6adcce7 100644
--- a/doc/development/code_review.md
+++ b/doc/development/code_review.md
@@ -283,10 +283,7 @@ first time.
you forget to remove any debugging code?
- Consider providing instructions on how to test the merge request. This can be
helpful for reviewers not familiar with the product feature or area of the codebase.
-<!-- vale gitlab.FutureTense = NO -->
-- Be grateful for the reviewer's suggestions. ("Good call. I'll make that
- change.")
-<!-- vale gitlab.FutureTense = YES -->
+- Be grateful for the reviewer's suggestions. (`Good call. I'll make that change.`)
- Don't take it personally. The review is of the code, not of you.
- Explain why the code exists. ("It's like that because of these reasons. Would
it be more clear if I rename this class/file/method/variable?")
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index baee01b8245..5e8a2b2356a 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -742,8 +742,6 @@ Items nested in lists should always align with the first character of the list
item. In unordered lists (using `-`), this means two spaces for each level of
indentation:
-<!-- vale off -->
-
````markdown
- Unordered list item 1
@@ -765,12 +763,8 @@ indentation:
![an image that will nest inside list item 4](image.png)
````
-<!-- vale on -->
-
For ordered lists, use three spaces for each level of indentation:
-<!-- vale off -->
-
````markdown
1. Ordered list item 1
@@ -792,8 +786,6 @@ For ordered lists, use three spaces for each level of indentation:
![an image that will nest inside list item 4](image.png)
````
-<!-- vale on -->
-
You can nest full lists inside other lists using the same rules as above. If you
want to mix types, that's also possible, if you don't mix items at the same
level:
@@ -1324,8 +1316,6 @@ hidden on the documentation site, but is displayed by `/help`.
- For regular fenced code blocks, always use a highlighting class corresponding to
the language for better readability. Examples:
- <!-- vale off -->
-
````markdown
```ruby
Ruby code
@@ -1344,8 +1334,6 @@ hidden on the documentation site, but is displayed by `/help`.
```
````
- <!-- vale on -->
-
Syntax highlighting is required for fenced code blocks added to the GitLab
documentation. Refer to this table for the most common language classes,
or check the [complete list](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers)
@@ -1834,8 +1822,6 @@ Configuration procedures can require users to edit configuration files, reconfig
GitLab, or restart GitLab. Use these styles to document these steps, replacing
`PATH/TO` with the appropriate path:
-<!-- vale off -->
-
````markdown
**For Omnibus installations**
@@ -1863,8 +1849,6 @@ GitLab, or restart GitLab. Use these styles to document these steps, replacing
GitLab for the changes to take effect.
````
-<!-- vale on -->
-
In this case:
- Bold the installation method's name.
diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md
index 821334e3008..a7b62fbb267 100644
--- a/doc/development/fe_guide/icons.md
+++ b/doc/development/fe_guide/icons.md
@@ -26,15 +26,11 @@ To use a sprite Icon in HAML or Rails we use a specific helper function:
sprite_icon(icon_name, size: nil, css_class: '')
```
-<!-- vale gitlab.Spelling = NO -->
-
-- **icon_name**: Use the icon_name for the SVG sprite in the list of
+- **`icon_name`**: Use the `icon_name` for the SVG sprite in the list of
([GitLab SVGs](https://gitlab-org.gitlab.io/gitlab-svgs)).
-- **size (optional)**: Use one of the following sizes : 16, 24, 32, 48, 72 (this
+- **`size` (optional)**: Use one of the following sizes : 16, 24, 32, 48, 72 (this
is translated into a `s16` class)
-- **css_class (optional)**: If you want to add additional CSS classes.
-
-<!-- vale gitlab.Spelling = YES -->
+- **`css_class` (optional)**: If you want to add additional CSS classes.
**Example**
diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md
index 0fb53884ea2..1cab8caf5d3 100644
--- a/doc/user/project/merge_requests/code_quality.md
+++ b/doc/user/project/merge_requests/code_quality.md
@@ -161,6 +161,7 @@ to be consider, but may be preferable depending on your use case.
--locked="false" \
--access-level="not_protected" \
--docker-volumes "/cache"\
+ --docker-volumes "/builds:/builds"\
--docker-volumes "/var/run/docker.sock:/var/run/docker.sock" \
--registration-token="<project_token>" \
--non-interactive
@@ -173,8 +174,8 @@ to be consider, but may be preferable depending on your use case.
in the previous step.
```shell
- --builds-dir /tmp/builds
- --docker-volumes /tmp/builds:/tmp/builds
+ --builds-dir "/tmp/builds"
+ --docker-volumes "/tmp/builds:/tmp/builds" # Use this instead of --docker-volumes "/builds:/builds"
```
The resulting configuration:
@@ -456,3 +457,32 @@ This can be due to multiple reasons:
GitLab only uses the Code Quality artifact from the latest created job (with the largest job ID).
If multiple jobs in a pipeline generate a code quality artifact, those of earlier jobs are ignored.
To avoid confusion, configure only one job to generate a `gl-code-quality-report.json`.
+
+### Rubocop errors
+
+When using Code Quality jobs on a **Ruby** project, you can encounter problems running Rubocop.
+For example, the following error can appear when using either a very recent or very old version
+of Ruby:
+
+```plaintext
+/usr/local/bundle/gems/rubocop-0.52.1/lib/rubocop/config.rb:510:in `check_target_ruby':
+Unknown Ruby version 2.7 found in `.ruby-version`. (RuboCop::ValidationError)
+Supported versions: 2.1, 2.2, 2.3, 2.4, 2.5
+```
+
+This is caused by the default version of **rubocop** used by the check engine not covering
+support for the Ruby version in use.
+To use a custom version of **rubocop** that
+[supports the version of Ruby used by the project](https://docs.rubocop.org/rubocop/compatibility.html#support-matrix),
+you can [override the configuration through a `.codeclimate.yml` file](https://docs.codeclimate.com/docs/rubocop#using-rubocops-newer-versions)
+created in the project repository.
+
+For example, to specify using **rubocop** release **0.67**:
+
+```yaml
+version: "2"
+plugins:
+ rubocop:
+ enabled: true
+ channel: rubocop-0-67
+```
diff --git a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
index f94b0b40ed6..94f48fa544f 100644
--- a/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
+++ b/doc/user/project/merge_requests/reviewing_and_managing_merge_requests.md
@@ -195,12 +195,7 @@ to expand the diff lines and leave a comment, just as you would for a changed li
### Commenting on multiple lines
> - [Introduced](https://gitlab.com/gitlab-org/ux-research/-/issues/870) in GitLab 13.2.
-> - It's deployed behind a feature flag, enabled by default.
-> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/221268) on GitLab 13.3.
-> - It's enabled on GitLab.com.
-> - It can be disabled or enabled per-project.
-> - It's recommended for production use.
-> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-multiline-comments). **(FREE SELF)**
+> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/299121) in GitLab 13.9.
GitLab provides a way to select which lines of code a comment refers to. After starting a comment
a dropdown selector is shown to select the first line that this comment refers to.
@@ -216,25 +211,6 @@ above it.
![Multiline comment selection displayed above comment](img/multiline-comment-saved.png)
-### Enable or disable multiline comments **(FREE SELF)**
-
-The multiline comments feature is under development but ready for production use.
-It is deployed behind a feature flag that is **disabled by default**.
-[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md)
-can opt to enable it for your instance.
-
-To disable it:
-
-```ruby
-Feature.disable(:multiline_comments)
-```
-
-To enable it:
-
-```ruby
-Feature.enable(:multiline_comments)
-```
-
## Pipeline status in merge requests widgets
If you've set up [GitLab CI/CD](../../../ci/README.md) in your project,
diff --git a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
index 56c6fbd96bc..91750af9a79 100644
--- a/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
+++ b/lib/gitlab/ci/templates/Security/SAST.gitlab-ci.yml
@@ -66,7 +66,8 @@ brakeman-sast:
- if: $CI_COMMIT_BRANCH &&
$SAST_DEFAULT_ANALYZERS =~ /brakeman/
exists:
- - 'config/routes.rb'
+ - '**/*.rb'
+ - '**/Gemfile'
eslint-sast:
extends: .sast-analyzer
diff --git a/lib/gitlab/usage_data_counters/known_events/common.yml b/lib/gitlab/usage_data_counters/known_events/common.yml
index cd64beea769..a877e0dc042 100644
--- a/lib/gitlab/usage_data_counters/known_events/common.yml
+++ b/lib/gitlab/usage_data_counters/known_events/common.yml
@@ -278,6 +278,11 @@
redis_slot: testing
aggregation: weekly
feature_flag: usage_data_i_testing_load_performance_widget_total
+- name: i_testing_metrics_report_artifact_uploaders
+ category: testing
+ redis_slot: testing
+ aggregation: weekly
+ feature_flag: usage_data_i_testing_metrics_report_artifact_uploaders
# Project Management group
- name: g_project_management_issue_title_changed
category: issues_edit
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 02977c28ef3..52d2559816e 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -1393,6 +1393,90 @@ msgstr ""
msgid "API Token"
msgstr ""
+msgid "APIFuzzing|API Fuzzing Configuration"
+msgstr ""
+
+msgid "APIFuzzing|Authentication is handled by providing HTTP basic authentication token as a header or cookie. %{linkStart}More information%{linkEnd}."
+msgstr ""
+
+msgid "APIFuzzing|Base URL of API fuzzing target."
+msgstr ""
+
+msgid "APIFuzzing|Choose a method"
+msgstr ""
+
+msgid "APIFuzzing|Choose a profile"
+msgstr ""
+
+msgid "APIFuzzing|Customize common API fuzzing settings to suit your requirements. For details of more advanced configuration options, see the %{docsLinkStart}GitLab API Fuzzing documentation%{docsLinkEnd}."
+msgstr ""
+
+msgid "APIFuzzing|Enable authentication"
+msgstr ""
+
+msgid "APIFuzzing|Ex: $TestPassword"
+msgstr ""
+
+msgid "APIFuzzing|Ex: $TestUsername"
+msgstr ""
+
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har"
+msgstr ""
+
+msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.json"
+msgstr ""
+
+msgid "APIFuzzing|Generate code snippet"
+msgstr ""
+
+msgid "APIFuzzing|HAR files may contain sensitive information such as authentication tokens, API keys, and session cookies. We recommend that you review the HAR files' contents before adding them to a repository."
+msgstr ""
+
+msgid "APIFuzzing|Instead of entering the password directly, enter the key of the CI variable set to the password."
+msgstr ""
+
+msgid "APIFuzzing|Instead of entering the username directly, enter the key of the CI variable set to the username."
+msgstr ""
+
+msgid "APIFuzzing|Make sure your credentials are secured"
+msgstr ""
+
+msgid "APIFuzzing|Password for basic authentication"
+msgstr ""
+
+msgid "APIFuzzing|Scan mode"
+msgstr ""
+
+msgid "APIFuzzing|Scan profile"
+msgstr ""
+
+msgid "APIFuzzing|Show code snippet for the profile"
+msgstr ""
+
+msgid "APIFuzzing|Target URL"
+msgstr ""
+
+msgid "APIFuzzing|There are two ways to perform scans."
+msgstr ""
+
+msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. A user with maintainer access rights can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area. We detected that you are not a maintainer. Commit your changes and assign them to a maintainer to update the credentials before merging."
+msgstr ""
+
+msgid "APIFuzzing|To prevent a security leak, authentication info must be added as a %{ciVariablesLinkStart}CI variable%{ciVariablesLinkEnd}. As a user with maintainer access rights, you can manage CI variables in the %{ciSettingsLinkStart}Settings%{ciSettingsLinkEnd} area."
+msgstr ""
+
+msgid "APIFuzzing|Use this tool to generate API fuzzing configuration YAML to copy into your .gitlab-ci.yml file. This tool does not reflect or update your .gitlab-ci.yml file automatically."
+msgstr ""
+
+msgid "APIFuzzing|Username for basic authentication"
+msgstr ""
+
+msgid "APIFuzzing|We recommend that you review the JSON specifications file before adding it to a repository."
+msgstr ""
+
+msgid "APIFuzzing|You may need a maintainer's help to secure your credentials."
+msgstr ""
+
msgid "AWS Access Key"
msgstr ""
@@ -4138,6 +4222,9 @@ msgstr ""
msgid "Authenticating"
msgstr ""
+msgid "Authentication"
+msgstr ""
+
msgid "Authentication Failure"
msgstr ""
@@ -11850,6 +11937,9 @@ msgstr ""
msgid "Evidence collection"
msgstr ""
+msgid "Ex: Example.com"
+msgstr ""
+
msgid "Exactly one of %{attributes} is required"
msgstr ""
@@ -12297,9 +12387,6 @@ msgstr ""
msgid "Failed to update issues, please try again."
msgstr ""
-msgid "Failed to update tag!"
-msgstr ""
-
msgid "Failed to update the Canary Ingress."
msgstr ""
@@ -14510,6 +14597,12 @@ msgstr ""
msgid "Guideline"
msgstr ""
+msgid "HAR (HTTP Archive)"
+msgstr ""
+
+msgid "HAR file path"
+msgstr ""
+
msgid "HTTP Basic: Access denied\\nYou must use a personal access token with 'api' scope for Git over HTTP.\\nYou can generate one at %{profile_personal_access_tokens_url}"
msgstr ""
@@ -20667,6 +20760,12 @@ msgstr ""
msgid "Open"
msgstr ""
+msgid "Open API"
+msgstr ""
+
+msgid "Open API specification file path"
+msgstr ""
+
msgid "Open Selection"
msgstr ""
diff --git a/rubocop/rubocop-migrations.yml b/rubocop/rubocop-migrations.yml
index 41bd2a4ce7d..45f8270b34d 100644
--- a/rubocop/rubocop-migrations.yml
+++ b/rubocop/rubocop-migrations.yml
@@ -38,6 +38,7 @@ Migration/UpdateLargeTable:
- :users
- :user_preferences
- :user_details
+ - :vulnerability_occurrences
- :web_hook_logs
DeniedMethods:
- :change_column_type_concurrently
diff --git a/spec/controllers/projects/security/configuration_controller_spec.rb b/spec/controllers/projects/security/configuration_controller_spec.rb
index afbebbad3d1..ef255d1efd0 100644
--- a/spec/controllers/projects/security/configuration_controller_spec.rb
+++ b/spec/controllers/projects/security/configuration_controller_spec.rb
@@ -7,6 +7,8 @@ RSpec.describe Projects::Security::ConfigurationController do
let(:user) { create(:user) }
before do
+ allow(controller).to receive(:ensure_security_and_compliance_enabled!)
+
sign_in(user)
end
diff --git a/spec/frontend/batch_comments/components/draft_note_spec.js b/spec/frontend/batch_comments/components/draft_note_spec.js
index ae7134b63c8..9e56b8aeb36 100644
--- a/spec/frontend/batch_comments/components/draft_note_spec.js
+++ b/spec/frontend/batch_comments/components/draft_note_spec.js
@@ -21,14 +21,11 @@ describe('Batch comments draft note component', () => {
const getList = () => getByRole(wrapper.element, 'list');
- const createComponent = (propsData = { draft }, features = {}) => {
+ const createComponent = (propsData = { draft }) => {
wrapper = shallowMount(localVue.extend(DraftNote), {
store,
propsData,
localVue,
- provide: {
- glFeatures: { multilineComments: true, ...features },
- },
});
jest.spyOn(wrapper.vm.$store, 'dispatch').mockImplementation();
@@ -145,16 +142,14 @@ describe('Batch comments draft note component', () => {
describe('multiline comments', () => {
describe.each`
- desc | props | features | event | expectedCalls
- ${'with `draft.position`'} | ${draftWithLineRange} | ${{}} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]}
- ${'with `draft.position`'} | ${draftWithLineRange} | ${{}} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]}
- ${'with `draft.position`'} | ${draftWithLineRange} | ${{ multilineComments: false }} | ${'mouseenter'} | ${[]}
- ${'with `draft.position`'} | ${draftWithLineRange} | ${{ multilineComments: false }} | ${'mouseleave'} | ${[]}
- ${'without `draft.position`'} | ${{}} | ${{}} | ${'mouseenter'} | ${[]}
- ${'without `draft.position`'} | ${{}} | ${{}} | ${'mouseleave'} | ${[]}
- `('$desc and features $features', ({ props, event, features, expectedCalls }) => {
+ desc | props | event | expectedCalls
+ ${'with `draft.position`'} | ${draftWithLineRange} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]}
+ ${'with `draft.position`'} | ${draftWithLineRange} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]}
+ ${'without `draft.position`'} | ${{}} | ${'mouseenter'} | ${[]}
+ ${'without `draft.position`'} | ${{}} | ${'mouseleave'} | ${[]}
+ `('$desc', ({ props, event, expectedCalls }) => {
beforeEach(() => {
- createComponent({ draft: { ...draft, ...props } }, features);
+ createComponent({ draft: { ...draft, ...props } });
jest.spyOn(store, 'dispatch');
});
diff --git a/spec/frontend/batch_comments/components/preview_item_spec.js b/spec/frontend/batch_comments/components/preview_item_spec.js
index 173b2710a30..08167a94068 100644
--- a/spec/frontend/batch_comments/components/preview_item_spec.js
+++ b/spec/frontend/batch_comments/components/preview_item_spec.js
@@ -56,17 +56,30 @@ describe('Batch comments draft preview item component', () => {
createComponent(false, {
file_path: 'index.js',
file_hash: 'abc',
- position: { new_line: 1 },
+ position: {
+ line_range: {
+ start: {
+ new_line: 1,
+ type: 'new',
+ },
+ },
+ },
});
- expect(vm.$el.querySelector('.bold').textContent).toContain(':1');
+ expect(vm.$el.querySelector('.bold').textContent).toContain(':+1');
});
it('renders old line position', () => {
createComponent(false, {
file_path: 'index.js',
file_hash: 'abc',
- position: { old_line: 2 },
+ position: {
+ line_range: {
+ start: {
+ old_line: 2,
+ },
+ },
+ },
});
expect(vm.$el.querySelector('.bold').textContent).toContain(':2');
diff --git a/spec/frontend/diffs/components/diff_line_note_form_spec.js b/spec/frontend/diffs/components/diff_line_note_form_spec.js
index faa68159c58..9ff80c635bb 100644
--- a/spec/frontend/diffs/components/diff_line_note_form_spec.js
+++ b/spec/frontend/diffs/components/diff_line_note_form_spec.js
@@ -17,6 +17,7 @@ describe('DiffLineNoteForm', () => {
const store = createStore();
store.state.notes.userData.id = 1;
store.state.notes.noteableData = noteableDataMock;
+ store.state.diffs.diffFiles = [diffFile];
store.replaceState({ ...store.state, ...args.state });
diff --git a/spec/frontend/notes/components/discussion_notes_spec.js b/spec/frontend/notes/components/discussion_notes_spec.js
index e803dcb7b4a..d37969fede4 100644
--- a/spec/frontend/notes/components/discussion_notes_spec.js
+++ b/spec/frontend/notes/components/discussion_notes_spec.js
@@ -23,7 +23,7 @@ describe('DiscussionNotes', () => {
let wrapper;
const getList = () => getByRole(wrapper.element, 'list');
- const createComponent = (props, features = {}) => {
+ const createComponent = (props) => {
wrapper = shallowMount(DiscussionNotes, {
store,
propsData: {
@@ -38,9 +38,6 @@ describe('DiscussionNotes', () => {
slots: {
'avatar-badge': '<span class="avatar-badge-slot-content" />',
},
- provide: {
- glFeatures: { multilineComments: true, ...features },
- },
});
};
@@ -177,16 +174,14 @@ describe('DiscussionNotes', () => {
});
describe.each`
- desc | props | features | event | expectedCalls
- ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{}} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]}
- ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{}} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]}
- ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{ multilineComments: false }} | ${'mouseenter'} | ${[]}
- ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${{ multilineComments: false }} | ${'mouseleave'} | ${[]}
- ${'without `discussion.position`'} | ${{}} | ${{}} | ${'mouseenter'} | ${[]}
- ${'without `discussion.position`'} | ${{}} | ${{}} | ${'mouseleave'} | ${[]}
- `('$desc and features $features', ({ props, event, features, expectedCalls }) => {
+ desc | props | event | expectedCalls
+ ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${'mouseenter'} | ${[['setSelectedCommentPositionHover', LINE_RANGE]]}
+ ${'with `discussion.position`'} | ${{ discussion: DISCUSSION_WITH_LINE_RANGE }} | ${'mouseleave'} | ${[['setSelectedCommentPositionHover']]}
+ ${'without `discussion.position`'} | ${{}} | ${'mouseenter'} | ${[]}
+ ${'without `discussion.position`'} | ${{}} | ${'mouseleave'} | ${[]}
+ `('$desc', ({ props, event, expectedCalls }) => {
beforeEach(() => {
- createComponent(props, features);
+ createComponent(props);
jest.spyOn(store, 'dispatch');
});
diff --git a/spec/frontend/notes/components/noteable_note_spec.js b/spec/frontend/notes/components/noteable_note_spec.js
index 6f06665f412..1f38364fc01 100644
--- a/spec/frontend/notes/components/noteable_note_spec.js
+++ b/spec/frontend/notes/components/noteable_note_spec.js
@@ -8,15 +8,6 @@ import NoteActions from '~/notes/components/note_actions.vue';
import NoteBody from '~/notes/components/note_body.vue';
import { noteableDataMock, notesDataMock, note } from '../mock_data';
-jest.mock('~/vue_shared/mixins/gl_feature_flags_mixin', () => () => ({
- inject: {
- glFeatures: {
- from: 'glFeatures',
- default: () => ({ multilineComments: true }),
- },
- },
-}));
-
describe('issue_note', () => {
let store;
let wrapper;
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
index 648d899f1a8..430cea17170 100644
--- a/spec/requests/api/generic_packages_spec.rb
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -6,6 +6,8 @@ RSpec.describe API::GenericPackages do
include HttpBasicAuthHelpers
using RSpec::Parameterized::TableSyntax
+ include_context 'workhorse headers'
+
let_it_be(:personal_access_token) { create(:personal_access_token) }
let_it_be(:project, reload: true) { create(:project) }
let_it_be(:deploy_token_rw) { create(:deploy_token, read_package_registry: true, write_package_registry: true) }
@@ -14,8 +16,6 @@ RSpec.describe API::GenericPackages do
let_it_be(:project_deploy_token_ro) { create(:project_deploy_token, deploy_token: deploy_token_ro, project: project) }
let_it_be(:deploy_token_wo) { create(:deploy_token, read_package_registry: false, write_package_registry: true) }
let_it_be(:project_deploy_token_wo) { create(:project_deploy_token, deploy_token: deploy_token_wo, project: project) }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
let(:user) { personal_access_token.user }
let(:ci_build) { create(:ci_build, :running, user: user) }
@@ -129,7 +129,7 @@ RSpec.describe API::GenericPackages do
end
it "responds with #{params[:expected_status]}" do
- authorize_upload_file(workhorse_header.merge(auth_header))
+ authorize_upload_file(workhorse_headers.merge(auth_header))
expect(response).to have_gitlab_http_status(expected_status)
end
@@ -144,7 +144,7 @@ RSpec.describe API::GenericPackages do
with_them do
it "responds with #{params[:expected_status]}" do
- authorize_upload_file(workhorse_header.merge(deploy_token_auth_header))
+ authorize_upload_file(workhorse_headers.merge(deploy_token_auth_header))
expect(response).to have_gitlab_http_status(expected_status)
end
@@ -162,7 +162,7 @@ RSpec.describe API::GenericPackages do
end
with_them do
- subject { authorize_upload_file(workhorse_header.merge(personal_access_token_header), param_name => param_value) }
+ subject { authorize_upload_file(workhorse_headers.merge(personal_access_token_header), param_name => param_value) }
it_behaves_like 'secure endpoint'
end
@@ -173,7 +173,7 @@ RSpec.describe API::GenericPackages do
stub_feature_flags(generic_packages: false)
project.add_developer(user)
- authorize_upload_file(workhorse_header.merge(personal_access_token_header))
+ authorize_upload_file(workhorse_headers.merge(personal_access_token_header))
expect(response).to have_gitlab_http_status(:not_found)
end
@@ -239,7 +239,7 @@ RSpec.describe API::GenericPackages do
end
it "responds with #{params[:expected_status]}" do
- headers = workhorse_header.merge(auth_header)
+ headers = workhorse_headers.merge(auth_header)
upload_file(params, headers)
@@ -254,7 +254,7 @@ RSpec.describe API::GenericPackages do
with_them do
it "responds with #{params[:expected_status]}" do
- headers = workhorse_header.merge(deploy_token_auth_header)
+ headers = workhorse_headers.merge(deploy_token_auth_header)
upload_file(params, headers)
@@ -270,7 +270,7 @@ RSpec.describe API::GenericPackages do
shared_examples 'creates a package and package file' do
it 'creates a package and package file' do
- headers = workhorse_header.merge(auth_header)
+ headers = workhorse_headers.merge(auth_header)
expect { upload_file(params, headers) }
.to change { project.packages.generic.count }.by(1)
@@ -324,26 +324,26 @@ RSpec.describe API::GenericPackages do
end
context 'event tracking' do
- subject { upload_file(params, workhorse_header.merge(personal_access_token_header)) }
+ subject { upload_file(params, workhorse_headers.merge(personal_access_token_header)) }
it_behaves_like 'a gitlab tracking event', described_class.name, 'push_package'
end
it 'rejects request without a file from workhorse' do
- headers = workhorse_header.merge(personal_access_token_header)
+ headers = workhorse_headers.merge(personal_access_token_header)
upload_file({}, headers)
expect(response).to have_gitlab_http_status(:bad_request)
end
it 'rejects request without an auth token' do
- upload_file(params, workhorse_header)
+ upload_file(params, workhorse_headers)
expect(response).to have_gitlab_http_status(:unauthorized)
end
it 'rejects request without workhorse rewritten fields' do
- headers = workhorse_header.merge(personal_access_token_header)
+ headers = workhorse_headers.merge(personal_access_token_header)
upload_file(params, headers, send_rewritten_field: false)
expect(response).to have_gitlab_http_status(:bad_request)
@@ -354,7 +354,7 @@ RSpec.describe API::GenericPackages do
allow(uploaded_file).to receive(:size).and_return(project.actual_limits.generic_packages_max_file_size + 1)
end
- headers = workhorse_header.merge(personal_access_token_header)
+ headers = workhorse_headers.merge(personal_access_token_header)
upload_file(params, headers)
expect(response).to have_gitlab_http_status(:bad_request)
@@ -378,7 +378,7 @@ RSpec.describe API::GenericPackages do
end
with_them do
- subject { upload_file(params, workhorse_header.merge(personal_access_token_header), param_name => param_value) }
+ subject { upload_file(params, workhorse_headers.merge(personal_access_token_header), param_name => param_value) }
it_behaves_like 'secure endpoint'
end
diff --git a/spec/requests/api/group_import_spec.rb b/spec/requests/api/group_import_spec.rb
index d8e945baf6a..bb7436502ed 100644
--- a/spec/requests/api/group_import_spec.rb
+++ b/spec/requests/api/group_import_spec.rb
@@ -5,13 +5,13 @@ require 'spec_helper'
RSpec.describe API::GroupImport do
include WorkhorseHelpers
+ include_context 'workhorse headers'
+
let_it_be(:user) { create(:user) }
let_it_be(:group) { create(:group) }
let(:path) { '/groups/import' }
let(:file) { File.join('spec', 'fixtures', 'group_export.tar.gz') }
let(:export_path) { "#{Dir.tmpdir}/group_export_spec" }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
before do
allow_next_instance_of(Gitlab::ImportExport) do |import_export|
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index 5c85909a851..7f0e4f18e3b 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -4,6 +4,8 @@ require 'spec_helper'
RSpec.describe API::MavenPackages do
include WorkhorseHelpers
+ include_context 'workhorse headers'
+
let_it_be_with_refind(:package_settings) { create(:namespace_package_setting, :group) }
let_it_be(:group) { package_settings.namespace }
let_it_be(:user) { create(:user) }
@@ -20,8 +22,7 @@ RSpec.describe API::MavenPackages do
let_it_be(:group_deploy_token) { create(:group_deploy_token, deploy_token: deploy_token_for_group, group: group) }
let(:package_name) { 'com/example/my-app' }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ let(:headers) { workhorse_headers }
let(:headers_with_token) { headers.merge('Private-Token' => personal_access_token.token) }
let(:group_deploy_token_headers) { { Gitlab::Auth::AuthFinders::DEPLOY_TOKEN_HEADER => deploy_token_for_group.token } }
@@ -548,8 +549,8 @@ RSpec.describe API::MavenPackages do
end
describe 'PUT /api/v4/projects/:id/packages/maven/*path/:file_name' do
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ include_context 'workhorse headers'
+
let(:send_rewritten_field) { true }
let(:file_upload) { fixture_file_upload('spec/fixtures/packages/maven/my-app-1.0-20180724.124855-1.jar') }
@@ -602,7 +603,7 @@ RSpec.describe API::MavenPackages do
end
context 'without workhorse header' do
- let(:workhorse_header) { {} }
+ let(:workhorse_headers) { {} }
subject { upload_file_with_token(params: params) }
diff --git a/spec/requests/api/nuget_project_packages_spec.rb b/spec/requests/api/nuget_project_packages_spec.rb
index 813ebc35ede..0277aa73220 100644
--- a/spec/requests/api/nuget_project_packages_spec.rb
+++ b/spec/requests/api/nuget_project_packages_spec.rb
@@ -144,8 +144,8 @@ RSpec.describe API::NugetProjectPackages do
end
describe 'PUT /api/v4/projects/:id/packages/nuget/authorize' do
- let_it_be(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let_it_be(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ include_context 'workhorse headers'
+
let(:url) { "/projects/#{target.id}/packages/nuget/authorize" }
let(:headers) { {} }
@@ -176,7 +176,7 @@ RSpec.describe API::NugetProjectPackages do
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ let(:headers) { user_headers.merge(workhorse_headers) }
before do
update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
@@ -194,8 +194,8 @@ RSpec.describe API::NugetProjectPackages do
end
describe 'PUT /api/v4/projects/:id/packages/nuget' do
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ include_context 'workhorse headers'
+
let_it_be(:file_name) { 'package.nupkg' }
let(:url) { "/projects/#{target.id}/packages/nuget" }
let(:headers) { {} }
@@ -239,7 +239,7 @@ RSpec.describe API::NugetProjectPackages do
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ let(:headers) { user_headers.merge(workhorse_headers) }
before do
update_visibility_to(Gitlab::VisibilityLevel.const_get(visibility_level, false))
@@ -256,7 +256,7 @@ RSpec.describe API::NugetProjectPackages do
it_behaves_like 'rejects nuget access with invalid target id'
context 'file size above maximum limit' do
- let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_header) }
+ let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_headers) }
before do
allow_next_instance_of(UploadedFile) do |uploaded_file|
diff --git a/spec/requests/api/project_import_spec.rb b/spec/requests/api/project_import_spec.rb
index 8e99d37c84f..a049d7d7515 100644
--- a/spec/requests/api/project_import_spec.rb
+++ b/spec/requests/api/project_import_spec.rb
@@ -5,13 +5,12 @@ require 'spec_helper'
RSpec.describe API::ProjectImport do
include WorkhorseHelpers
+ include_context 'workhorse headers'
+
let(:user) { create(:user) }
let(:file) { File.join('spec', 'features', 'projects', 'import_export', 'test_project_export.tar.gz') }
let(:namespace) { create(:group) }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
-
before do
namespace.add_owner(user)
end
diff --git a/spec/requests/api/pypi_packages_spec.rb b/spec/requests/api/pypi_packages_spec.rb
index 94ecd177890..ae5b132f409 100644
--- a/spec/requests/api/pypi_packages_spec.rb
+++ b/spec/requests/api/pypi_packages_spec.rb
@@ -74,8 +74,8 @@ RSpec.describe API::PypiPackages do
end
describe 'POST /api/v4/projects/:id/packages/pypi/authorize' do
- let_it_be(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let_it_be(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ include_context 'workhorse headers'
+
let(:url) { "/projects/#{project.id}/packages/pypi/authorize" }
let(:headers) { {} }
@@ -106,7 +106,7 @@ RSpec.describe API::PypiPackages do
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ let(:headers) { user_headers.merge(workhorse_headers) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
@@ -124,8 +124,8 @@ RSpec.describe API::PypiPackages do
end
describe 'POST /api/v4/projects/:id/packages/pypi' do
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ include_context 'workhorse headers'
+
let_it_be(:file_name) { 'package.whl' }
let(:url) { "/projects/#{project.id}/packages/pypi" }
let(:headers) { {} }
@@ -170,7 +170,7 @@ RSpec.describe API::PypiPackages do
with_them do
let(:token) { user_token ? personal_access_token.token : 'wrong' }
let(:user_headers) { user_role == :anonymous ? {} : basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ let(:headers) { user_headers.merge(workhorse_headers) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel.const_get(project_visibility_level, false))
@@ -184,7 +184,7 @@ RSpec.describe API::PypiPackages do
let(:requires_python) { 'x' * 256 }
let(:token) { personal_access_token.token }
let(:user_headers) { basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ let(:headers) { user_headers.merge(workhorse_headers) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
@@ -196,7 +196,7 @@ RSpec.describe API::PypiPackages do
context 'with an invalid package' do
let(:token) { personal_access_token.token }
let(:user_headers) { basic_auth_header(user.username, token) }
- let(:headers) { user_headers.merge(workhorse_header) }
+ let(:headers) { user_headers.merge(workhorse_headers) }
before do
params[:name] = '.$/@!^*'
@@ -213,7 +213,7 @@ RSpec.describe API::PypiPackages do
it_behaves_like 'rejects PyPI access with unknown project id'
context 'file size above maximum limit' do
- let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_header) }
+ let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_headers) }
before do
allow_next_instance_of(UploadedFile) do |uploaded_file|
diff --git a/spec/requests/import/gitlab_groups_controller_spec.rb b/spec/requests/import/gitlab_groups_controller_spec.rb
index 51f1363cf1c..c65caf2ebf0 100644
--- a/spec/requests/import/gitlab_groups_controller_spec.rb
+++ b/spec/requests/import/gitlab_groups_controller_spec.rb
@@ -5,12 +5,10 @@ require 'spec_helper'
RSpec.describe Import::GitlabGroupsController do
include WorkhorseHelpers
+ include_context 'workhorse headers'
+
let_it_be(:user) { create(:user) }
let(:import_path) { "#{Dir.tmpdir}/gitlab_groups_controller_spec" }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_headers) do
- { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token }
- end
before do
allow_next_instance_of(Gitlab::ImportExport) do |import_export|
diff --git a/spec/requests/import/gitlab_projects_controller_spec.rb b/spec/requests/import/gitlab_projects_controller_spec.rb
index d7d4de21a33..58843a7fec4 100644
--- a/spec/requests/import/gitlab_projects_controller_spec.rb
+++ b/spec/requests/import/gitlab_projects_controller_spec.rb
@@ -5,8 +5,7 @@ require 'spec_helper'
RSpec.describe Import::GitlabProjectsController do
include WorkhorseHelpers
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+ include_context 'workhorse headers'
let_it_be(:namespace) { create(:namespace) }
let_it_be(:user) { namespace.owner }
diff --git a/spec/services/ci/create_job_artifacts_service_spec.rb b/spec/services/ci/create_job_artifacts_service_spec.rb
index 29e51a23dea..1efd1d390a2 100644
--- a/spec/services/ci/create_job_artifacts_service_spec.rb
+++ b/spec/services/ci/create_job_artifacts_service_spec.rb
@@ -27,6 +27,14 @@ RSpec.describe Ci::CreateJobArtifactsService do
UploadedFile.new(upload.path, **params)
end
+ def unique_metrics_report_uploaders
+ Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(
+ event_names: described_class::METRICS_REPORT_UPLOAD_EVENT_NAME,
+ start_date: 2.weeks.ago,
+ end_date: 2.weeks.from_now
+ )
+ end
+
describe '#execute' do
subject { service.execute(artifacts_file, params, metadata_file: metadata_file) }
@@ -42,6 +50,12 @@ RSpec.describe Ci::CreateJobArtifactsService do
expect(new_artifact.file_sha256).to eq(artifacts_sha256)
end
+ it 'does not track the job user_id' do
+ subject
+
+ expect(unique_metrics_report_uploaders).to eq(0)
+ end
+
context 'when metadata file is also uploaded' do
let(:metadata_file) do
file_to_upload('spec/fixtures/ci_build_artifacts_metadata.gz', sha256: artifacts_sha256)
@@ -174,6 +188,20 @@ RSpec.describe Ci::CreateJobArtifactsService do
end
end
+ context 'when artifact_type is metrics' do
+ before do
+ allow(job).to receive(:user_id).and_return(123)
+ end
+
+ let(:params) { { 'artifact_type' => 'metrics', 'artifact_format' => 'gzip' }.with_indifferent_access }
+
+ it 'tracks the job user_id' do
+ subject
+
+ expect(unique_metrics_report_uploaders).to eq(1)
+ end
+ end
+
context 'when artifact type is cluster_applications' do
let(:artifacts_file) do
file_to_upload('spec/fixtures/helm/helm_list_v2_prometheus_missing.json.gz', sha256: artifacts_sha256)
diff --git a/spec/services/ci/create_pipeline_service_spec.rb b/spec/services/ci/create_pipeline_service_spec.rb
index f63ab1bbccd..1005985b3e4 100644
--- a/spec/services/ci/create_pipeline_service_spec.rb
+++ b/spec/services/ci/create_pipeline_service_spec.rb
@@ -537,7 +537,7 @@ RSpec.describe Ci::CreatePipelineService do
it 'pull it from Auto-DevOps' do
pipeline = execute_service
expect(pipeline).to be_auto_devops_source
- expect(pipeline.builds.map(&:name)).to match_array(%w[build code_quality eslint-sast secret_detection_default_branch test])
+ expect(pipeline.builds.map(&:name)).to match_array(%w[brakeman-sast build code_quality eslint-sast secret_detection_default_branch test])
end
end
diff --git a/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb b/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
index 7ad73ea18f4..f3bbb325475 100644
--- a/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
+++ b/spec/support/shared_contexts/requests/api/conan_packages_shared_context.rb
@@ -67,9 +67,9 @@ RSpec.shared_context 'conan file upload endpoints' do
include WorkhorseHelpers
include HttpBasicAuthHelpers
+ include_context 'workhorse headers'
+
let(:jwt) { build_jwt(personal_access_token) }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_header) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
- let(:headers_with_token) { build_token_auth_header(jwt.encoded).merge(workhorse_header) }
+ let(:headers_with_token) { build_token_auth_header(jwt.encoded).merge(workhorse_headers) }
let(:recipe_path) { "foo/bar/#{project.full_path.tr('/', '+')}/baz"}
end
diff --git a/spec/support/shared_contexts/requests/api/workhorse_shared_context.rb b/spec/support/shared_contexts/requests/api/workhorse_shared_context.rb
new file mode 100644
index 00000000000..36be64339a2
--- /dev/null
+++ b/spec/support/shared_contexts/requests/api/workhorse_shared_context.rb
@@ -0,0 +1,6 @@
+# frozen_string_literal: true
+
+RSpec.shared_context 'workhorse headers' do
+ let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
+ let(:workhorse_headers) { { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token } }
+end
diff --git a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
index 8616a3bd0b4..acaa0d8c2bc 100644
--- a/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/debian_packages_shared_examples.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
RSpec.shared_context 'Debian repository shared context' do |object_type|
+ include_context 'workhorse headers'
+
before do
stub_feature_flags(debian_packages: true)
end
@@ -37,16 +39,15 @@ RSpec.shared_context 'Debian repository shared context' do |object_type|
let(:params) { workhorse_params }
let(:auth_headers) { {} }
- let(:workhorse_token) { JWT.encode({ 'iss' => 'gitlab-workhorse' }, Gitlab::Workhorse.secret, 'HS256') }
- let(:workhorse_headers) do
+ let(:wh_headers) do
if method == :put
- { 'GitLab-Workhorse' => '1.0', Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER => workhorse_token }
+ workhorse_headers
else
{}
end
end
- let(:headers) { auth_headers.merge(workhorse_headers) }
+ let(:headers) { auth_headers.merge(wh_headers) }
let(:send_rewritten_field) { true }
diff --git a/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
index 8b60857cdaf..617fdecbb5b 100644
--- a/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/nuget_packages_shared_examples.rb
@@ -123,7 +123,7 @@ RSpec.shared_examples 'process nuget workhorse authorization' do |user_type, sta
context 'with a request that bypassed gitlab-workhorse' do
let(:headers) do
basic_auth_header(user.username, personal_access_token.token)
- .merge(workhorse_header)
+ .merge(workhorse_headers)
.tap { |h| h.delete(Gitlab::Workhorse::INTERNAL_API_REQUEST_HEADER) }
end
diff --git a/spec/support/shared_examples/requests/api/packages_shared_examples.rb b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
index 3833604e304..15976eed021 100644
--- a/spec/support/shared_examples/requests/api/packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
@@ -24,7 +24,7 @@ end
RSpec.shared_examples 'deploy token for package uploads' do
context 'with deploy token headers' do
- let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_header) }
+ let(:headers) { basic_auth_header(deploy_token.username, deploy_token.token).merge(workhorse_headers) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
@@ -35,7 +35,7 @@ RSpec.shared_examples 'deploy token for package uploads' do
end
context 'invalid token' do
- let(:headers) { basic_auth_header(deploy_token.username, 'bar').merge(workhorse_header) }
+ let(:headers) { basic_auth_header(deploy_token.username, 'bar').merge(workhorse_headers) }
it_behaves_like 'returning response status', :unauthorized
end
@@ -102,7 +102,7 @@ end
RSpec.shared_examples 'job token for package uploads' do
context 'with job token headers' do
- let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, job.token).merge(workhorse_header) }
+ let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, job.token).merge(workhorse_headers) }
before do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
@@ -114,13 +114,13 @@ RSpec.shared_examples 'job token for package uploads' do
end
context 'invalid token' do
- let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, 'bar').merge(workhorse_header) }
+ let(:headers) { basic_auth_header(::Gitlab::Auth::CI_JOB_USER, 'bar').merge(workhorse_headers) }
it_behaves_like 'returning response status', :unauthorized
end
context 'invalid user' do
- let(:headers) { basic_auth_header('foo', job.token).merge(workhorse_header) }
+ let(:headers) { basic_auth_header('foo', job.token).merge(workhorse_headers) }
it_behaves_like 'returning response status', :unauthorized
end