Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-11-02 00:11:19 +00:00
parent f3bcf3c911
commit 023c409645
20 changed files with 352 additions and 185 deletions

View file

@ -29,7 +29,7 @@ run-dev-fixtures-ee:
extends: extends:
- .run-dev-fixtures - .run-dev-fixtures
- .dev-fixtures:rules:ee-only - .dev-fixtures:rules:ee-only
- .use-pg12-ee - .use-pg12-es7-ee
script: script:
- cp ee/db/fixtures/development/* $FIXTURE_PATH - cp ee/db/fixtures/development/* $FIXTURE_PATH
- *run-dev-fixtures-script - *run-dev-fixtures-script

View file

@ -275,34 +275,34 @@
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
PG_VERSION: "13" PG_VERSION: "13"
.use-pg11-ee: .use-pg11-es7-ee:
services: services:
- name: postgres:11.6 - name: postgres:11.6
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:5.0-alpine - name: redis:5.0-alpine
- name: elasticsearch:7.17.0 - name: elasticsearch:7.17.6
command: ["elasticsearch", "-E", "discovery.type=single-node", "-E", "xpack.security.enabled=false"] command: ["elasticsearch", "-E", "discovery.type=single-node", "-E", "xpack.security.enabled=false"]
variables: variables:
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
PG_VERSION: "11" PG_VERSION: "11"
.use-pg12-ee: .use-pg12-es7-ee:
services: services:
- name: postgres:12 - name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:6.0-alpine - name: redis:6.0-alpine
- name: elasticsearch:7.17.0 - name: elasticsearch:7.17.6
command: ["elasticsearch", "-E", "discovery.type=single-node", "-E", "xpack.security.enabled=false"] command: ["elasticsearch", "-E", "discovery.type=single-node", "-E", "xpack.security.enabled=false"]
variables: variables:
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
PG_VERSION: "12" PG_VERSION: "12"
.use-pg13-ee: .use-pg13-es7-ee:
services: services:
- name: postgres:13 - name: postgres:13
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:6.2-alpine - name: redis:6.2-alpine
- name: elasticsearch:7.17.0 - name: elasticsearch:7.17.6
command: ["elasticsearch", "-E", "discovery.type=single-node", "-E", "xpack.security.enabled=false"] command: ["elasticsearch", "-E", "discovery.type=single-node", "-E", "xpack.security.enabled=false"]
variables: variables:
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
@ -313,7 +313,7 @@
- name: postgres:12 - name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:6.0-alpine - name: redis:6.0-alpine
- name: elasticsearch:8.3.3 - name: elasticsearch:8.4.1
variables: variables:
POSTGRES_HOST_AUTH_METHOD: trust POSTGRES_HOST_AUTH_METHOD: trust
PG_VERSION: "12" PG_VERSION: "12"
@ -325,7 +325,19 @@
- name: postgres:12 - name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"] command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:6.0-alpine - name: redis:6.0-alpine
- name: opensearchproject/opensearch:1.2.4 - name: opensearchproject/opensearch:1.3.5
alias: elasticsearch
command: ["bin/opensearch", "-E", "discovery.type=single-node", "-E", "plugins.security.disabled=true"]
variables:
POSTGRES_HOST_AUTH_METHOD: trust
PG_VERSION: "12"
.use-pg12-opensearch2-ee:
services:
- name: postgres:12
command: ["postgres", "-c", "fsync=off", "-c", "synchronous_commit=off", "-c", "full_page_writes=off"]
- name: redis:6.0-alpine
- name: opensearchproject/opensearch:2.2.1
alias: elasticsearch alias: elasticsearch
command: ["bin/opensearch", "-E", "discovery.type=single-node", "-E", "plugins.security.disabled=true"] command: ["bin/opensearch", "-E", "discovery.type=single-node", "-E", "plugins.security.disabled=true"]
variables: variables:

View file

@ -574,11 +574,6 @@ rspec-ee unit pg12 es8:
- .rspec-ee-base-pg12-es8 - .rspec-ee-base-pg12-es8
- .rspec-ee-unit-parallel - .rspec-ee-unit-parallel
rspec-ee unit pg12 opensearch1:
extends:
- .rspec-ee-base-pg12-opensearch1
- .rspec-ee-unit-parallel
rspec-ee unit pg12 minimal: rspec-ee unit pg12 minimal:
extends: extends:
- rspec-ee unit pg12 - rspec-ee unit pg12
@ -602,11 +597,6 @@ rspec-ee integration pg12 es8:
- .rspec-ee-base-pg12-es8 - .rspec-ee-base-pg12-es8
- .rspec-ee-integration-parallel - .rspec-ee-integration-parallel
rspec-ee integration pg12 opensearch1:
extends:
- .rspec-ee-base-pg12-opensearch1
- .rspec-ee-integration-parallel
rspec-ee integration pg12 minimal: rspec-ee integration pg12 minimal:
extends: extends:
- rspec-ee integration pg12 - rspec-ee integration pg12
@ -630,11 +620,6 @@ rspec-ee system pg12 es8:
- .rspec-ee-base-pg12-es8 - .rspec-ee-base-pg12-es8
- .rspec-ee-system-parallel - .rspec-ee-system-parallel
rspec-ee system pg12 opensearch1:
extends:
- .rspec-ee-base-pg12-opensearch1
- .rspec-ee-system-parallel
rspec-ee system pg12 minimal: rspec-ee system pg12 minimal:
extends: extends:
- rspec-ee system pg12 - rspec-ee system pg12
@ -743,6 +728,61 @@ rspec-ee system pg11:
- .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only - .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
- .rspec-ee-system-parallel - .rspec-ee-system-parallel
# PG12
rspec-ee unit pg12 es7:
extends:
- .rspec-ee-base-pg12-es7
- .rspec-ee-unit-parallel
- .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
rspec-ee unit pg12 opensearch1:
extends:
- .rspec-ee-base-pg12-opensearch1
- .rspec-ee-unit-parallel
- .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
rspec-ee unit pg12 opensearch2:
extends:
- .rspec-ee-base-pg12-opensearch2
- .rspec-ee-unit-parallel
- .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
rspec-ee integration pg12 es7:
extends:
- .rspec-ee-base-pg12-es7
- .rspec-ee-integration-parallel
- .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
rspec-ee integration pg12 opensearch1:
extends:
- .rspec-ee-base-pg12-opensearch1
- .rspec-ee-integration-parallel
- .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
rspec-ee integration pg12 opensearch2:
extends:
- .rspec-ee-base-pg12-opensearch2
- .rspec-ee-integration-parallel
- .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
rspec-ee system pg12 es7:
extends:
- .rspec-ee-base-pg12-es7
- .rspec-ee-system-parallel
- .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
rspec-ee system pg12 opensearch1:
extends:
- .rspec-ee-base-pg12-opensearch1
- .rspec-ee-system-parallel
- .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
rspec-ee system pg12 opensearch2:
extends:
- .rspec-ee-base-pg12-opensearch2
- .rspec-ee-system-parallel
- .rails:rules:default-branch-schedule-nightly--code-backstage-ee-only
# PG13 # PG13
rspec-ee migration pg13: rspec-ee migration pg13:
extends: extends:

View file

@ -109,12 +109,18 @@ include:
.rspec-ee-base-pg11: .rspec-ee-base-pg11:
extends: extends:
- .rspec-base - .rspec-base
- .use-pg11-ee - .use-pg11-es7-ee
.rspec-ee-base-pg12: .rspec-ee-base-pg12:
extends: extends:
- .rspec-base - .rspec-base
- .use-pg12-ee - .use-pg12-es7-ee
.rspec-ee-base-pg12-es7:
extends:
- .rspec-base
- .use-pg12-es7-ee
- .rails:rules:run-search-tests
.rspec-ee-base-pg12-es8: .rspec-ee-base-pg12-es8:
extends: extends:
@ -128,10 +134,16 @@ include:
- .use-pg12-opensearch1-ee - .use-pg12-opensearch1-ee
- .rails:rules:run-search-tests - .rails:rules:run-search-tests
.rspec-ee-base-pg12-opensearch2:
extends:
- .rspec-base
- .use-pg12-opensearch2-ee
- .rails:rules:run-search-tests
.rspec-ee-base-pg13: .rspec-ee-base-pg13:
extends: extends:
- .rspec-base - .rspec-base
- .use-pg13-ee - .use-pg13-es7-ee
.db-job-base: .db-job-base:
extends: extends:

View file

@ -573,6 +573,8 @@
rules: rules:
- <<: *if-merge-request-labels-group-global-search - <<: *if-merge-request-labels-group-global-search
changes: *search-backend-patterns changes: *search-backend-patterns
- <<: *if-merge-request-labels-group-global-search
changes: *ci-patterns
.rails:rules:ee-and-foss-default-rules: .rails:rules:ee-and-foss-default-rules:
rules: rules:

View file

@ -145,7 +145,8 @@ export default {
}, },
currentTabIndex: { currentTabIndex: {
get() { get() {
return this.$options.tabsConfig.findIndex((tab) => tab.id === this.activeTab); const tabIndex = this.$options.tabsConfig.findIndex((tab) => tab.id === this.activeTab);
return tabIndex >= 0 ? tabIndex : 0;
}, },
set(tabIdx) { set(tabIdx) {
const tabId = this.$options.tabsConfig[tabIdx].id; const tabId = this.$options.tabsConfig[tabIdx].id;

View file

@ -5,9 +5,26 @@ import { joinPaths } from '~/lib/utils/url_utility';
Vue.use(VueRouter); Vue.use(VueRouter);
export default function createRouter(base) { export default function createRouter(base) {
return new VueRouter({ const router = new VueRouter({
mode: 'history', mode: 'history',
base: joinPaths(gon.relative_url_root || '', base), base: joinPaths(gon.relative_url_root || '', base),
routes: [{ path: '/:tabId', name: 'tab' }], routes: [{ path: '/:tabId', name: 'tab' }],
}); });
/*
Backward-compatible behavior. Redirects hash mode URLs to history mode ones.
Ex: from #/overview to /overview
from #/metrics to /metrics
from #/activity to /activity
*/
router.beforeEach((to, _, next) => {
if (to.hash.startsWith('#/')) {
const path = to.fullPath.substring(2);
next(path);
} else {
next();
}
});
return router;
} }

