Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
02c3b2af44
commit
ced6c9ae9a
54 changed files with 480 additions and 229 deletions
|
@ -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();
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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}')">
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
},
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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!'));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -69,9 +69,6 @@ table {
|
|||
}
|
||||
}
|
||||
|
||||
td {
|
||||
border-color: $white-normal;
|
||||
}
|
||||
}
|
||||
|
||||
.thead-white {
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
%th
|
||||
%tbody
|
||||
%tr
|
||||
%td.flash-container{ colspan: 4 }
|
||||
= yield
|
||||
|
||||
= paginate @protected_tags, theme: 'gitlab'
|
||||
|
|
5
changelogs/unreleased/ar-fix-border-color.yml
Normal file
5
changelogs/unreleased/ar-fix-border-color.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Fix protected branches/tags border
|
||||
merge_request: 52816
|
||||
author:
|
||||
type: changed
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: 'Improve Vulnerability Tracking: Add fingerprints table'
|
||||
merge_request: 52720
|
||||
author:
|
||||
type: added
|
5
changelogs/unreleased/rf-update-brakeman-rules.yml
Normal file
5
changelogs/unreleased/rf-update-brakeman-rules.yml
Normal file
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
title: Update Ruby detection rules for SAST
|
||||
merge_request: 53414
|
||||
author:
|
||||
type: changed
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
||||
|
|
40
db/migrate/20201108134919_add_finding_fingerprint_table.rb
Normal file
40
db/migrate/20201108134919_add_finding_fingerprint_table.rb
Normal file
|
@ -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
|
|
@ -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
|
||||
|
|
1
db/schema_migrations/20201108134919
Normal file
1
db/schema_migrations/20201108134919
Normal file
|
@ -0,0 +1 @@
|
|||
6643e5b4c5597d92c94115f392bfbd5cfce9884eb0bcb18f9629855f3711eed0
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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,18 +1122,32 @@ 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',
|
||||
},
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
- 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.
|
||||
|
||||
```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>
|
||||
|
|
|
@ -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.
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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?")
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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**
|
||||
|
||||
|
|
|
@ -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
|
||||
```
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ""
|
||||
|
||||
|
|
|
@ -38,6 +38,7 @@ Migration/UpdateLargeTable:
|
|||
- :users
|
||||
- :user_preferences
|
||||
- :user_details
|
||||
- :vulnerability_occurrences
|
||||
- :web_hook_logs
|
||||
DeniedMethods:
|
||||
- :change_column_type_concurrently
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
|
||||
|
|
|
@ -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');
|
||||
|
|
|
@ -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 });
|
||||
|
||||
|
|
|
@ -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');
|
||||
});
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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) }
|
||||
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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|
|
||||
|
|
|
@ -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 }
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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 }
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue