Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-05-19 15:09:09 +00:00
parent 0eea37aefa
commit d0bb0e04f4
29 changed files with 404 additions and 93 deletions

View File

@ -44,7 +44,7 @@ docs-lint markdown:
- .default-retry
- .docs:rules:docs-lint
# When updating the image version here, update it in /scripts/lint-doc.sh too.
image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.15-vale-2.15.5-markdownlint-0.31.1
image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-markdown:alpine-3.15-vale-2.16.1-markdownlint-0.31.1
stage: lint
needs: []
script:
@ -53,7 +53,7 @@ docs-lint markdown:
docs-lint links:
extends:
- .docs:rules:docs-lint
image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-html:alpine-3.15-ruby-2.7.5-cee62c13
image: registry.gitlab.com/gitlab-org/gitlab-docs/lint-html:alpine-3.15-ruby-2.7.5-e6a8a48a
stage: lint
needs: []
script:

View File

@ -12,6 +12,7 @@ import { DynamicScroller, DynamicScrollerItem } from 'vendor/vue-virtual-scrolle
import api from '~/api';
import { sprintf, s__, __ } from '~/locale';
import Poll from '~/lib/utils/poll';
import { normalizeHeaders } from '~/lib/utils/common_utils';
import { EXTENSION_ICON_CLASS, EXTENSION_ICONS } from '../../constants';
import StatusIcon from './status_icon.vue';
import Actions from './actions.vue';
@ -147,6 +148,35 @@ export default {
this.triggerRedisTracking();
}
},
initExtensionMultiPolling() {
const allData = [];
const requests = this.fetchMultiData();
requests.forEach((request) => {
const poll = new Poll({
resource: {
fetchData: () => request(this.$props),
},
method: 'fetchData',
successCallback: (response) => {
const headers = normalizeHeaders(response.headers);
if (!headers['POLL-INTERVAL']) {
allData.push(response.data);
}
if (allData.length === requests.length) {
this.setCollapsedData(allData);
}
},
errorCallback: (e) => {
this.setCollapsedError(e);
},
});
poll.makeRequest();
});
},
initExtensionPolling() {
const poll = new Poll({
resource: {
@ -172,7 +202,11 @@ export default {
this.loadingState = LOADING_STATES.collapsedLoading;
if (this.$options.enablePolling) {
this.initExtensionPolling();
if (this.fetchMultiData) {
this.initExtensionMultiPolling();
} else {
this.initExtensionPolling();
}
} else {
this.fetchCollapsedData(this.$props)
.then((data) => {

View File

@ -98,13 +98,15 @@ export default {
<span v-else-if="isConfidential" ref="confidential">
{{ confidentialContextText }}
{{ __('People without permission will never get a notification.') }}
<gl-link :href="confidentialNoteableDocsPath" target="_blank">{{ __('Learn more') }}</gl-link>
<gl-link :href="confidentialNoteableDocsPath" target="_blank">{{
__('Learn more.')
}}</gl-link>
</span>
<span v-else-if="isLocked" ref="locked">
{{ lockedContextText }}
{{ __('Only project members can comment.') }}
<gl-link :href="lockedNoteableDocsPath" target="_blank">{{ __('Learn more') }}</gl-link>
<gl-link :href="lockedNoteableDocsPath" target="_blank">{{ __('Learn more.') }}</gl-link>
</span>
</div>
</template>

View File

@ -106,15 +106,15 @@
}
@mixin btn-blue {
@include btn-color($blue-500, $blue-600, $blue-600, $blue-700, $blue-700, $blue-800, $white);
@include btn-color($blue-500, $blue-600, $blue-600, $blue-700, $blue-700, $blue-800, $white-contrast);
}
@mixin btn-orange {
@include btn-color($orange-500, $orange-600, $orange-500, $orange-600, $orange-600, $orange-800, $white);
@include btn-color($orange-500, $orange-600, $orange-500, $orange-600, $orange-600, $orange-800, $white-contrast);
}
@mixin btn-red {
@include btn-color($red-500, $red-600, $red-600, $red-700, $red-700, $red-800, $white);
@include btn-color($red-500, $red-600, $red-600, $red-700, $red-700, $red-800, $white-contrast);
}
@mixin btn-white {
@ -122,7 +122,7 @@
}
@mixin btn-purple {
@include btn-color($purple-700, $purple-800, $purple-800, $purple-900, $purple-900, $purple-950, $white);
@include btn-color($purple-700, $purple-800, $purple-800, $purple-900, $purple-900, $purple-950, $white-contrast);
}
@mixin btn-with-margin {
@ -417,16 +417,6 @@ fieldset[disabled] .btn,
cursor: default;
}
// This class helps convert `.gl-button` children so that they consistently
// match the style of `.btn` elements which might be around them. Ideally we
// wouldn't need this class.
//
// Remove by upgrading all buttons in a container to use the new `.gl-button` style.
.gl-button-deprecated-adapter .gl-button {
box-shadow: none;
border-width: 1px;
}
copy-code {
@include gl-absolute;
@include gl-transition-medium;

View File

@ -78,12 +78,15 @@ module Boards
end
def list
return unless params.key?(:id)
return unless params.key?(:id) || params.key?(:list)
strong_memoize(:list) do
id = params[:id]
list = params[:list]
if board.lists.loaded?
if list.present?
list
elsif board.lists.loaded?
board.lists.find { |l| l.id == id }
else
board.lists.find(id)

View File

@ -10,7 +10,7 @@
stage: create
reporter: phikai
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
issue_url: # (optional) This is a link to the deprecation issue in GitLab
documentation_url: # (optional) This is a link to the current documentation page
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345451 # (optional) This is a link to the deprecation issue in GitLab
documentation_url: https://docs.gitlab.com/ee/api/graphql/removed_items.html#graphql-types # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -0,0 +1,16 @@
- name: "`defaultMergeCommitMessageWithDescription` GraphQL API field"
announcement_milestone: "14.5" # The milestone when this feature was first announced as deprecated.
announcement_date: "2021-11-22" # The date of the milestone release when this feature was first announced as deprecated. This should almost always be the 22nd of a month (YYYY-MM-22), unless you did an out of band blog post.
removal_milestone: "15.0" # The milestone when this feature is planned to be removed
removal_date: "2022-05-22" # the date of the milestone release when this feature is planned to be removed
breaking_change: true # (required) Change to true if this removal is a breaking change.
reporter: phikai # (required) GitLab username of the person reporting the removal
stage: create # (required) String value of the stage that the feature was created in. e.g., Growth
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345451 # (required) Link to the deprecation issue in GitLab
body: | # (required) Do not modify this line, instead modify the lines below.
The GraphQL API field `defaultMergeCommitMessageWithDescription` has been removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template.
# The following items are not published on the docs page, but may be used in the future.
tiers: # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
documentation_url: https://docs.gitlab.com/ee/api/graphql/removed_items.html#graphql-types # (optional) This is a link to the current documentation page
image_url: # (optional) This is a link to a thumbnail image depicting the feature
video_url: # (optional) Use the youtube thumbnail URL with the structure of https://img.youtube.com/vi/UNIQUEID/hqdefault.jpg

View File

@ -0,0 +1,32 @@
# frozen_string_literal: true
class SchedulePurgingStaleSecurityScans < Gitlab::Database::Migration[2.0]
MIGRATION = 'PurgeStaleSecurityScans'
BATCH_SIZE = 10_000
DELAY_INTERVAL = 2.minutes
restrict_gitlab_migration gitlab_schema: :gitlab_main
disable_ddl_transaction!
def up
return unless should_run?
queue_background_migration_jobs_by_range_at_intervals(
Gitlab::BackgroundMigration::PurgeStaleSecurityScans::SecurityScan.to_purge,
MIGRATION,
DELAY_INTERVAL,
batch_size: BATCH_SIZE,
track_jobs: true
)
end
def down
# no-op
end
private
def should_run?
Gitlab.dev_or_test_env? || Gitlab.com?
end
end

View File

@ -0,0 +1 @@
dabbd8b95ec49b4267d53768013b4e62ae1219a4575dc8b0fccb0e117e725885

View File

@ -3,52 +3,11 @@ stage: Manage
group: Optimize
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments
type: reference, api
remove_date: '2022-05-18'
redirect_to: 'dora/metrics.md'
---
# DORA4 Analytics Project API **(ULTIMATE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/279039) in GitLab 13.7.
# DORA4 Analytics Project API (removed) **(ULTIMATE)**
WARNING:
These endpoints have been removed in GitLab 14.0. Use the [DORA metrics API](dora/metrics.md) instead.
All methods require reporter authorization.
## List project deployment frequencies
Get a list of all project deployment frequencies, sorted by date:
```plaintext
GET /projects/:id/analytics/deployment_frequency?environment=:environment&from=:from&to=:to&interval=:interval
```
| Attribute | Type | Required | Description |
|--------------|--------|----------|-----------------------|
| `id` | string | yes | The ID of the project |
| `environment`| string | yes | The name of the environment to filter by |
| `from` | string | yes | Datetime range to start from, inclusive, ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`) |
| `to` | string | no | Datetime range to end at, exclusive, ISO 8601 format (`YYYY-MM-DDTHH:MM:SSZ`) |
| `interval` | string | no | The bucketing interval (`all`, `monthly`, `daily`) |
Example request:
```shell
curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/analytics/deployment_frequency?environment=:environment&from=:from&to=:to&interval=:interval"
```
Example response:
```json
[
{
"from": "2017-01-01",
"to": "2017-01-02",
"value": 106
},
{
"from": "2017-01-02",
"to": "2017-01-03",
"value": 55
}
]
```
This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/323713) in 13.11 and removed in GitLab 14.0. Use the [DORA metrics API](dora/metrics.md) instead.

View File

@ -145,6 +145,17 @@ Returns [`String!`](#string).
| ---- | ---- | ----------- |
| <a id="queryechotext"></a>`text` | [`String!`](#string) | Text to echo back. |
### `Query.epicBoardList`
Returns [`EpicList`](#epiclist).
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="queryepicboardlistepicfilters"></a>`epicFilters` | [`EpicFilters`](#epicfilters) | Filters applied when getting epic metadata in the epic board list. |
| <a id="queryepicboardlistid"></a>`id` | [`BoardsEpicListID!`](#boardsepiclistid) | Global ID of the list. |
### `Query.geoNode`
Find a Geo node.

View File

@ -422,6 +422,15 @@ Response:
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22988) in GitLab 11.6.
Deleting a pipeline expires all pipeline caches, and deletes all immediately
related objects, such as builds, logs, artifacts, and triggers.
**This action cannot be undone.**
Deleting a pipeline does not automatically delete its
[child pipelines](../ci/pipelines/parent_child_pipelines.md).
See the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/39503)
for details.
```plaintext
DELETE /projects/:id/pipelines/:pipeline_id
```

View File

@ -50,10 +50,10 @@ Example response:
## Export Service Ping SQL queries
This action is available only for the GitLab instance [Administrator](../user/permissions.md) users.
This action is behind the `usage_data_queries_api` feature flag and is available only for the GitLab instance [Administrator](../user/permissions.md) users.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57016) in GitLab 13.11.
> - [Deployed behind a feature flag](../user/feature_flags.md), disabled by default.
> - [Deployed behind a feature flag](../user/feature_flags.md) named `usage_data_queries_api`, disabled by default.
Return all of the raw SQL queries used to compute Service Ping.
@ -113,8 +113,10 @@ Example response:
## UsageDataNonSqlMetrics API
This action is behind the `usage_data_non_sql_metrics` feature flag and is available only for the GitLab instance [Administrator](../user/permissions.md) users.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57050) in GitLab 13.11.
> - [Deployed behind a feature flag](../user/feature_flags.md), disabled by default.
> - [Deployed behind a feature flag](../user/feature_flags.md), named `usage_data_non_sql_metrics`, disabled by default.
Return all non-SQL metrics data used in the Service ping.

View File

@ -287,9 +287,15 @@ page, then selecting **Delete**.
![Pipeline Delete](img/pipeline-delete.png)
Deleting a pipeline does not automatically delete its
[child pipelines](parent_child_pipelines.md).
See the [related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/39503)
for details.
WARNING:
Deleting a pipeline expires all pipeline caches, and deletes all related objects,
such as builds, logs, artifacts, and triggers. **This action cannot be undone.**
Deleting a pipeline expires all pipeline caches, and deletes all immediately
related objects, such as builds, logs, artifacts, and triggers.
**This action cannot be undone.**
### Pipeline security on protected branches

View File

@ -46,6 +46,7 @@ export default {
methods: {
fetchCollapsedData(props) {}, // Required: Fetches data required for collapsed state
fetchFullData(props) {}, // Required: Fetches data for the full expanded content
fetchMultiData() {}, // Optional: Works in conjunction with `enablePolling` and allows polling multiple endpoints
},
};
```
@ -232,6 +233,30 @@ export default {
};
```
If the extension needs to poll multiple endpoints at the same time, then `fetchMultiData`
can be used to return an array of functions. A new `poll` object will be created for each
endpoint and they will be polled separately. Once all endpoints are resolved, polling will
be stopped and `setCollapsedData` will be called with an array of `response.data`.
```javascript
export default {
//...
enablePolling: true
methods: {
fetchMultiData() {
return [
() => axios.get(this.reportPath1),
() => axios.get(this.reportPath2),
() => axios.get(this.reportPath3)
},
},
};
```
**Important** The function needs to return a `Promise` that resolves the `response` object.
The implementation relies on the `POLL-INTERVAL` header to keep polling, therefore it is
important not to alter the status code and headers.
### Errors
If `fetchCollapsedData()` or `fetchFullData()` methods throw an error:

View File

@ -118,12 +118,16 @@ NOTE:
There is a [video showing how to see the slow log](https://youtu.be/BBI68QuYRH8) (GitLab internal)
on GitLab.com
<!-- vale gitlab.Substitutions = NO -->
On GitLab.com, entries from the [Redis
slow log](https://redis.io/commands/slowlog) are available in the
`pubsub-redis-inf-gprd*` index with the [`redis.slowlog` tag](https://log.gprd.gitlab.net/app/kibana#/discover?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-1d,to:now))&_a=(columns:!(json.type,json.command,json.exec_time_s),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:AWSQX_Vf93rHTYrsexmk,key:json.tag,negate:!f,params:(query:redis.slowlog),type:phrase),query:(match:(json.tag:(query:redis.slowlog,type:phrase))))),index:AWSQX_Vf93rHTYrsexmk)).
This shows commands that have taken a long time and may be a performance
concern.
<!-- vale gitlab.Substitutions = YES -->
The
[`fluent-plugin-redis-slowlog`](https://gitlab.com/gitlab-org/fluent-plugin-redis-slowlog)
project is responsible for taking the `slowlog` entries from Redis and

View File

@ -11,7 +11,7 @@ This operation should be very uncommon. We do not recommend it for the vast majo
Sidekiq routing rules allow administrators to re-route certain background jobs from their regular queue to an alternative queue. By default, GitLab uses one queue per background job type. GitLab has over 400 background job types, and so correspondingly it has over 400 queues.
Most administrators will not need to change this setting. In some cases with particularly large background job processing workloads, Redis performance may suffer due to the number of queues that GitLab listens to.
Most administrators do not need to change this setting. In some cases with particularly large background job processing workloads, Redis performance may suffer due to the number of queues that GitLab listens to.
If the Sidekiq routing rules are changed, administrators need to take care with the migration to avoid losing jobs entirely. The basic migration steps are:

View File

@ -517,6 +517,8 @@ that may remain stuck permanently in a **pending** state.
sudo printf "x /tmp/gitaly-%s-*\n" hooks git-exec-path >/etc/tmpfiles.d/gitaly-workaround.conf
```
This issue is fixed in GitLab 14.10 and later.
### 14.6.0
- See [LFS objects import and mirror issue in GitLab 14.6.0 to 14.7.2](#lfs-objects-import-and-mirror-issue-in-gitlab-1460-to-1472).

View File

@ -675,6 +675,16 @@ keyword has been [replaced](https://gitlab.com/gitlab-org/gitlab/-/issues/344533
[`artifacts:reports:coverage_report`](https://docs.gitlab.com/ee/ci/yaml/artifacts_reports.html#artifactsreportscoverage_report).
Cobertura is the only supported report file, but this is the first step towards GitLab supporting other report types.
### `defaultMergeCommitMessageWithDescription` GraphQL API field
WARNING:
This feature was changed or removed in 15.0
as a [breaking change](https://docs.gitlab.com/ee/development/contributing/#breaking-changes).
Before updating GitLab, review the details carefully to determine if you need to make any
changes to your code, settings, or workflow.
The GraphQL API field `defaultMergeCommitMessageWithDescription` has been removed in GitLab 15.0. For projects with a commit message template set, it will ignore the template.
### `omniauth-kerberos` gem
WARNING:

View File

@ -47,7 +47,8 @@ The policy editor currently only supports the YAML mode. The Rule mode is tracke
The YAML file with scan execution policies consists of an array of objects matching scan execution
policy schema nested under the `scan_execution_policy` key. You can configure a maximum of 5
policies under the `scan_execution_policy` key.
policies under the `scan_execution_policy` key. Any other policies configured after
the first 5 are not applied.
When you save a new policy, GitLab validates its contents against [this JSON schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/validators/json_schemas/security_orchestration_policy.json).
If you're not familiar with how to read [JSON schemas](https://json-schema.org/),

View File

@ -0,0 +1,32 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
# rubocop:disable Style/Documentation
class PurgeStaleSecurityScans # rubocop:disable Migration/BackgroundMigrationBaseClass
class SecurityScan < ::ApplicationRecord
include EachBatch
STALE_AFTER = 90.days
self.table_name = 'security_scans'
# Otherwise the schema_spec fails
validates :info, json_schema: { filename: 'security_scan_info', draft: 7 }
enum status: { succeeded: 1, purged: 6 }
scope :to_purge, -> { where('id <= ?', last_stale_record_id) }
scope :by_range, -> (range) { where(id: range) }
def self.last_stale_record_id
where('created_at < ?', STALE_AFTER.ago).order(created_at: :desc).first
end
end
def perform(_start_id, _end_id); end
end
end
end
Gitlab::BackgroundMigration::PurgeStaleSecurityScans.prepend_mod

View File

@ -33677,6 +33677,9 @@ msgstr ""
msgid "SecurityOrchestration|After dismissing the alert, the information will never be shown again."
msgstr ""
msgid "SecurityOrchestration|After enabling a group-level policy, this policy automatically applies to all projects in this group."
msgstr ""
msgid "SecurityOrchestration|All policies"
msgstr ""
@ -33743,6 +33746,9 @@ msgstr ""
msgid "SecurityOrchestration|Enforce security for this project. %{linkStart}More information.%{linkEnd}"
msgstr ""
msgid "SecurityOrchestration|Group level policy"
msgstr ""
msgid "SecurityOrchestration|If any scanner finds a newly detected critical vulnerability in an open merge request targeting the master branch, then require two approvals from any member of App security."
msgstr ""

View File

@ -57,7 +57,7 @@
"@gitlab/at.js": "1.5.7",
"@gitlab/favicon-overlay": "2.0.0",
"@gitlab/svgs": "2.14.0",
"@gitlab/ui": "40.2.1",
"@gitlab/ui": "40.6.0",
"@gitlab/visual-review-tools": "1.7.3",
"@rails/actioncable": "6.1.4-7",
"@rails/ujs": "6.1.4-7",

View File

@ -31,6 +31,7 @@ import {
fullDataErrorExtension,
pollingExtension,
pollingErrorExtension,
multiPollingExtension,
} from './test_extensions';
jest.mock('~/api.js');
@ -987,6 +988,8 @@ describe('MrWidgetOptions', () => {
beforeEach(() => {
pollRequest = jest.spyOn(Poll.prototype, 'makeRequest');
pollStop = jest.spyOn(Poll.prototype, 'stop');
registeredExtensions.extensions = [];
});
afterEach(() => {
@ -996,6 +999,63 @@ describe('MrWidgetOptions', () => {
registeredExtensions.extensions = [];
});
describe('success - multi polling', () => {
const findWidgetTestExtension = () => wrapper.find('[data-testid="widget-extension"]');
// Clear all left-over timeouts that may be registered in the poll class
afterEach(() => {
let id = window.setTimeout(() => {}, 0);
while (id > 0) {
window.clearTimeout(id);
id -= 1;
}
});
it('sets data when polling is complete', async () => {
registerExtension(
multiPollingExtension([
() =>
Promise.resolve({
headers: { 'poll-interval': 0 },
status: 200,
data: { reports: 'parsed' },
}),
() =>
Promise.resolve({
status: 200,
data: { reports: 'parsed' },
}),
]),
);
await createComponent();
expect(findWidgetTestExtension().html()).toContain(
'Multi polling test extension reports: parsed, count: 2',
);
});
it('shows loading state until polling is complete', async () => {
registerExtension(
multiPollingExtension([
() =>
Promise.resolve({
headers: { 'poll-interval': 1 },
status: 204,
}),
() =>
Promise.resolve({
status: 200,
data: { reports: 'parsed' },
}),
]),
);
await createComponent();
expect(findWidgetTestExtension().html()).toContain('Loading...');
});
});
describe('success', () => {
beforeEach(() => {
registerExtension(pollingExtension);

View File

@ -106,6 +106,25 @@ export const pollingExtension = {
enablePolling: true,
};
export const multiPollingExtension = (endpointsToBePolled) => ({
name: 'WidgetTestMultiPollingExtension',
props: ['targetProjectFullPath'],
computed: {
summary(data) {
return `Multi polling test extension reports: ${data?.[0]?.reports}, count: ${data.length}`;
},
statusIcon(data) {
return data?.[0]?.reports === 'parsed' ? EXTENSION_ICONS.success : EXTENSION_ICONS.warning;
},
},
enablePolling: true,
methods: {
fetchMultiData() {
return endpointsToBePolled;
},
},
});
export const pollingErrorExtension = {
...collapsedDataErrorExtension,
enablePolling: true,

View File

@ -10,7 +10,7 @@ exports[`Issue Warning Component when issue is locked but not confidential rende
href="locked-path"
target="_blank"
>
Learn more
Learn more.
</gl-link-stub>
</span>
`;
@ -25,7 +25,7 @@ exports[`Issue Warning Component when noteable is confidential but not locked re
href="confidential-path"
target="_blank"
>
Learn more
Learn more.
</gl-link-stub>
</span>
`;

View File

@ -0,0 +1,69 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe SchedulePurgingStaleSecurityScans do
let_it_be(:namespaces) { table(:namespaces) }
let_it_be(:projects) { table(:projects) }
let_it_be(:pipelines) { table(:ci_pipelines) }
let_it_be(:builds) { table(:ci_builds) }
let_it_be(:security_scans) { table(:security_scans) }
let_it_be(:namespace) { namespaces.create!(name: "foo", path: "bar") }
let_it_be(:project) { projects.create!(namespace_id: namespace.id, project_namespace_id: namespace.id) }
let_it_be(:pipeline) { pipelines.create!(project_id: project.id, ref: 'master', sha: 'adf43c3a', status: 'success') }
let_it_be(:ci_build) { builds.create!(commit_id: pipeline.id, retried: false, type: 'Ci::Build') }
let!(:security_scan_1) { security_scans.create!(build_id: ci_build.id, scan_type: 1, created_at: 91.days.ago) }
let!(:security_scan_2) { security_scans.create!(build_id: ci_build.id, scan_type: 2, created_at: 91.days.ago) }
let(:com?) { false }
let(:dev_or_test_env?) { false }
before do
allow(::Gitlab).to receive(:com?).and_return(com?)
allow(::Gitlab).to receive(:dev_or_test_env?).and_return(dev_or_test_env?)
stub_const("#{described_class.name}::BATCH_SIZE", 1)
end
shared_examples_for 'schedules the background jobs' do
before do
# This will not be scheduled as it's not stale
security_scans.create!(build_id: ci_build.id, scan_type: 3)
end
around do |example|
freeze_time { Sidekiq::Testing.fake! { example.run } }
end
it 'creates 2 jobs', :aggregate_failures do
migrate!
expect(BackgroundMigrationWorker.jobs.size).to be(2)
expect(described_class::MIGRATION)
.to be_scheduled_delayed_migration(2.minutes, security_scan_1.id, security_scan_1.id)
expect(described_class::MIGRATION)
.to be_scheduled_delayed_migration(4.minutes, security_scan_2.id, security_scan_2.id)
end
end
context 'when the migration does not run on GitLab.com or `dev_or_test_env`' do
it 'does not run the migration' do
expect { migrate! }.not_to change { BackgroundMigrationWorker.jobs.size }
end
end
context 'when the migration runs on GitLab.com' do
let(:com?) { true }
it_behaves_like 'schedules the background jobs'
end
context 'when the migration runs on dev or test env' do
let(:dev_or_test_env?) { true }
it_behaves_like 'schedules the background jobs'
end
end

View File

@ -3,17 +3,17 @@
RSpec.shared_examples 'items list service' do
it 'avoids N+1' do
params = { board_id: board.id }
control = ActiveRecord::QueryRecorder.new { described_class.new(parent, user, params).execute }
control = ActiveRecord::QueryRecorder.new { list_service(params).execute }
new_list
expect { described_class.new(parent, user, params).execute }.not_to exceed_query_limit(control)
expect { list_service(params).execute }.not_to exceed_query_limit(control)
end
it 'returns opened items when list_id is missing' do
it 'returns opened items when list_id and list are missing' do
params = { board_id: board.id }
items = described_class.new(parent, user, params).execute
items = list_service(params).execute
expect(items).to match_array(backlog_items)
end
@ -21,7 +21,7 @@ RSpec.shared_examples 'items list service' do
it 'returns opened items when listing items from Backlog' do
params = { board_id: board.id, id: backlog.id }
items = described_class.new(parent, user, params).execute
items = list_service(params).execute
expect(items).to match_array(backlog_items)
end
@ -29,7 +29,7 @@ RSpec.shared_examples 'items list service' do
it 'returns opened items that have label list applied when listing items from a label list' do
params = { board_id: board.id, id: list1.id }
items = described_class.new(parent, user, params).execute
items = list_service(params).execute
expect(items).to match_array(list1_items)
end
@ -37,20 +37,24 @@ RSpec.shared_examples 'items list service' do
it 'returns closed items when listing items from Closed sorted by closed_at in descending order' do
params = { board_id: board.id, id: closed.id }
items = described_class.new(parent, user, params).execute
items = list_service(params).execute
expect(items).to eq(closed_items)
end
it 'raises an error if the list does not belong to the board' do
list = create(list_factory) # rubocop:disable Rails/SaveBang
service = described_class.new(parent, user, board_id: board.id, id: list.id)
params = { board_id: board.id, id: list.id }
service = list_service(params)
expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound)
end
it 'raises an error if list id is invalid' do
service = described_class.new(parent, user, board_id: board.id, id: nil)
it 'raises an error if list and list id are invalid or missing' do
params = { board_id: board.id, id: nil, list: nil }
service = list_service(params)
expect { service.execute }.to raise_error(ActiveRecord::RecordNotFound)
end
@ -58,8 +62,22 @@ RSpec.shared_examples 'items list service' do
it 'returns items from all lists if :all_list is used' do
params = { board_id: board.id, all_lists: true }
items = described_class.new(parent, user, params).execute
items = list_service(params).execute
expect(items).to match_array(all_items)
end
it 'returns opened items that have label list applied when using list param' do
params = { board_id: board.id, list: list1 }
items = list_service(params).execute
expect(items).to match_array(list1_items)
end
def list_service(params)
args = [parent, user].push(params)
described_class.new(*args)
end
end

View File

@ -968,10 +968,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-2.14.0.tgz#92b36bc98ccbed49a4dbca310862146275091cb2"
integrity sha512-U9EYmEIiTMl7R3X5DmCrw6fz7gz8c1kjvQtaF6HfJ15xDtR7trRAyCNbn3z7YGk1QJ8Cv/Ifw2/T5SxXwYd7dw==
"@gitlab/ui@40.2.1":
version "40.2.1"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-40.2.1.tgz#510ea1cda0a62afbfb0bc6a74b56e1128ddef428"
integrity sha512-dDsyu8Zuf5MYZwx6A6m2TeIPJL+ytTP7J0x0M8649MOqJJB2/3pq8IfcowWSQAvpO57w5N+G/QlotNypZ3e31w==
"@gitlab/ui@40.6.0":
version "40.6.0"
resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-40.6.0.tgz#67ee263d2ce88cb9ef27235e19b2a0844a321c29"
integrity sha512-aib9szbLX/UlejMp1ZG3dzZSLmDwK1V6fKxS5bueaaeHRNKPkQ7sFcyIZNG8sF3sHKUxDwA/OEfciIsRW6xzCQ==
dependencies:
"@popperjs/core" "^2.11.2"
bootstrap-vue "2.20.1"