View file

@ -38,128 +38,6 @@ This content has been converted to a Rake task, see [verify database values can
This content has been moved to [Troubleshooting Repository mirroring](../../user/project/repository/mirror/index.md#transfer-mirror-users-and-tokens-to-a-single-service-account-in-rails-console). This content has been moved to [Troubleshooting Repository mirroring](../../user/project/repository/mirror/index.md#transfer-mirror-users-and-tokens-to-a-single-service-account-in-rails-console).
## Users
### Create new user
```ruby
u = User.new(username: 'test_user', email: 'test@example.com', name: 'Test User', password: 'password', password_confirmation: 'password')
u.skip_confirmation! # Use it only if you wish user to be automatically confirmed. If skipped, user receives confirmation e-mail
u.save!
```
### Skip reconfirmation
```ruby
user = User.find_by_username('<username>')
user.skip_reconfirmation!
```
### Disable 2fa for single user
**In GitLab 13.5 and later:**
Use the code under [Disable 2FA | For a single user](../../security/two_factor_authentication.md#for-a-single-user) so that the target user
is notified that 2FA has been disabled.
**In GitLab 13.4 and earlier:**
```ruby
user = User.find_by_username('<username>')
user.disable_two_factor!
```
### Active users & Historical users
```ruby
# Active users on the instance, now
User.active.count
# Users taking a seat on the instance
User.billable.count
# The historical max on the instance as of the past year
::HistoricalData.max_historical_user_count(from: 1.year.ago.beginning_of_day, to: Time.current.end_of_day)
```
Using cURL and jq (up to a max 100, see [Pagination](../../api/index.md#pagination)):
```shell
curl --silent --header "Private-Token: ********************" \
"https://gitlab.example.com/api/v4/users?per_page=100&active" | jq --compact-output '.[] | [.id,.name,.username]'
```
### Update Daily Billable & Historical users
```ruby
# Forces recount of historical (max) users
::HistoricalDataWorker.new.perform
# Forces recount of daily billable users
identifier = Analytics::UsageTrends::Measurement.identifiers[:billable_users]
::Analytics::UsageTrends::CounterJobWorker.new.perform(identifier, User.minimum(:id), User.maximum(:id), Time.zone.now)
```
### Block or Delete Users that have no projects or groups
```ruby
users = User.where('id NOT IN (select distinct(user_id) from project_authorizations)')
# How many users are removed?
users.count
# If that count looks sane:
# You can either block the users:
users.each { |user| user.blocked? ? nil : user.block! }
# Or you can delete them:
# need 'current user' (your user) for auditing purposes
current_user = User.find_by(username: '<your username>')
users.each do |user|
DeleteUserWorker.perform_async(current_user.id, user.id)
end
```
### Deactivate Users that have no recent activity
```ruby
days_inactive = 90
inactive_users = User.active.where("last_activity_on <= ?", days_inactive.days.ago)
inactive_users.each do |user|
puts "user '#{user.username}': #{user.last_activity_on}"
user.deactivate!
end
```
### Block Users that have no recent activity
```ruby
days_inactive = 90
inactive_users = User.active.where("last_activity_on <= ?", days_inactive.days.ago)
inactive_users.each do |user|
puts "user '#{user.username}': #{user.last_activity_on}"
user.block!
end
```
### Find a user's max permissions for project/group
```ruby
user = User.find_by_username 'username'
project = Project.find_by_full_path 'group/project'
user.max_member_access_for_project project.id
```
```ruby
user = User.find_by_username 'username'
group = Group.find_by_full_path 'group'
user.max_member_access_for_group group.id
```
## Merge requests ## Merge requests
## CI ## CI

View file

@ -85,7 +85,7 @@ In this mode, `jest` would resolve all the dependencies of related to the change
In addition, there are a few circumstances where we would always run the full Jest tests: In addition, there are a few circumstances where we would always run the full Jest tests:
- when the `pipeline:run-all-jest` label is set on the merge request - when the `pipeline:run-all-jest` label is set on the merge request or is set by triage automation when the merge request is approved by any reviewer
- when the merge request is created by an automation (for example, Gitaly update or MR targeting a stable branch) - when the merge request is created by an automation (for example, Gitaly update or MR targeting a stable branch)
- when the merge request is created in a security mirror - when the merge request is created in a security mirror
- when any CI configuration file is changed (for example, `.gitlab-ci.yml` or `.gitlab/ci/**/*`) - when any CI configuration file is changed (for example, `.gitlab-ci.yml` or `.gitlab/ci/**/*`)

View file

@ -104,6 +104,8 @@ instead of the Rails console.
Using the [Rails console](../administration/operations/rails_console.md), 2FA for a single user can be disabled. Using the [Rails console](../administration/operations/rails_console.md), 2FA for a single user can be disabled.
Connect to the Rails console and run: Connect to the Rails console and run:
**In GitLab 13.5 and later:**
```ruby ```ruby
admin = User.find_by_username('<USERNAME>') admin = User.find_by_username('<USERNAME>')
user_to_disable = User.find_by_username('<USERNAME>') user_to_disable = User.find_by_username('<USERNAME>')
@ -111,6 +113,9 @@ user_to_disable = User.find_by_username('<USERNAME>')
TwoFactor::DestroyService.new(admin, user: user_to_disable).execute TwoFactor::DestroyService.new(admin, user: user_to_disable).execute
``` ```
NOTE:
The target user is notified that 2FA has been disabled.
### For all users ### For all users
There may be some special situations where you want to disable 2FA for everyone There may be some special situations where you want to disable 2FA for everyone

View file

@ -460,3 +460,40 @@ If your credit card is declined when purchasing a GitLab subscription, possible
Check with your financial institution to confirm if any of these reasons apply. If they don't Check with your financial institution to confirm if any of these reasons apply. If they don't
apply, contact [GitLab Support](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293). apply, contact [GitLab Support](https://support.gitlab.com/hc/en-us/requests/new?ticket_form_id=360000071293).
### Check daily and historical billable users
You can get a list of daily and historical billable users in your GitLab instance.
1. [Start a rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session).
1. Count the number of users in the instance:
```ruby
User.billable.count
```
1. Get the historical maximum number of users on the instance from the past year:
```ruby
::HistoricalData.max_historical_user_count(from: 1.year.ago.beginning_of_day, to: Time.current.end_of_day)
```
### Update daily billable and historical users
You can trigger a manual update of the daily and historical billable users in your GitLab instance.
1. [Start a rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session).
1. Force an update of the daily billable users:
```ruby
identifier = Analytics::UsageTrends::Measurement.identifiers[:billable_users]
::Analytics::UsageTrends::CounterJobWorker.new.perform(identifier, User.minimum(:id), User.maximum(:id), Time.zone.now)
```
1. Force an update of the historical max billable users:
```ruby
::HistoricalDataWorker.new.perform
```

View file

@ -283,3 +283,62 @@ You can also delete a user and their contributions, such as merge requests, issu
NOTE: NOTE:
Before 15.1, additionally groups of which deleted user were the only owner among direct members were deleted. Before 15.1, additionally groups of which deleted user were the only owner among direct members were deleted.
## Troubleshooting
When moderating users, you may need to perform bulk actions on them based on certain conditions. The following rails console scripts show some examples of this. You may [start a rails console session](../../administration/operations/rails_console.md#starting-a-rails-console-session) and use scripts similar to the following:
### Deactivate Users that have no recent activity
WARNING:
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
```ruby
days_inactive = 90
inactive_users = User.active.where("last_activity_on <= ?", days_inactive.days.ago)
inactive_users.each do |user|
puts "user '#{user.username}': #{user.last_activity_on}"
user.deactivate!
end
```
### Block Users that have no recent activity
WARNING:
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
```ruby
days_inactive = 90
inactive_users = User.active.where("last_activity_on <= ?", days_inactive.days.ago)
inactive_users.each do |user|
puts "user '#{user.username}': #{user.last_activity_on}"
user.block!
end
```
### Block or Delete Users that have no projects or groups
WARNING:
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
```ruby
users = User.where('id NOT IN (select distinct(user_id) from project_authorizations)')
# How many users are removed?
users.count
# If that count looks sane:
# You can either block the users:
users.each { |user| user.blocked? ? nil : user.block! }
# Or you can delete them:
# need 'current user' (your user) for auditing purposes
current_user = User.find_by(username: '<your username>')
users.each do |user|
DeleteUserWorker.perform_async(current_user.id, user.id)
end
```

View file

@ -859,3 +859,17 @@ Commands that change data can cause damage if not run correctly or under the rig
```ruby ```ruby
GroupDestroyWorker.new.perform(group_id, user_id) GroupDestroyWorker.new.perform(group_id, user_id)
``` ```
### Find a user's max permissions for a group or project
```ruby
user = User.find_by_username 'username'
project = Project.find_by_full_path 'group/project'
user.max_member_access_for_project project.id
```
```ruby
user = User.find_by_username 'username'
group = Group.find_by_full_path 'group'
user.max_member_access_for_group group.id
```

View file

@ -49,3 +49,16 @@ Users are:
- Created when first signing with [Group SAML](../../group/saml_sso/index.md). - Created when first signing with [Group SAML](../../group/saml_sso/index.md).
- Automatically created by [SCIM](../../group/saml_sso/scim_setup.md) when the user is created in - Automatically created by [SCIM](../../group/saml_sso/scim_setup.md) when the user is created in
the identity provider. the identity provider.
## Create users through the Rails console
WARNING:
Commands that change data can cause damage if not run correctly or under the right conditions. Always run commands in a test environment first and have a backup instance ready to restore.
To create a user through the rails console, [start a console session](../../../administration/operations/rails_console.md#starting-a-rails-console-session) and run the following commands:
```ruby
u = User.new(username: 'test_user', email: 'test@example.com', name: 'Test User', password: 'password', password_confirmation: 'password')
u.skip_confirmation! # Use it only if you wish user to be automatically confirmed. If skipped, user receives confirmation e-mail
u.save!
```

View file

@ -171,6 +171,7 @@ module API
namespace do namespace do
mount ::API::AccessRequests mount ::API::AccessRequests
mount ::API::Appearance mount ::API::Appearance
mount ::API::BulkImports
mount ::API::Ci::Runner mount ::API::Ci::Runner
mount ::API::Clusters::Agents mount ::API::Clusters::Agents
mount ::API::Clusters::AgentTokens mount ::API::Clusters::AgentTokens
@ -207,7 +208,6 @@ module API
mount ::API::Boards mount ::API::Boards
mount ::API::Branches mount ::API::Branches
mount ::API::BroadcastMessages mount ::API::BroadcastMessages
mount ::API::BulkImports
mount ::API::Ci::JobArtifacts mount ::API::Ci::JobArtifacts
mount ::API::Ci::Jobs mount ::API::Ci::Jobs
mount ::API::Ci::PipelineSchedules mount ::API::Ci::PipelineSchedules

View file

@ -41,7 +41,15 @@ module API
resource :bulk_imports do resource :bulk_imports do
desc 'Start a new GitLab Migration' do desc 'Start a new GitLab Migration' do
detail 'This feature was introduced in GitLab 14.2.' detail 'This feature was introduced in GitLab 14.2.'
success Entities::BulkImport success code: 200, model: Entities::BulkImport
consumes ['application/x-www-form-urlencoded']
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 400, message: 'Bad request' },
{ code: 404, message: 'Not found' },
{ code: 422, message: 'Unprocessable entity' },
{ code: 503, message: 'Service unavailable' }
]
end end
params do params do
requires :configuration, type: Hash, desc: 'The source GitLab instance configuration' do requires :configuration, type: Hash, desc: 'The source GitLab instance configuration' do
@ -88,7 +96,13 @@ module API
desc 'List all GitLab Migrations' do desc 'List all GitLab Migrations' do
detail 'This feature was introduced in GitLab 14.1.' detail 'This feature was introduced in GitLab 14.1.'
success Entities::BulkImport is_array true
success code: 200, model: Entities::BulkImport
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 404, message: 'Not found' },
{ code: 503, message: 'Service unavailable' }
]
end end
params do params do
use :pagination use :pagination
@ -103,7 +117,13 @@ module API
desc "List all GitLab Migrations' entities" do desc "List all GitLab Migrations' entities" do
detail 'This feature was introduced in GitLab 14.1.' detail 'This feature was introduced in GitLab 14.1.'
success Entities::BulkImports::Entity is_array true
success code: 200, model: Entities::BulkImports::Entity
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 404, message: 'Not found' },
{ code: 503, message: 'Service unavailable' }
]
end end
params do params do
use :pagination use :pagination
@ -123,7 +143,12 @@ module API
desc 'Get GitLab Migration details' do desc 'Get GitLab Migration details' do
detail 'This feature was introduced in GitLab 14.1.' detail 'This feature was introduced in GitLab 14.1.'
success Entities::BulkImport success code: 200, model: Entities::BulkImport
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 404, message: 'Not found' },
{ code: 503, message: 'Service unavailable' }
]
end end
params do params do
requires :import_id, type: Integer, desc: "The ID of user's GitLab Migration" requires :import_id, type: Integer, desc: "The ID of user's GitLab Migration"
@ -134,7 +159,13 @@ module API
desc "List GitLab Migration entities" do desc "List GitLab Migration entities" do
detail 'This feature was introduced in GitLab 14.1.' detail 'This feature was introduced in GitLab 14.1.'
success Entities::BulkImports::Entity is_array true
success code: 200, model: Entities::BulkImports::Entity
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 404, message: 'Not found' },
{ code: 503, message: 'Service unavailable' }
]
end end
params do params do
requires :import_id, type: Integer, desc: "The ID of user's GitLab Migration" requires :import_id, type: Integer, desc: "The ID of user's GitLab Migration"
@ -148,7 +179,12 @@ module API
desc 'Get GitLab Migration entity details' do desc 'Get GitLab Migration entity details' do
detail 'This feature was introduced in GitLab 14.1.' detail 'This feature was introduced in GitLab 14.1.'
success Entities::BulkImports::Entity success code: 200, model: Entities::BulkImports::Entity
failure [
{ code: 401, message: 'Unauthorized' },
{ code: 404, message: 'Not found' },
{ code: 503, message: 'Service unavailable' }
]
end end
params do params do
requires :import_id, type: Integer, desc: "The ID of user's GitLab Migration" requires :import_id, type: Integer, desc: "The ID of user's GitLab Migration"

