Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
4d58268e54
commit
fae5be5632
|
@ -43,9 +43,6 @@ export const getProjectValueStreamStages = (requestPath, valueStreamId) => {
|
|||
export const getProjectValueStreamStageData = ({ requestPath, stageId, params }) =>
|
||||
axios.get(joinPaths(requestPath, 'events', stageId), { params });
|
||||
|
||||
export const getProjectValueStreamMetrics = (requestPath, params) =>
|
||||
axios.get(requestPath, { params });
|
||||
|
||||
/**
|
||||
* Dedicated project VSA paths
|
||||
*/
|
||||
|
|
|
@ -47,15 +47,13 @@ export default {
|
|||
'selectedStage',
|
||||
'selectedStageEvents',
|
||||
'selectedStageError',
|
||||
'stages',
|
||||
'summary',
|
||||
'permissions',
|
||||
'stageCounts',
|
||||
'endpoints',
|
||||
'features',
|
||||
'createdBefore',
|
||||
'createdAfter',
|
||||
'pagination',
|
||||
'hasNoAccessError',
|
||||
]),
|
||||
...mapGetters(['pathNavigationData', 'filterParams']),
|
||||
isLoaded() {
|
||||
|
@ -69,9 +67,7 @@ export default {
|
|||
return !this.isLoadingStage && this.isEmptyStage;
|
||||
},
|
||||
displayNoAccess() {
|
||||
return (
|
||||
!this.isLoadingStage && this.selectedStage?.id && !this.isUserAllowed(this.selectedStage.id)
|
||||
);
|
||||
return !this.isLoadingStage && this.hasNoAccessError;
|
||||
},
|
||||
displayPathNavigation() {
|
||||
return this.isLoading || (this.selectedStage && this.pathNavigationData.length);
|
||||
|
@ -137,10 +133,6 @@ export default {
|
|||
this.isOverviewDialogDismissed = true;
|
||||
setCookie(OVERVIEW_DIALOG_COOKIE, '1');
|
||||
},
|
||||
isUserAllowed(id) {
|
||||
const { permissions } = this;
|
||||
return Boolean(permissions?.[id]);
|
||||
},
|
||||
onHandleUpdatePagination(data) {
|
||||
this.updateStageTablePagination(data);
|
||||
},
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import {
|
||||
getProjectValueStreamStages,
|
||||
getProjectValueStreams,
|
||||
getProjectValueStreamMetrics,
|
||||
getValueStreamStageMedian,
|
||||
getValueStreamStageRecords,
|
||||
getValueStreamStageCounts,
|
||||
|
@ -52,24 +51,6 @@ export const fetchValueStreams = ({ commit, dispatch, state }) => {
|
|||
commit(types.RECEIVE_VALUE_STREAMS_ERROR, status);
|
||||
});
|
||||
};
|
||||
export const fetchCycleAnalyticsData = ({
|
||||
state: {
|
||||
endpoints: { requestPath },
|
||||
},
|
||||
getters: { legacyFilterParams },
|
||||
commit,
|
||||
}) => {
|
||||
commit(types.REQUEST_CYCLE_ANALYTICS_DATA);
|
||||
|
||||
return getProjectValueStreamMetrics(requestPath, legacyFilterParams)
|
||||
.then(({ data }) => commit(types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS, data))
|
||||
.catch(() => {
|
||||
commit(types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR);
|
||||
createFlash({
|
||||
message: __('There was an error while fetching value stream summary data.'),
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
export const fetchStageData = ({
|
||||
getters: { requestParams, filterParams, paginationParams },
|
||||
|
@ -153,7 +134,6 @@ export const fetchStageCountValues = ({
|
|||
|
||||
export const fetchValueStreamStageData = ({ dispatch }) =>
|
||||
Promise.all([
|
||||
dispatch('fetchCycleAnalyticsData'),
|
||||
dispatch('fetchStageData'),
|
||||
dispatch('fetchStageMedians'),
|
||||
dispatch('fetchStageCountValues'),
|
||||
|
@ -178,6 +158,11 @@ export const setDateRange = ({ dispatch, commit }, { createdAfter, createdBefore
|
|||
};
|
||||
|
||||
export const setInitialStage = ({ dispatch, commit, state: { stages } }, stage) => {
|
||||
if (!stages.length && !stage) {
|
||||
commit(types.SET_NO_ACCESS_ERROR);
|
||||
return null;
|
||||
}
|
||||
|
||||
const selectedStage = stage || stages[0];
|
||||
commit(types.SET_SELECTED_STAGE, selectedStage);
|
||||
return dispatch('fetchValueStreamStageData');
|
||||
|
|
|
@ -49,12 +49,6 @@ const dateRangeParams = ({ createdAfter, createdBefore }) => ({
|
|||
created_before: createdBefore ? dateFormat(createdBefore, dateFormats.isoDate) : null,
|
||||
});
|
||||
|
||||
export const legacyFilterParams = ({ daysInPast }) => {
|
||||
return {
|
||||
'cycle_analytics[start_date]': daysInPast,
|
||||
};
|
||||
};
|
||||
|
||||
export const filterParams = (state) => {
|
||||
return {
|
||||
...filterBarParams(state),
|
||||
|
|
|
@ -5,6 +5,7 @@ export const SET_SELECTED_VALUE_STREAM = 'SET_SELECTED_VALUE_STREAM';
|
|||
export const SET_SELECTED_STAGE = 'SET_SELECTED_STAGE';
|
||||
export const SET_DATE_RANGE = 'SET_DATE_RANGE';
|
||||
export const SET_PAGINATION = 'SET_PAGINATION';
|
||||
export const SET_NO_ACCESS_ERROR = 'SET_NO_ACCESS_ERROR';
|
||||
|
||||
export const REQUEST_VALUE_STREAMS = 'REQUEST_VALUE_STREAMS';
|
||||
export const RECEIVE_VALUE_STREAMS_SUCCESS = 'RECEIVE_VALUE_STREAMS_SUCCESS';
|
||||
|
@ -14,10 +15,6 @@ export const REQUEST_VALUE_STREAM_STAGES = 'REQUEST_VALUE_STREAM_STAGES';
|
|||
export const RECEIVE_VALUE_STREAM_STAGES_SUCCESS = 'RECEIVE_VALUE_STREAM_STAGES_SUCCESS';
|
||||
export const RECEIVE_VALUE_STREAM_STAGES_ERROR = 'RECEIVE_VALUE_STREAM_STAGES_ERROR';
|
||||
|
||||
export const REQUEST_CYCLE_ANALYTICS_DATA = 'REQUEST_CYCLE_ANALYTICS_DATA';
|
||||
export const RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS = 'RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS';
|
||||
export const RECEIVE_CYCLE_ANALYTICS_DATA_ERROR = 'RECEIVE_CYCLE_ANALYTICS_DATA_ERROR';
|
||||
|
||||
export const REQUEST_STAGE_DATA = 'REQUEST_STAGE_DATA';
|
||||
export const RECEIVE_STAGE_DATA_SUCCESS = 'RECEIVE_STAGE_DATA_SUCCESS';
|
||||
export const RECEIVE_STAGE_DATA_ERROR = 'RECEIVE_STAGE_DATA_ERROR';
|
||||
|
|
|
@ -41,6 +41,9 @@ export default {
|
|||
direction: direction || PAGINATION_SORT_DIRECTION_DESC,
|
||||
});
|
||||
},
|
||||
[types.SET_NO_ACCESS_ERROR](state) {
|
||||
state.hasNoAccessError = true;
|
||||
},
|
||||
[types.REQUEST_VALUE_STREAMS](state) {
|
||||
state.valueStreams = [];
|
||||
},
|
||||
|
@ -59,23 +62,12 @@ export default {
|
|||
[types.RECEIVE_VALUE_STREAM_STAGES_ERROR](state) {
|
||||
state.stages = [];
|
||||
},
|
||||
[types.REQUEST_CYCLE_ANALYTICS_DATA](state) {
|
||||
state.isLoading = true;
|
||||
state.hasError = false;
|
||||
},
|
||||
[types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS](state, data) {
|
||||
state.permissions = data?.permissions || {};
|
||||
state.hasError = false;
|
||||
},
|
||||
[types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR](state) {
|
||||
state.isLoading = false;
|
||||
state.hasError = true;
|
||||
},
|
||||
[types.REQUEST_STAGE_DATA](state) {
|
||||
state.isLoadingStage = true;
|
||||
state.isEmptyStage = false;
|
||||
state.selectedStageEvents = [];
|
||||
state.hasError = false;
|
||||
|
||||
state.hasNoAccessError = false;
|
||||
},
|
||||
[types.RECEIVE_STAGE_DATA_SUCCESS](state, events = []) {
|
||||
state.isLoadingStage = false;
|
||||
|
@ -83,13 +75,14 @@ export default {
|
|||
state.selectedStageEvents = events.map((ev) =>
|
||||
convertObjectPropsToCamelCase(ev, { deep: true }),
|
||||
);
|
||||
state.hasError = false;
|
||||
|
||||
state.hasNoAccessError = false;
|
||||
},
|
||||
[types.RECEIVE_STAGE_DATA_ERROR](state, error) {
|
||||
state.isLoadingStage = false;
|
||||
state.isEmptyStage = true;
|
||||
state.selectedStageEvents = [];
|
||||
state.hasError = true;
|
||||
|
||||
state.selectedStageError = error;
|
||||
},
|
||||
[types.REQUEST_STAGE_MEDIANS](state) {
|
||||
|
|
|
@ -10,9 +10,7 @@ export default () => ({
|
|||
createdAfter: null,
|
||||
createdBefore: null,
|
||||
stages: [],
|
||||
summary: [],
|
||||
analytics: [],
|
||||
stats: [],
|
||||
valueStreams: [],
|
||||
selectedValueStream: {},
|
||||
selectedStage: {},
|
||||
|
@ -20,11 +18,10 @@ export default () => ({
|
|||
selectedStageError: '',
|
||||
medians: {},
|
||||
stageCounts: {},
|
||||
hasError: false,
|
||||
hasNoAccessError: false,
|
||||
isLoading: false,
|
||||
isLoadingStage: false,
|
||||
isEmptyStage: false,
|
||||
permissions: {},
|
||||
pagination: {
|
||||
page: null,
|
||||
hasNextPage: false,
|
||||
|
|
|
@ -200,8 +200,7 @@ class FinalizeCiBuildsBigintConversion < Gitlab::Database::Migration[1.0]
|
|||
column: column,
|
||||
target_column: :id_convert_to_bigint,
|
||||
name: temporary_name,
|
||||
on_delete: on_delete,
|
||||
reverse_lock_order: true)
|
||||
on_delete: on_delete)
|
||||
end
|
||||
end
|
||||
|
||||
|
@ -214,9 +213,6 @@ class FinalizeCiBuildsBigintConversion < Gitlab::Database::Migration[1.0]
|
|||
next unless foreign_key_exists?(from_table, TABLE_NAME, column: column, primary_key: :id, name: existing_name)
|
||||
|
||||
with_lock_retries do
|
||||
# Explicitly lock table in order of parent, child to attempt to avoid deadlocks
|
||||
execute "LOCK TABLE #{TABLE_NAME}, #{from_table} IN ACCESS EXCLUSIVE MODE"
|
||||
|
||||
temporary_name = "#{existing_name}_tmp"
|
||||
|
||||
remove_foreign_key(from_table, TABLE_NAME, column: column, primary_key: :id, name: existing_name)
|
||||
|
|
|
@ -1,21 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class SchedulePopulateStatusColumnOfSecurityScans < Gitlab::Database::Migration[1.0]
|
||||
MIGRATION = 'PopulateStatusColumnOfSecurityScans'
|
||||
BATCH_SIZE = 10_000
|
||||
DELAY_INTERVAL = 2.minutes
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
return unless Gitlab.ee?
|
||||
|
||||
queue_background_migration_jobs_by_range_at_intervals(
|
||||
define_batchable_model('security_scans'),
|
||||
MIGRATION,
|
||||
DELAY_INTERVAL,
|
||||
batch_size: BATCH_SIZE
|
||||
)
|
||||
# no-op
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
@ -1,20 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ScheduleBackfillCiNamespaceMirrors < Gitlab::Database::Migration[1.0]
|
||||
MIGRATION = 'BackfillCiNamespaceMirrors'
|
||||
BATCH_SIZE = 10_000
|
||||
DELAY_INTERVAL = 2.minutes
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
queue_background_migration_jobs_by_range_at_intervals(
|
||||
Gitlab::BackgroundMigration::BackfillCiNamespaceMirrors::Namespace.base_query,
|
||||
MIGRATION,
|
||||
DELAY_INTERVAL,
|
||||
batch_size: BATCH_SIZE,
|
||||
track_jobs: true
|
||||
)
|
||||
# no-op
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
@ -1,20 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class ScheduleBackfillCiProjectMirrors < Gitlab::Database::Migration[1.0]
|
||||
MIGRATION = 'BackfillCiProjectMirrors'
|
||||
BATCH_SIZE = 10_000
|
||||
DELAY_INTERVAL = 2.minutes
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
queue_background_migration_jobs_by_range_at_intervals(
|
||||
Gitlab::BackgroundMigration::BackfillCiProjectMirrors::Project.base_query,
|
||||
MIGRATION,
|
||||
DELAY_INTERVAL,
|
||||
batch_size: BATCH_SIZE,
|
||||
track_jobs: true
|
||||
)
|
||||
# no-op
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CleanupBackfillCiNamespaceMirrors < Gitlab::Database::Migration[1.0]
|
||||
MIGRATION = 'BackfillCiNamespaceMirrors'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
finalize_background_migration(MIGRATION)
|
||||
# no-op
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
@ -1,12 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CleanupBackfillCiProjectMirrors < Gitlab::Database::Migration[1.0]
|
||||
MIGRATION = 'BackfillCiProjectMirrors'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
finalize_background_migration(MIGRATION)
|
||||
# no-op
|
||||
end
|
||||
|
||||
def down
|
||||
|
|
|
@ -1303,14 +1303,26 @@ process repositories that do not pass consistency checks.
|
|||
For Omnibus GitLab installations, edit `/etc/gitlab/gitlab.rb` and set the
|
||||
following keys (in this example, to disable the `hasDotgit` consistency check):
|
||||
|
||||
```ruby
|
||||
ignored_git_errors = ["hasDotgit = ignore"]
|
||||
omnibus_gitconfig['system'] = {
|
||||
"fsck" => ignored_git_errors,
|
||||
"fetch.fsck" => ignored_git_errors,
|
||||
"receive.fsck" => ignored_git_errors,
|
||||
}
|
||||
```
|
||||
- In [GitLab 15.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6800) and later:
|
||||
|
||||
```ruby
|
||||
gitaly['gitconfig'] = [
|
||||
{ key: "fsck.hasDotgit", value: "ignore" },
|
||||
{ key: "fetch.fsck.hasDotgit", value: "ignore" },
|
||||
{ key: "receive.fsck.hasDotgit", value: "ignore "},
|
||||
]
|
||||
```
|
||||
|
||||
- In GitLab 15.2 and earlier (legacy method):
|
||||
|
||||
```ruby
|
||||
ignored_git_errors = ["hasDotgit = ignore"]
|
||||
omnibus_gitconfig['system'] = {
|
||||
"fsck" => ignored_git_errors,
|
||||
"fetch.fsck" => ignored_git_errors,
|
||||
"receive.fsck" => ignored_git_errors,
|
||||
}
|
||||
```
|
||||
|
||||
For source installs, edit the Gitaly configuration (`gitaly.toml`) to do the
|
||||
equivalent:
|
||||
|
|
|
@ -80,7 +80,7 @@ separated by spaces.
|
|||
|
||||
To copy the name of a single failed test:
|
||||
|
||||
1. Expand the **Test summary** panel by selecting **Show test summary details** (**{angle-down}**).
|
||||
1. Expand the **Test summary** panel by selecting **Show test summary details** (**{chevron-lg-down}**).
|
||||
1. Select the test you want to review.
|
||||
1. Select **Copy test name to rerun locally** (**{copy-to-clipboard}**).
|
||||
|
||||
|
|
|
@ -208,7 +208,27 @@ See [the documentation](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/p
|
|||
Everything in `app/serializers`, used for presenting the response to a request,
|
||||
typically in JSON.
|
||||
|
||||
### Model class methods
|
||||
### Models
|
||||
|
||||
Classes and modules in `app/models` represent domain concepts that encapsulate both
|
||||
[data and behavior](https://en.wikipedia.org/wiki/Domain_model).
|
||||
|
||||
These classes can interact directly with a data store (like ActiveRecord models) or
|
||||
can be a thin wrapper (Plain Old Ruby Objects) on top of ActiveRecord models to express a
|
||||
richer domain concept.
|
||||
|
||||
[Entities and Value Objects](https://martinfowler.com/bliki/EvansClassification.html)
|
||||
that represent domain concepts are considered domain models.
|
||||
|
||||
Some examples:
|
||||
|
||||
- [`DesignManagement::DesignAtVersion`](https://gitlab.com/gitlab-org/gitlab/-/blob/b62ce98cff8e0530210670f9cb0314221181b77f/app/models/design_management/design_at_version.rb)
|
||||
is a model that leverages validations to combine designs and versions.
|
||||
- [`Ci::Minutes::Usage`](https://gitlab.com/gitlab-org/gitlab/-/blob/ec52f19f7325410177c00fef06379f55ab7cab67/ee/app/models/ci/minutes/usage.rb)
|
||||
is a Value Object that provides [CI/CD minutes usage](../ci/pipelines/cicd_minutes.md)
|
||||
for a given namespace.
|
||||
|
||||
#### Model class methods
|
||||
|
||||
These are class methods defined by _GitLab itself_, including the following
|
||||
methods provided by Active Record:
|
||||
|
@ -222,7 +242,7 @@ methods provided by Active Record:
|
|||
Any other methods such as `find_by(some_column: X)` are not included, and
|
||||
instead fall under the "Active Record" abstraction.
|
||||
|
||||
### Model instance methods
|
||||
#### Model instance methods
|
||||
|
||||
Instance methods defined on Active Record models by _GitLab itself_. Methods
|
||||
provided by Active Record are not included, except for the following methods:
|
||||
|
@ -232,7 +252,7 @@ provided by Active Record are not included, except for the following methods:
|
|||
- `destroy`
|
||||
- `delete`
|
||||
|
||||
### Active Record
|
||||
#### Active Record
|
||||
|
||||
The API provided by Active Record itself, such as the `where` method, `save`,
|
||||
`delete_all`, and so on.
|
||||
|
|
|
@ -556,19 +556,6 @@ sudo -u git -H cp config/puma.rb.example config/puma.rb
|
|||
# cores you have available. You can get that number via the `nproc` command.
|
||||
sudo -u git -H editor config/puma.rb
|
||||
|
||||
# Disable 'git gc --auto' because GitLab already runs 'git gc' when needed
|
||||
sudo -u git -H git config --global gc.auto 0
|
||||
|
||||
# Enable packfile bitmaps
|
||||
sudo -u git -H git config --global repack.writeBitmaps true
|
||||
|
||||
# Enable push options
|
||||
# Refer to https://docs.gitlab.com/ee/user/project/push_options.html for more information.
|
||||
sudo -u git -H git config --global receive.advertisePushOptions true
|
||||
|
||||
# Enable fsyncObjectFiles to reduce risk of repository corruption if the server crashes
|
||||
sudo -u git -H git config --global core.fsyncObjectFiles true
|
||||
|
||||
# Configure Redis connection settings
|
||||
sudo -u git -H cp config/resque.yml.example config/resque.yml
|
||||
sudo -u git -H cp config/cable.yml.example config/cable.yml
|
||||
|
|
|
@ -157,13 +157,29 @@ To fix this issue, you must disable SSL verification:
|
|||
|
||||
1. Change the global Git `sslVerify` option to `false` on the GitLab server.
|
||||
|
||||
- **For Omnibus installations**
|
||||
- **For Omnibus installations in [GitLab 15.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6800) and later**:
|
||||
|
||||
```ruby
|
||||
gitaly['gitconfig'] = [
|
||||
{key: "http.sslVerify", value: "false"},
|
||||
]
|
||||
```
|
||||
|
||||
- **For Omnibus installations in GitLab 15.2 and earlier (legacy method)**:
|
||||
|
||||
```ruby
|
||||
omnibus_gitconfig['system'] = { "http" => ["sslVerify = false"] }
|
||||
```
|
||||
|
||||
- **For installations from source**
|
||||
- **For installations from source in [GitLab 15.3](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/6800) and later**, edit the Gitaly configuration (`gitaly.toml`):
|
||||
|
||||
```toml
|
||||
[[git.config]]
|
||||
key = "http.sslVerify"
|
||||
value = "false"
|
||||
```
|
||||
|
||||
- **For installations from source in GitLab 15.2 and earlier (legacy method)**:
|
||||
|
||||
```shell
|
||||
git config --global http.sslVerify false
|
||||
|
|
|
@ -81,7 +81,15 @@ If you know the username, user ID, or email address, you can use the Rails conso
|
|||
new_password = ::User.random_password
|
||||
user.password = new_password
|
||||
user.password_confirmation = new_password
|
||||
```
|
||||
```
|
||||
|
||||
To set a specific value for the new password:
|
||||
|
||||
```ruby
|
||||
new_password = 'examplepassword'
|
||||
user.password = new_password
|
||||
user.password_confirmation = new_password
|
||||
```
|
||||
|
||||
1. Optional. Notify the user that an administrator changed their password:
|
||||
|
||||
|
|
|
@ -212,10 +212,10 @@ apply more than one:
|
|||
[`gitlab.rb`](https://gitlab.com/gitlab-org/omnibus-gitlab/-/blob/13.5.1+ee.0/files/gitlab-config-template/gitlab.rb.template#L1435-1455) file:
|
||||
|
||||
```shell
|
||||
omnibus_gitconfig['system'] = {
|
||||
gitaly['gitconfig'] = [
|
||||
# Set the http.postBuffer size, in bytes
|
||||
"http" => ["postBuffer = 524288000"]
|
||||
}
|
||||
{key: "http.postBuffer", value: "524288000"},
|
||||
]
|
||||
```
|
||||
|
||||
1. After applying this change, apply the configuration change:
|
||||
|
|
|
@ -324,6 +324,15 @@ When transferring groups, note:
|
|||
- Only explicit group membership is transferred, not inherited membership. If the group's owners have only inherited membership, this leaves the group without an owner. In this case, the user transferring the group becomes the group's owner.
|
||||
- Transfers fail if [packages](../packages/index.md) exist in any of the projects in the group, or in any of its subgroups.
|
||||
|
||||
To transfer a group:
|
||||
|
||||
1. On the top bar, select **Menu > Groups** and find your group.
|
||||
1. On the left sidebar, select **Settings > General**.
|
||||
1. Expand the **Advanced** section.
|
||||
1. In the **Remove group** section, select **Transfer group**.
|
||||
1. Select the group name in the drop down menu.
|
||||
1. Select **Transfer group**.
|
||||
|
||||
## Enable delayed project deletion **(PREMIUM)**
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220382) in GitLab 13.2.
|
||||
|
|
|
@ -1,77 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
# A job to create ci_namespace_mirrors entries in batches
|
||||
class BackfillCiNamespaceMirrors
|
||||
class Namespace < ActiveRecord::Base # rubocop:disable Style/Documentation
|
||||
include ::EachBatch
|
||||
|
||||
self.table_name = 'namespaces'
|
||||
self.inheritance_column = nil
|
||||
|
||||
scope :base_query, -> do
|
||||
select(:id, :parent_id)
|
||||
end
|
||||
end
|
||||
|
||||
PAUSE_SECONDS = 0.1
|
||||
SUB_BATCH_SIZE = 500
|
||||
|
||||
def perform(start_id, end_id)
|
||||
batch_query = Namespace.base_query.where(id: start_id..end_id)
|
||||
batch_query.each_batch(of: SUB_BATCH_SIZE) do |sub_batch|
|
||||
first, last = sub_batch.pick(Arel.sql('MIN(id), MAX(id)'))
|
||||
ranged_query = Namespace.unscoped.base_query.where(id: first..last)
|
||||
|
||||
update_sql = <<~SQL
|
||||
INSERT INTO ci_namespace_mirrors (namespace_id, traversal_ids)
|
||||
#{insert_values(ranged_query)}
|
||||
ON CONFLICT (namespace_id) DO NOTHING
|
||||
SQL
|
||||
# We do nothing on conflict because we consider they were already filled.
|
||||
|
||||
Namespace.connection.execute(update_sql)
|
||||
|
||||
sleep PAUSE_SECONDS
|
||||
end
|
||||
|
||||
mark_job_as_succeeded(start_id, end_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def insert_values(batch)
|
||||
calculated_traversal_ids(
|
||||
batch.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433')
|
||||
)
|
||||
end
|
||||
|
||||
# Copied from lib/gitlab/background_migration/backfill_namespace_traversal_ids_children.rb
|
||||
def calculated_traversal_ids(batch)
|
||||
<<~SQL
|
||||
WITH RECURSIVE cte(source_id, namespace_id, parent_id, height) AS (
|
||||
(
|
||||
SELECT batch.id, batch.id, batch.parent_id, 1
|
||||
FROM (#{batch.to_sql}) AS batch
|
||||
)
|
||||
UNION ALL
|
||||
(
|
||||
SELECT cte.source_id, n.id, n.parent_id, cte.height+1
|
||||
FROM namespaces n, cte
|
||||
WHERE n.id = cte.parent_id
|
||||
)
|
||||
)
|
||||
SELECT flat_hierarchy.source_id as namespace_id,
|
||||
array_agg(flat_hierarchy.namespace_id ORDER BY flat_hierarchy.height DESC) as traversal_ids
|
||||
FROM (SELECT * FROM cte FOR UPDATE) flat_hierarchy
|
||||
GROUP BY flat_hierarchy.source_id
|
||||
SQL
|
||||
end
|
||||
|
||||
def mark_job_as_succeeded(*arguments)
|
||||
Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded('BackfillCiNamespaceMirrors', arguments)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,52 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
# A job to create ci_project_mirrors entries in batches
|
||||
class BackfillCiProjectMirrors
|
||||
class Project < ActiveRecord::Base # rubocop:disable Style/Documentation
|
||||
include ::EachBatch
|
||||
|
||||
self.table_name = 'projects'
|
||||
|
||||
scope :base_query, -> do
|
||||
select(:id, :namespace_id)
|
||||
end
|
||||
end
|
||||
|
||||
PAUSE_SECONDS = 0.1
|
||||
SUB_BATCH_SIZE = 500
|
||||
|
||||
def perform(start_id, end_id)
|
||||
batch_query = Project.base_query.where(id: start_id..end_id)
|
||||
batch_query.each_batch(of: SUB_BATCH_SIZE) do |sub_batch|
|
||||
first, last = sub_batch.pick(Arel.sql('MIN(id), MAX(id)'))
|
||||
ranged_query = Project.unscoped.base_query.where(id: first..last)
|
||||
|
||||
update_sql = <<~SQL
|
||||
INSERT INTO ci_project_mirrors (project_id, namespace_id)
|
||||
#{insert_values(ranged_query)}
|
||||
ON CONFLICT (project_id) DO NOTHING
|
||||
SQL
|
||||
# We do nothing on conflict because we consider they were already filled.
|
||||
|
||||
Project.connection.execute(update_sql)
|
||||
|
||||
sleep PAUSE_SECONDS
|
||||
end
|
||||
|
||||
mark_job_as_succeeded(start_id, end_id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def insert_values(batch)
|
||||
batch.allow_cross_joins_across_databases(url: 'https://gitlab.com/gitlab-org/gitlab/-/issues/336433').to_sql
|
||||
end
|
||||
|
||||
def mark_job_as_succeeded(*arguments)
|
||||
Gitlab::Database::BackgroundMigrationJob.mark_all_as_succeeded('BackfillCiProjectMirrors', arguments)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,13 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
class PopulateStatusColumnOfSecurityScans # rubocop:disable Style/Documentation
|
||||
def perform(_start_id, _end_id)
|
||||
# no-op
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Gitlab::BackgroundMigration::PopulateStatusColumnOfSecurityScans.prepend_mod
|
|
@ -39740,9 +39740,6 @@ msgstr ""
|
|||
msgid "There was an error while fetching value stream analytics duration data."
|
||||
msgstr ""
|
||||
|
||||
msgid "There was an error while fetching value stream summary data."
|
||||
msgstr ""
|
||||
|
||||
msgid "There was an error with the reCAPTCHA. Please solve the reCAPTCHA again."
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -11,7 +11,6 @@ import ValueStreamFilters from '~/cycle_analytics/components/value_stream_filter
|
|||
import { NOT_ENOUGH_DATA_ERROR } from '~/cycle_analytics/constants';
|
||||
import initState from '~/cycle_analytics/store/state';
|
||||
import {
|
||||
permissions,
|
||||
transformedProjectStagePathData,
|
||||
selectedStage,
|
||||
issueEvents,
|
||||
|
@ -34,7 +33,6 @@ let wrapper;
|
|||
|
||||
const { id: groupId, path: groupPath } = currentGroup;
|
||||
const defaultState = {
|
||||
permissions,
|
||||
currentGroup,
|
||||
createdBefore,
|
||||
createdAfter,
|
||||
|
@ -240,24 +238,6 @@ describe('Value stream analytics component', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('without enough permissions', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent({
|
||||
initialState: {
|
||||
selectedStage,
|
||||
permissions: {
|
||||
...permissions,
|
||||
[selectedStage.id]: false,
|
||||
},
|
||||
},
|
||||
});
|
||||
});
|
||||
|
||||
it('renders the empty stage with `You need permission.` message', () => {
|
||||
expect(findEmptyStageTitle()).toBe('You need permission.');
|
||||
});
|
||||
});
|
||||
|
||||
describe('without a selected stage', () => {
|
||||
beforeEach(() => {
|
||||
wrapper = createComponent({
|
||||
|
|
|
@ -101,30 +101,12 @@ export const selectedStage = {
|
|||
...issueStage,
|
||||
value: null,
|
||||
active: false,
|
||||
isUserAllowed: true,
|
||||
emptyStageText:
|
||||
'The issue stage shows the time it takes from creating an issue to assigning the issue to a milestone, or add the issue to a list on your Issue Board. Begin creating issues to see data for this stage.',
|
||||
|
||||
slug: 'issue',
|
||||
};
|
||||
|
||||
export const stats = [issueStage, planStage, codeStage, testStage, reviewStage, stagingStage];
|
||||
|
||||
export const permissions = {
|
||||
issue: true,
|
||||
plan: true,
|
||||
code: true,
|
||||
test: true,
|
||||
review: true,
|
||||
staging: true,
|
||||
};
|
||||
|
||||
export const rawData = {
|
||||
summary,
|
||||
stats,
|
||||
permissions,
|
||||
};
|
||||
|
||||
export const convertedData = {
|
||||
summary: [
|
||||
{ value: '20', title: 'New Issues' },
|
||||
|
|
|
@ -153,6 +153,19 @@ describe('Project Value Stream Analytics actions', () => {
|
|||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with no value stream stages available', () => {
|
||||
it('will return SET_NO_ACCESS_ERROR', () => {
|
||||
state = { ...state, stages: [] };
|
||||
testAction({
|
||||
action: actions.setInitialStage,
|
||||
state,
|
||||
payload: null,
|
||||
expectedMutations: [{ type: 'SET_NO_ACCESS_ERROR' }],
|
||||
expectedActions: [],
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('updateStageTablePagination', () => {
|
||||
|
@ -170,46 +183,6 @@ describe('Project Value Stream Analytics actions', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('fetchCycleAnalyticsData', () => {
|
||||
beforeEach(() => {
|
||||
state = { ...defaultState, endpoints: mockEndpoints };
|
||||
mock = new MockAdapter(axios);
|
||||
mock.onGet(mockRequestPath).reply(httpStatusCodes.OK);
|
||||
});
|
||||
|
||||
it(`dispatches the 'setSelectedStage' and 'fetchStageData' actions`, () =>
|
||||
testAction({
|
||||
action: actions.fetchCycleAnalyticsData,
|
||||
state,
|
||||
payload: {},
|
||||
expectedMutations: [
|
||||
{ type: 'REQUEST_CYCLE_ANALYTICS_DATA' },
|
||||
{ type: 'RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS' },
|
||||
],
|
||||
expectedActions: [],
|
||||
}));
|
||||
|
||||
describe('with a failing request', () => {
|
||||
beforeEach(() => {
|
||||
state = { endpoints: mockEndpoints };
|
||||
mock = new MockAdapter(axios);
|
||||
mock.onGet(mockRequestPath).reply(httpStatusCodes.BAD_REQUEST);
|
||||
});
|
||||
|
||||
it(`commits the 'RECEIVE_CYCLE_ANALYTICS_DATA_ERROR' mutation`, () =>
|
||||
testAction({
|
||||
action: actions.fetchCycleAnalyticsData,
|
||||
state,
|
||||
payload: {},
|
||||
expectedMutations: [
|
||||
{ type: 'REQUEST_CYCLE_ANALYTICS_DATA' },
|
||||
{ type: 'RECEIVE_CYCLE_ANALYTICS_DATA_ERROR' },
|
||||
],
|
||||
expectedActions: [],
|
||||
}));
|
||||
});
|
||||
});
|
||||
|
||||
describe('fetchStageData', () => {
|
||||
const mockStagePath = /value_streams\/\w+\/stages\/\w+\/records/;
|
||||
const headers = {
|
||||
|
@ -529,14 +502,13 @@ describe('Project Value Stream Analytics actions', () => {
|
|||
});
|
||||
|
||||
describe('fetchValueStreamStageData', () => {
|
||||
it('will dispatch the fetchCycleAnalyticsData, fetchStageData, fetchStageMedians and fetchStageCountValues actions', () =>
|
||||
it('will dispatch the fetchStageData, fetchStageMedians and fetchStageCountValues actions', () =>
|
||||
testAction({
|
||||
action: actions.fetchValueStreamStageData,
|
||||
state,
|
||||
payload: {},
|
||||
expectedMutations: [],
|
||||
expectedActions: [
|
||||
{ type: 'fetchCycleAnalyticsData' },
|
||||
{ type: 'fetchStageData' },
|
||||
{ type: 'fetchStageMedians' },
|
||||
{ type: 'fetchStageCountValues' },
|
||||
|
|
|
@ -38,31 +38,24 @@ describe('Project Value Stream Analytics mutations', () => {
|
|||
});
|
||||
|
||||
it.each`
|
||||
mutation | stateKey | value
|
||||
${types.REQUEST_VALUE_STREAMS} | ${'valueStreams'} | ${[]}
|
||||
${types.RECEIVE_VALUE_STREAMS_ERROR} | ${'valueStreams'} | ${[]}
|
||||
${types.REQUEST_VALUE_STREAM_STAGES} | ${'stages'} | ${[]}
|
||||
${types.RECEIVE_VALUE_STREAM_STAGES_ERROR} | ${'stages'} | ${[]}
|
||||
${types.REQUEST_CYCLE_ANALYTICS_DATA} | ${'isLoading'} | ${true}
|
||||
${types.REQUEST_CYCLE_ANALYTICS_DATA} | ${'hasError'} | ${false}
|
||||
${types.RECEIVE_CYCLE_ANALYTICS_DATA_SUCCESS} | ${'hasError'} | ${false}
|
||||
${types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR} | ${'isLoading'} | ${false}
|
||||
${types.RECEIVE_CYCLE_ANALYTICS_DATA_ERROR} | ${'hasError'} | ${true}
|
||||
${types.REQUEST_STAGE_DATA} | ${'isLoadingStage'} | ${true}
|
||||
${types.REQUEST_STAGE_DATA} | ${'isEmptyStage'} | ${false}
|
||||
${types.REQUEST_STAGE_DATA} | ${'hasError'} | ${false}
|
||||
${types.REQUEST_STAGE_DATA} | ${'selectedStageEvents'} | ${[]}
|
||||
${types.RECEIVE_STAGE_DATA_SUCCESS} | ${'isLoadingStage'} | ${false}
|
||||
${types.RECEIVE_STAGE_DATA_SUCCESS} | ${'selectedStageEvents'} | ${[]}
|
||||
${types.RECEIVE_STAGE_DATA_SUCCESS} | ${'hasError'} | ${false}
|
||||
${types.RECEIVE_STAGE_DATA_ERROR} | ${'isLoadingStage'} | ${false}
|
||||
${types.RECEIVE_STAGE_DATA_ERROR} | ${'selectedStageEvents'} | ${[]}
|
||||
${types.RECEIVE_STAGE_DATA_ERROR} | ${'hasError'} | ${true}
|
||||
${types.RECEIVE_STAGE_DATA_ERROR} | ${'isEmptyStage'} | ${true}
|
||||
${types.REQUEST_STAGE_MEDIANS} | ${'medians'} | ${{}}
|
||||
${types.RECEIVE_STAGE_MEDIANS_ERROR} | ${'medians'} | ${{}}
|
||||
${types.REQUEST_STAGE_COUNTS} | ${'stageCounts'} | ${{}}
|
||||
${types.RECEIVE_STAGE_COUNTS_ERROR} | ${'stageCounts'} | ${{}}
|
||||
mutation | stateKey | value
|
||||
${types.REQUEST_VALUE_STREAMS} | ${'valueStreams'} | ${[]}
|
||||
${types.RECEIVE_VALUE_STREAMS_ERROR} | ${'valueStreams'} | ${[]}
|
||||
${types.REQUEST_VALUE_STREAM_STAGES} | ${'stages'} | ${[]}
|
||||
${types.RECEIVE_VALUE_STREAM_STAGES_ERROR} | ${'stages'} | ${[]}
|
||||
${types.REQUEST_STAGE_DATA} | ${'isLoadingStage'} | ${true}
|
||||
${types.REQUEST_STAGE_DATA} | ${'isEmptyStage'} | ${false}
|
||||
${types.REQUEST_STAGE_DATA} | ${'selectedStageEvents'} | ${[]}
|
||||
${types.RECEIVE_STAGE_DATA_SUCCESS} | ${'isLoadingStage'} | ${false}
|
||||
${types.RECEIVE_STAGE_DATA_SUCCESS} | ${'selectedStageEvents'} | ${[]}
|
||||
${types.RECEIVE_STAGE_DATA_ERROR} | ${'isLoadingStage'} | ${false}
|
||||
${types.RECEIVE_STAGE_DATA_ERROR} | ${'selectedStageEvents'} | ${[]}
|
||||
${types.RECEIVE_STAGE_DATA_ERROR} | ${'isEmptyStage'} | ${true}
|
||||
${types.REQUEST_STAGE_MEDIANS} | ${'medians'} | ${{}}
|
||||
${types.RECEIVE_STAGE_MEDIANS_ERROR} | ${'medians'} | ${{}}
|
||||
${types.REQUEST_STAGE_COUNTS} | ${'stageCounts'} | ${{}}
|
||||
${types.RECEIVE_STAGE_COUNTS_ERROR} | ${'stageCounts'} | ${{}}
|
||||
${types.SET_NO_ACCESS_ERROR} | ${'hasNoAccessError'} | ${true}
|
||||
`('$mutation will set $stateKey to $value', ({ mutation, stateKey, value }) => {
|
||||
mutations[mutation](state);
|
||||
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::BackgroundMigration::BackfillCiNamespaceMirrors, :migration,
|
||||
:suppress_gitlab_schemas_validate_connection, schema: 20211208122200 do
|
||||
let(:namespaces) { table(:namespaces) }
|
||||
let(:ci_namespace_mirrors) { table(:ci_namespace_mirrors) }
|
||||
|
||||
subject { described_class.new }
|
||||
|
||||
describe '#perform' do
|
||||
it 'creates hierarchies for all namespaces in range' do
|
||||
namespaces.create!(id: 5, name: 'test1', path: 'test1')
|
||||
namespaces.create!(id: 7, name: 'test2', path: 'test2')
|
||||
namespaces.create!(id: 8, name: 'test3', path: 'test3')
|
||||
|
||||
subject.perform(5, 7)
|
||||
|
||||
expect(ci_namespace_mirrors.all).to contain_exactly(
|
||||
an_object_having_attributes(namespace_id: 5, traversal_ids: [5]),
|
||||
an_object_having_attributes(namespace_id: 7, traversal_ids: [7])
|
||||
)
|
||||
end
|
||||
|
||||
it 'handles existing hierarchies gracefully' do
|
||||
namespaces.create!(id: 5, name: 'test1', path: 'test1')
|
||||
test2 = namespaces.create!(id: 7, name: 'test2', path: 'test2')
|
||||
namespaces.create!(id: 8, name: 'test3', path: 'test3', parent_id: 7)
|
||||
namespaces.create!(id: 9, name: 'test4', path: 'test4')
|
||||
|
||||
# Simulate a situation where a user has had a chance to move a group to another parent
|
||||
# before the background migration has had a chance to run
|
||||
test2.update!(parent_id: 5)
|
||||
ci_namespace_mirrors.create!(namespace_id: test2.id, traversal_ids: [5, 7])
|
||||
|
||||
subject.perform(5, 8)
|
||||
|
||||
expect(ci_namespace_mirrors.all).to contain_exactly(
|
||||
an_object_having_attributes(namespace_id: 5, traversal_ids: [5]),
|
||||
an_object_having_attributes(namespace_id: 7, traversal_ids: [5, 7]),
|
||||
an_object_having_attributes(namespace_id: 8, traversal_ids: [5, 7, 8])
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,47 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::BackgroundMigration::BackfillCiProjectMirrors, :migration,
|
||||
:suppress_gitlab_schemas_validate_connection, schema: 20211208122201 do
|
||||
let(:namespaces) { table(:namespaces) }
|
||||
let(:projects) { table(:projects) }
|
||||
let(:ci_project_mirrors) { table(:ci_project_mirrors) }
|
||||
|
||||
subject { described_class.new }
|
||||
|
||||
describe '#perform' do
|
||||
it 'creates ci_project_mirrors for all projects in range' do
|
||||
namespaces.create!(id: 10, name: 'namespace1', path: 'namespace1')
|
||||
projects.create!(id: 5, namespace_id: 10, name: 'test1', path: 'test1')
|
||||
projects.create!(id: 7, namespace_id: 10, name: 'test2', path: 'test2')
|
||||
projects.create!(id: 8, namespace_id: 10, name: 'test3', path: 'test3')
|
||||
|
||||
subject.perform(5, 7)
|
||||
|
||||
expect(ci_project_mirrors.all).to contain_exactly(
|
||||
an_object_having_attributes(project_id: 5, namespace_id: 10),
|
||||
an_object_having_attributes(project_id: 7, namespace_id: 10)
|
||||
)
|
||||
end
|
||||
|
||||
it 'handles existing ci_project_mirrors gracefully' do
|
||||
namespaces.create!(id: 10, name: 'namespace1', path: 'namespace1')
|
||||
namespaces.create!(id: 11, name: 'namespace2', path: 'namespace2', parent_id: 10)
|
||||
projects.create!(id: 5, namespace_id: 10, name: 'test1', path: 'test1')
|
||||
projects.create!(id: 7, namespace_id: 11, name: 'test2', path: 'test2')
|
||||
projects.create!(id: 8, namespace_id: 11, name: 'test3', path: 'test3')
|
||||
|
||||
# Simulate a situation where a user has had a chance to move a project to another namespace
|
||||
# before the background migration has had a chance to run
|
||||
ci_project_mirrors.create!(project_id: 7, namespace_id: 10)
|
||||
|
||||
subject.perform(5, 7)
|
||||
|
||||
expect(ci_project_mirrors.all).to contain_exactly(
|
||||
an_object_having_attributes(project_id: 5, namespace_id: 10),
|
||||
an_object_having_attributes(project_id: 7, namespace_id: 10)
|
||||
)
|
||||
end
|
||||
end
|
||||
end
|
|
@ -1,48 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe SchedulePopulateStatusColumnOfSecurityScans, :suppress_gitlab_schemas_validate_connection do
|
||||
before do
|
||||
allow(Gitlab).to receive(:ee?).and_return(ee?)
|
||||
stub_const("#{described_class.name}::BATCH_SIZE", 1)
|
||||
end
|
||||
|
||||
context 'when the Gitlab instance is CE' do
|
||||
let(:ee?) { false }
|
||||
|
||||
it 'does not run the migration' do
|
||||
expect { migrate! }.not_to change { BackgroundMigrationWorker.jobs.size }
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the Gitlab instance is EE' do
|
||||
let(:ee?) { true }
|
||||
let(:namespaces) { table(:namespaces) }
|
||||
let(:projects) { table(:projects) }
|
||||
let(:pipelines) { table(:ci_pipelines) }
|
||||
let(:builds) { table(:ci_builds) }
|
||||
let(:security_scans) { table(:security_scans) }
|
||||
|
||||
let(:namespace) { namespaces.create!(name: "foo", path: "bar") }
|
||||
let(:project) { projects.create!(namespace_id: namespace.id) }
|
||||
let(:pipeline) { pipelines.create!(project_id: project.id, ref: 'master', sha: 'adf43c3a', status: 'success') }
|
||||
let(: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) }
|
||||
let!(:security_scan_2) { security_scans.create!(build_id: ci_build.id, scan_type: 2) }
|
||||
|
||||
around do |example|
|
||||
freeze_time { Sidekiq::Testing.fake! { example.run } }
|
||||
end
|
||||
|
||||
it 'schedules the background 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
|
||||
end
|
|
@ -1 +1 @@
|
|||
- "./spec/migrations/20210907211557_finalize_ci_builds_bigint_conversion_spec.rb"
|
||||
[]
|
||||
|
|
Loading…
Reference in New Issue