View file

@ -3,11 +3,13 @@
module API module API
module Entities module Entities
class BulkImport < Grape::Entity class BulkImport < Grape::Entity
expose :id expose :id, documentation: { type: 'integer', example: 1 }
expose :status_name, as: :status expose :status_name, as: :status, documentation: {
expose :source_type type: 'string', example: 'finished', values: %w[created started finished timeout failed]
expose :created_at }
expose :updated_at expose :source_type, documentation: { type: 'string', example: 'gitlab' }
expose :created_at, documentation: { type: 'dateTime', example: '2012-05-28T04:42:42-07:00' }
expose :updated_at, documentation: { type: 'dateTime', example: '2012-05-28T04:42:42-07:00' }
end end
end end
end end

View file

@ -4,19 +4,21 @@ module API
module Entities module Entities
module BulkImports module BulkImports
class Entity < Grape::Entity class Entity < Grape::Entity
expose :id expose :id, documentation: { type: 'integer', example: 1 }
expose :bulk_import_id expose :bulk_import_id, documentation: { type: 'integer', example: 1 }
expose :status_name, as: :status expose :status_name, as: :status, documentation: {
expose :source_full_path type: 'string', example: 'created', values: %w[created started finished timeout failed]
expose :destination_name # deprecated }
expose :destination_slug expose :source_full_path, documentation: { type: 'string', example: 'source_group' }
expose :destination_namespace expose :destination_name, documentation: { type: 'string', example: 'destination_slug' } # deprecated
expose :parent_id expose :destination_slug, documentation: { type: 'string', example: 'destination_slug' }
expose :namespace_id expose :destination_namespace, documentation: { type: 'string', example: 'destination_path' }
expose :project_id expose :parent_id, documentation: { type: 'integer', example: 1 }
expose :created_at expose :namespace_id, documentation: { type: 'integer', example: 1 }
expose :updated_at expose :project_id, documentation: { type: 'integer', example: 1 }
expose :failures, using: EntityFailure expose :created_at, documentation: { type: 'dateTime', example: '2012-05-28T04:42:42-07:00' }
expose :updated_at, documentation: { type: 'dateTime', example: '2012-05-28T04:42:42-07:00' }
expose :failures, using: EntityFailure, documentation: { is_array: true }
end end
end end
end end

View file

@ -4,16 +4,18 @@ module API
module Entities module Entities
module BulkImports module BulkImports
class EntityFailure < Grape::Entity class EntityFailure < Grape::Entity
expose :relation expose :relation, documentation: { type: 'string', example: 'group' }
expose :pipeline_step, as: :step expose :pipeline_step, as: :step, documentation: { type: 'string', example: 'extractor' }
expose :exception_message do |failure| expose :exception_message, documentation: { type: 'string', example: 'error message' } do |failure|
::Projects::ImportErrorFilter.filter_message(failure.exception_message.truncate(72)) ::Projects::ImportErrorFilter.filter_message(failure.exception_message.truncate(72))
end end
expose :exception_class expose :exception_class, documentation: { type: 'string', example: 'Exception' }
expose :correlation_id_value expose :correlation_id_value, documentation: { type: 'string', example: 'dfcf583058ed4508e4c7c617bd7f0edd' }
expose :created_at expose :created_at, documentation: { type: 'dateTime', example: '2012-05-28T04:42:42-07:00' }
expose :pipeline_class expose :pipeline_class, documentation: {
expose :pipeline_step type: 'string', example: 'BulkImports::Groups::Pipelines::GroupPipeline'
}
expose :pipeline_step, documentation: { type: 'string', example: 'extractor' }
end end
end end
end end

View file

@ -0,0 +1,35 @@
import createRouter from '~/vue_shared/alert_details/router';
import setWindowLocation from 'helpers/set_window_location_helper';
const BASE_PATH = '/-/alert_management/1/details';
const EMPTY_HASH = '';
const NOOP = () => {};
describe('AlertDetails router', () => {
const originalLocation = window.location.href;
let router;
beforeEach(() => {
setWindowLocation(originalLocation);
router = createRouter(BASE_PATH);
});
describe('redirects hash route mode URLs to history route mode', () => {
it.each`
hashPath | historyPath
${'/#/overview'} | ${'/overview'}
${'#/overview'} | ${'/overview'}
${'/#/'} | ${'/'}
${'#/'} | ${'/'}
${'/#'} | ${'/'}
${'#'} | ${'/'}
${'/'} | ${'/'}
${'/overview'} | ${'/overview'}
`('should redirect "$hashPath" to "$historyPath"', ({ hashPath, historyPath }) => {
router.push(hashPath, NOOP);
expect(window.location.hash).toBe(EMPTY_HASH);
expect(window.location.pathname).toBe(BASE_PATH + historyPath);
});
});
});