Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
35850d3d16
commit
c20abe491c
|
@ -1 +1 @@
|
|||
251acb8c75aa66481893bf775a44cba669ccc3c9
|
||||
c0b07ba36fc8fc40830f061cb55a5c951a166e1c
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<script>
|
||||
import { GlButton, GlSprintf } from '@gitlab/ui';
|
||||
import { createAlert } from '~/alert';
|
||||
import { visitUrl } from '~/lib/utils/url_utility';
|
||||
import { STATUS_MERGED } from '~/issues/constants';
|
||||
import { BV_SHOW_MODAL } from '~/lib/utils/constants';
|
||||
import { HTTP_STATUS_UNAUTHORIZED } from '~/lib/utils/http_status';
|
||||
|
@ -114,6 +115,13 @@ export default {
|
|||
return this.userHasApproved && !this.userCanApprove && this.mr.state !== STATUS_MERGED;
|
||||
},
|
||||
approvalText() {
|
||||
// Repeating a text of this to keep i18n easier to do (vs, construcing a compound string)
|
||||
if (this.requireSamlAuthToApprove) {
|
||||
return this.isApproved && this.approvedBy.length > 0
|
||||
? s__('mrWidget|Approve additionally with SAML')
|
||||
: s__('mrWidget|Approve with SAML');
|
||||
}
|
||||
|
||||
return this.isApproved && this.approvedBy.length > 0
|
||||
? s__('mrWidget|Approve additionally')
|
||||
: s__('mrWidget|Approve');
|
||||
|
@ -161,14 +169,20 @@ export default {
|
|||
.join(', ')
|
||||
.concat('.');
|
||||
},
|
||||
requireSamlAuthToApprove() {
|
||||
return this.mr.requireSamlAuthToApprove;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
approve() {
|
||||
if (this.requireSamlAuthToApprove) {
|
||||
this.approveWithSamlAuth();
|
||||
return;
|
||||
}
|
||||
if (this.requirePasswordToApprove) {
|
||||
this.$root.$emit(BV_SHOW_MODAL, this.modalId);
|
||||
return;
|
||||
}
|
||||
|
||||
this.updateApproval(
|
||||
() => this.service.approveMergeRequest(),
|
||||
() =>
|
||||
|
@ -179,6 +193,10 @@ export default {
|
|||
),
|
||||
);
|
||||
},
|
||||
approveWithSamlAuth() {
|
||||
// Intentionally direct to SAML Identity Provider for renewed authorization even if SSO session exists
|
||||
visitUrl(this.mr.samlApprovalPath);
|
||||
},
|
||||
approveWithAuth(data) {
|
||||
this.updateApproval(
|
||||
() => this.service.approveMergeRequestWithAuth(data),
|
||||
|
|
|
@ -35,7 +35,7 @@ To create a new user account with auditor access (or change an existing user):
|
|||
To create a user account with auditor access:
|
||||
|
||||
1. On the left sidebar, at the bottom, select **Admin Area**.
|
||||
1. On the left sidebar, select **Overview > Users**.
|
||||
1. Select **Overview > Users**.
|
||||
1. Create a new user or edit an existing one. Set **Access Level** to **Auditor**.
|
||||
1. If you created a user, select **Create user**. For an existing user, select **Save changes**.
|
||||
|
||||
|
|
|
@ -36,6 +36,174 @@ methods to export or back up your data yourself from GitLab.com.
|
|||
|
||||
Issues are stored in the database, and can't be stored in Git itself.
|
||||
|
||||
## GitLab backup archive creation process
|
||||
|
||||
When working with GitLab backups, you might need to know how GitLab creates backup archives. To create backup archives, GitLab:
|
||||
|
||||
1. If creating an incremental backup, extracts the previous backup archive and read its `backup_information.yml` file.
|
||||
1. Updates or generates the `backup_information.yml` file.
|
||||
1. Runs all backup sub-tasks:
|
||||
- `db` to backup the GitLab PostgreSQL database (not Gitaly Cluster).
|
||||
- `repositories` to back up Git repositories.
|
||||
- `uploads` to back up attachments.
|
||||
- `builds` to back up CI job output logs.
|
||||
- `artifacts` to back up CI job artifacts.
|
||||
- `pages` to back up page content.
|
||||
- `lfs` to back up LFS objects.
|
||||
- `terraform_state` to back up Terraform states.
|
||||
- `registry` to back up container registry images.
|
||||
- `packages` to back up packages.
|
||||
- `ci_secure_files` to back up project-level secure files.
|
||||
1. Archives the backup staging area into a tar file.
|
||||
1. Optional. Uploads the new backup archive to object-storage.
|
||||
1. Cleans up backup staging directory files that are now archived.
|
||||
|
||||
## Backup staging directory
|
||||
|
||||
The backup staging directory is a place to temporarily:
|
||||
|
||||
- Store backup artifacts on disk before the GitLab backup archive is created.
|
||||
- Extract backup archives on disk before restoring a backup or creating an incremental backup.
|
||||
|
||||
This directory is the same directory where completed GitLab backup archives are created. When creating an untarred backup, the backup artifacts are left in this directory and no
|
||||
archive is created.
|
||||
|
||||
Example backup staging directory with untarred backup:
|
||||
|
||||
```plaintext
|
||||
backups/
|
||||
├── 1701728344_2023_12_04_16.7.0-pre_gitlab_backup.tar
|
||||
├── 1701728447_2023_12_04_16.7.0-pre_gitlab_backup.tar
|
||||
├── artifacts.tar.gz
|
||||
├── backup_information.yml
|
||||
├── builds.tar.gz
|
||||
├── ci_secure_files.tar.gz
|
||||
├── db
|
||||
│ ├── ci_database.sql.gz
|
||||
│ └── database.sql.gz
|
||||
├── lfs.tar.gz
|
||||
├── packages.tar.gz
|
||||
├── pages.tar.gz
|
||||
├── repositories
|
||||
│ ├── manifests/
|
||||
│ ├── @hashed/
|
||||
│ └── @snippets/
|
||||
├── terraform_state.tar.gz
|
||||
└── uploads.tar.gz
|
||||
```
|
||||
|
||||
## `backup_information.yml` file
|
||||
|
||||
The `backup_information.yml` file saves all backup inputs that are not included in the backup itself. It includes information such as:
|
||||
|
||||
- The time the backup was created.
|
||||
- The version of GitLab that generated the backup.
|
||||
- Any options that were specified, such as skipped sub-tasks.
|
||||
|
||||
This information is used by some sub-tasks to determine how:
|
||||
|
||||
- To restore.
|
||||
- To link data in the backup with external services (such as server-side repository backups).
|
||||
|
||||
This file is saved into the backup staging directory.
|
||||
|
||||
## Database backups
|
||||
|
||||
Database backups are created and restored by a GitLab backup sub-task called `db`. The database sub-task uses `pg_dump` to create [a SQL dump](https://www.postgresql.org/docs/14/backup-dump.html). The output of `pg_dump` is piped through `gzip` in order to create a compressed SQL file. This file is saved to the backup staging directory.
|
||||
|
||||
## Repository backups
|
||||
|
||||
Repository backups are created and restored by a GitLab backup sub-task called `repositories`. The repositories sub-task uses a Gitaly command
|
||||
[`gitaly-backup`](https://gitlab.com/gitlab-org/gitaly/-/blob/master/doc/gitaly-backup.md) to create Git repository backups:
|
||||
|
||||
- GitLab uses its database to tell `gitaly-backup` which repositories to back up.
|
||||
- `gitaly-backup` then calls a series of RPCs on Gitaly to collect the repository backup data for each repository. This data is streamed into a directory structure in the GitLab backup staging directory.
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box Backup host
|
||||
participant Repositories sub-task
|
||||
participant gitaly-backup
|
||||
end
|
||||
|
||||
Repositories sub-task->>+gitaly-backup: List of repositories
|
||||
|
||||
loop Each repository
|
||||
gitaly-backup->>+Gitaly: ListRefs request
|
||||
Gitaly->>-gitaly-backup: List of Git references
|
||||
|
||||
gitaly-backup->>+Gitaly: CreateBundleFromRefList request
|
||||
Gitaly->>-gitaly-backup: Git bundle file
|
||||
|
||||
gitaly-backup->>+Gitaly: GetCustomHooks request
|
||||
Gitaly->>-gitaly-backup: Custom hooks archive
|
||||
end
|
||||
|
||||
gitaly-backup->>-Repositories sub-task: Success/failure
|
||||
```
|
||||
|
||||
Storages configured to Gitaly Cluster are backed up the same as standalone Gitaly. When Gitaly Cluster receives the RPC calls from `gitaly-backup`, it is responsible for
|
||||
rebuilding its own database. This means that there is no need to backup the Gitaly Cluster database separately. Because backups operate through RPCs, each repository is only backed
|
||||
up once no matter the replication factor.
|
||||
|
||||
### Server-side repository backups
|
||||
|
||||
You can configure repository backups as server-side repository backups. When specified, `gitaly-backup` makes a single RPC call for each repository to create the backup. This RPC
|
||||
does not transmit any repository data. Instead, the RPC triggers the Gitaly node that stores that physical repository to upload the backup data directly to object-storage. Because
|
||||
the data is no longer transmitted through RPCs from Gitaly, server-side backups require much less network transfer and require no disk storage on the machine that is running the
|
||||
backup Rake task. The backups stored on object-storage are linked to the created backup archive by [the backup name](backup_gitlab.md#backup-timestamp).
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
box Backup host
|
||||
participant Repositories sub-task
|
||||
participant gitaly-backup
|
||||
end
|
||||
|
||||
Repositories sub-task->>+gitaly-backup: List of repositories
|
||||
|
||||
loop Each repository
|
||||
gitaly-backup->>+Gitaly: BackupRepository request
|
||||
|
||||
Gitaly->>+Object-storage: Git references file
|
||||
Object-storage->>-Gitaly: Success/failure
|
||||
|
||||
Gitaly->>+Object-storage: Git bundle file
|
||||
Object-storage->>-Gitaly: Success/failure
|
||||
|
||||
Gitaly->>+Object-storage: Custom hooks archive
|
||||
Object-storage->>-Gitaly: Success/failure
|
||||
|
||||
Gitaly->>+Object-storage: Backup manifest file
|
||||
Object-storage->>-Gitaly: Success/failure
|
||||
|
||||
Gitaly->>-gitaly-backup: Success/failure
|
||||
end
|
||||
|
||||
gitaly-backup->>-Repositories sub-task: Success/failure
|
||||
```
|
||||
|
||||
## File backups
|
||||
|
||||
The following GitLab backup sub-tasks back up files:
|
||||
|
||||
- `uploads`
|
||||
- `builds`
|
||||
- `artifacts`
|
||||
- `pages`
|
||||
- `lfs`
|
||||
- `terraform_state`
|
||||
- `registry`
|
||||
- `packages`
|
||||
- `ci_secure_files`
|
||||
|
||||
These file sub-tasks determine a set of files within a directory specific to the task. This set of files is then passed to `tar`
|
||||
to create an archive. This archive is piped (not saved to disk) through `gzip` to save a compressed tar file to the backup staging directory.
|
||||
|
||||
Because backups are created from live instances, the files that tar is trying to archive can sometimes be modified while creating the backup. In this case, an alternate "copy"
|
||||
strategy can be used. When this strategy is used, `rsync` is first used to create a copy of the files to back up. Then, these copies are passed to `tar` as usual. In this case,
|
||||
the machine running the backup Rake task must have enough storage for the copied files and the compressed archive.
|
||||
|
||||
## Related features
|
||||
|
||||
- [Geo](../geo/index.md)
|
||||
|
|
|
@ -1542,50 +1542,3 @@ go_cloud_url = "s3://gitaly-backups?region=minio&endpoint=my.minio.local:8080&di
|
|||
```
|
||||
|
||||
::EndTabs
|
||||
|
||||
## Configure negotiation timeouts
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/5574) in GitLab 16.5.
|
||||
|
||||
Gitaly supports configurable negotiation timeouts.
|
||||
|
||||
Negotiation timeouts can be configured for the `git-upload-pack(1)` and `git-upload-archive(1)`
|
||||
operations, which are invoked by a Gitaly node when you execute the `git fetch` and
|
||||
`git archive --remote` commands respectively. You might need to increase the negotiation timeout:
|
||||
|
||||
- For particularly large repositories.
|
||||
- When performing these commands in parallel.
|
||||
|
||||
These timeouts affect only the [negotiation phase](https://git-scm.com/docs/pack-protocol/2.2.3#_packfile_negotiation) of
|
||||
remote Git operations, not the entire transfer.
|
||||
|
||||
Valid values for timeouts follow the format of [`ParseDuration`](https://pkg.go.dev/time#ParseDuration) in Go.
|
||||
|
||||
How you configure negotiation timeouts depends on the type of installation you have:
|
||||
|
||||
::Tabs
|
||||
|
||||
:::TabTitle Linux package (Omnibus)
|
||||
|
||||
Edit `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
gitaly['configuration'] = {
|
||||
timeout: {
|
||||
upload_pack_negotiation: '10m', # 10 minutes
|
||||
upload_archive_negotiation: '20m', # 20 minutes
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::TabTitle Self-compiled (source)
|
||||
|
||||
Edit `/home/git/gitaly/config.toml`:
|
||||
|
||||
```toml
|
||||
[timeout]
|
||||
upload_pack_negotiation = "10m"
|
||||
upload_archive_negotiation = "20m"
|
||||
```
|
||||
|
||||
::EndTabs
|
||||
|
|
|
@ -6,23 +6,75 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Gitaly timeouts **(FREE SELF)**
|
||||
|
||||
[Gitaly](../gitaly/index.md) timeouts are configurable. The timeouts can be
|
||||
configured to make sure that long-running Gitaly calls don't needlessly take up resources.
|
||||
[Gitaly](../gitaly/index.md) provides two types of configurable timeouts:
|
||||
|
||||
To access Gitaly timeout settings:
|
||||
- Call timeouts, configured by using the GitLab UI.
|
||||
- Negotiation timeouts, configured by using Gitaly configuration files.
|
||||
|
||||
## Configure the call timeouts
|
||||
|
||||
Configure the following call timeouts to make sure that long-running Gitaly calls don't needlessly take up resources. To
|
||||
configure the call timeouts:
|
||||
|
||||
1. On the left sidebar, at the bottom, select **Admin Area**.
|
||||
1. Select **Settings > Preferences**.
|
||||
1. Expand the **Gitaly timeouts** section.
|
||||
1. Set each timeout as required.
|
||||
|
||||
## Available timeouts
|
||||
### Available call timeouts
|
||||
|
||||
The following timeouts are available.
|
||||
Different call timeouts are available for different Gitaly operations.
|
||||
|
||||
| Timeout | Default | Description |
|
||||
|:--------|:-----------|:------------|
|
||||
| Default | 55 seconds | Timeout for most Gitaly calls (not enforced for `git` `fetch` and `push` operations, or Sidekiq jobs). For example, checking if a repository exists on disk. Makes sure that Gitaly calls made within a web request cannot exceed the entire request timeout. It should be shorter than the [worker timeout](../operations/puma.md#change-the-worker-timeout) that can be configured for [Puma](../../install/requirements.md#puma-settings). If a Gitaly call timeout exceeds the worker timeout, the remaining time from the worker timeout is used to avoid having to terminate the worker. |
|
||||
| Fast | 10 seconds | Timeout for fast Gitaly operations used within requests, sometimes multiple times. For example, checking if a repository exists on disk. If fast operations exceed this threshold, there may be a problem with a storage shard. Failing fast can help maintain the stability of the GitLab instance. |
|
||||
| Medium | 30 seconds | Timeout for Gitaly operations that should be fast (possibly within requests) but preferably not used multiple times within a request. For example, loading blobs. Timeout that should be set between Default and Fast. |
|
||||
| Default | 55 seconds | Timeout for most Gitaly calls (not enforced for `git` `fetch` and `push` operations, or Sidekiq jobs). For example, checking if a repository exists on disk. Makes sure that Gitaly calls made in a web request cannot exceed the entire request timeout. It should be shorter than the [worker timeout](../operations/puma.md#change-the-worker-timeout) that can be configured for [Puma](../../install/requirements.md#puma-settings). If a Gitaly call timeout exceeds the worker timeout, the remaining time from the worker timeout is used to avoid having to terminate the worker. |
|
||||
| Fast | 10 seconds | Timeout for fast Gitaly operations used in requests, sometimes multiple times. For example, checking if a repository exists on disk. If fast operations exceed this threshold, there may be a problem with a storage shard. Failing fast can help maintain the stability of the GitLab instance. |
|
||||
| Medium | 30 seconds | Timeout for Gitaly operations that should be fast (possibly in requests) but preferably not used multiple times in a request. For example, loading blobs. Timeout that should be set between Default and Fast. |
|
||||
|
||||
You can also [configure negotiation timeouts](../gitaly/configure_gitaly.md#configure-negotiation-timeouts).
|
||||
## Configure the negotiation timeouts
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/5574) in GitLab 16.5.
|
||||
|
||||
You might need to increase the negotiation timeout:
|
||||
|
||||
- For particularly large repositories.
|
||||
- When performing these commands in parallel.
|
||||
|
||||
You can configure negotiation timeouts for:
|
||||
|
||||
- `git-upload-pack(1)`, which is invoked by a Gitaly node when you execute `git fetch`.
|
||||
- `git-upload-archive(1)`, which is invoked by a Gitaly node when you execute `git archive --remote`.
|
||||
|
||||
To configure these timeouts:
|
||||
|
||||
::Tabs
|
||||
|
||||
:::TabTitle Linux package (Omnibus)
|
||||
|
||||
Edit `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
gitaly['configuration'] = {
|
||||
timeout: {
|
||||
upload_pack_negotiation: '10m', # 10 minutes
|
||||
upload_archive_negotiation: '20m', # 20 minutes
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
:::TabTitle Self-compiled (source)
|
||||
|
||||
Edit `/home/git/gitaly/config.toml`:
|
||||
|
||||
```toml
|
||||
[timeout]
|
||||
upload_pack_negotiation = "10m"
|
||||
upload_archive_negotiation = "20m"
|
||||
```
|
||||
|
||||
::EndTabs
|
||||
|
||||
For the values, use the format of [`ParseDuration`](https://pkg.go.dev/time#ParseDuration) in Go.
|
||||
|
||||
These timeouts affect only the [negotiation phase](https://git-scm.com/docs/pack-protocol/2.2.3#_packfile_negotiation) of
|
||||
remote Git operations, not the entire transfer.
|
||||
|
|
|
@ -15,5 +15,5 @@ the following snippet in the rails console.
|
|||
|
||||
```ruby
|
||||
u = User.find(1)
|
||||
Project.last(100).each { |p| p.set_timestamps_for_create && p.add_maintainer(u, current_user: u) } # Change 100 to whatever number of projects you need access to
|
||||
Project.last(100).each { |p| p.send(:set_timestamps_for_create) && p.add_maintainer(u, current_user: u) } # Change 100 to whatever number of projects you need access to
|
||||
```
|
||||
|
|
|
@ -188,8 +188,8 @@ To export a report of merge request compliance violations for projects in a grou
|
|||
|
||||
1. On the left sidebar, select **Search or go to** and find your group.
|
||||
1. On the left sidebar, select **Secure > Compliance center**.
|
||||
1. On the page, select the **Violations** tab.
|
||||
1. On the Violations tab, select the **Export full report as CSV** action in the top right corner
|
||||
1. Select the **Export** action in the top right corner
|
||||
1. Select **Export violations report**
|
||||
|
||||
A report is compiled and delivered to your email inbox as an attachment.
|
||||
|
||||
|
@ -235,7 +235,8 @@ To generate the Chain of Custody report:
|
|||
|
||||
1. On the left sidebar, select **Search or go to** and find your group.
|
||||
1. On the left sidebar, select **Secure > Compliance center**.
|
||||
1. Select **List of all merge commits**.
|
||||
1. Select the **Export** action in the top right corner
|
||||
1. Select **Export chain of custody report**
|
||||
|
||||
Depending on your version of GitLab, the Chain of Custody report is either sent through email or available for download.
|
||||
|
||||
|
@ -251,9 +252,9 @@ To generate a commit-specific Chain of Custody report:
|
|||
|
||||
1. On the left sidebar, select **Search or go to** and find your group.
|
||||
1. On the left sidebar, select **Secure > Compliance center**.
|
||||
1. At the top of the compliance report, to the right of **List of all commits**, select the down arrow
|
||||
(**{chevron-lg-down}**).
|
||||
1. Enter the commit SHA, and then select **Export commit custody report**.
|
||||
1. Select the **Export** action in the top right corner
|
||||
1. Select **Export custody report of a specific commit**
|
||||
1. Enter the commit SHA, and then select **Export custody report**.
|
||||
|
||||
Depending on your version of GitLab, the Chain of Custody report is either sent through email or available for download.
|
||||
|
||||
|
@ -358,8 +359,8 @@ To export a report of compliance frameworks on projects in a group:
|
|||
|
||||
1. On the left sidebar, select **Search or go to** and find your group.
|
||||
1. On the left sidebar, select **Secure > Compliance center**.
|
||||
1. On the page, select the **Projects** tab.
|
||||
1. On the Frameworks tab, select the **Export as CSV** action in the top right corner
|
||||
1. Select the **Export** action in the top right corner
|
||||
1. Select **Export list of project frameworks**
|
||||
|
||||
A report is compiled and delivered to your email inbox as an attachment.
|
||||
|
||||
|
|
|
@ -189,7 +189,7 @@ You might experience a `fatal: the remote end hung up unexpectedly` error when a
|
|||
- The same large repository in parallel.
|
||||
|
||||
You can attempt to mitigate this issue by increasing the default negotiation timeout values. For more information, see
|
||||
[Configure negotiation timeouts](../../../../administration/gitaly/configure_gitaly.md#configure-negotiation-timeouts).
|
||||
[Configure the negotiation timeouts](../../../../administration/settings/gitaly_timeouts.md#configure-the-negotiation-timeouts).
|
||||
|
||||
## Optimize your repository
|
||||
|
||||
|
|
|
@ -1439,9 +1439,6 @@ msgstr ""
|
|||
msgid "(leave blank if you don't want to change it)"
|
||||
msgstr ""
|
||||
|
||||
msgid "(max size 15 MB)"
|
||||
msgstr ""
|
||||
|
||||
msgid "(no user)"
|
||||
msgstr ""
|
||||
|
||||
|
@ -6111,6 +6108,9 @@ msgstr ""
|
|||
msgid "Approval options"
|
||||
msgstr ""
|
||||
|
||||
msgid "Approval rejected."
|
||||
msgstr ""
|
||||
|
||||
msgid "Approval rules"
|
||||
msgstr ""
|
||||
|
||||
|
@ -6272,7 +6272,7 @@ msgstr ""
|
|||
msgid "ApprovalSettings|Remove approvals by Code Owners if their files changed"
|
||||
msgstr ""
|
||||
|
||||
msgid "ApprovalSettings|Require user password to approve"
|
||||
msgid "ApprovalSettings|Require user re-authentication (password or SAML) to approve"
|
||||
msgstr ""
|
||||
|
||||
msgid "ApprovalSettings|There was an error loading merge request approval settings."
|
||||
|
@ -12429,13 +12429,34 @@ msgstr ""
|
|||
msgid "Completed in %{duration_seconds} seconds (%{relative_time})"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compliance Center|Export full report as CSV"
|
||||
msgid "Compliance Center Export|(limited to 15 MB)"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compliance Center|Export merge request violations as CSV. You will be emailed after the export is processed."
|
||||
msgid "Compliance Center Export|Example: 2dc6aa3"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compliance Center|Export projects as CSV. You will be emailed after the export is processed."
|
||||
msgid "Compliance Center Export|Export as CSV"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compliance Center Export|Export chain of custody report"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compliance Center Export|Export custody report"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compliance Center Export|Export custody report of a specific commit"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compliance Center Export|Export list of project frameworks"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compliance Center Export|Export violations report"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compliance Center Export|Invalid hash"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compliance Center Export|Send email of the chosen report as CSV"
|
||||
msgstr ""
|
||||
|
||||
msgid "Compliance Center|Frameworks"
|
||||
|
@ -19975,9 +19996,6 @@ msgstr ""
|
|||
msgid "Export as CSV"
|
||||
msgstr ""
|
||||
|
||||
msgid "Export commit custody report"
|
||||
msgstr ""
|
||||
|
||||
msgid "Export group"
|
||||
msgstr ""
|
||||
|
||||
|
@ -25935,9 +25953,6 @@ msgstr ""
|
|||
msgid "Invalid format selected"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid hash"
|
||||
msgstr ""
|
||||
|
||||
msgid "Invalid input, please avoid emoji"
|
||||
msgstr ""
|
||||
|
||||
|
@ -28695,9 +28710,6 @@ msgstr ""
|
|||
msgid "List available repositories"
|
||||
msgstr ""
|
||||
|
||||
msgid "List of all commits"
|
||||
msgstr ""
|
||||
|
||||
msgid "List of suitable GCP locations"
|
||||
msgstr ""
|
||||
|
||||
|
@ -57854,6 +57866,12 @@ msgstr ""
|
|||
msgid "mrWidget|Approve additionally"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Approve additionally with SAML"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Approve with SAML"
|
||||
msgstr ""
|
||||
|
||||
msgid "mrWidget|Approved by"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -2,7 +2,13 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Projects::MergeRequestsController, '(JavaScript fixtures)', type: :controller do
|
||||
RSpec
|
||||
.describe(
|
||||
Projects::MergeRequestsController,
|
||||
'(JavaScript fixtures)',
|
||||
type: :controller,
|
||||
feature_category: :code_review_workflow
|
||||
) do
|
||||
include JavaScriptFixturesHelpers
|
||||
|
||||
let(:namespace) { create(:namespace, name: 'frontend-fixtures') }
|
||||
|
|
|
@ -4,6 +4,7 @@ import { GlButton, GlSprintf } from '@gitlab/ui';
|
|||
import { shallowMount } from '@vue/test-utils';
|
||||
import { createMockSubscription as createMockApolloSubscription } from 'mock-apollo-client';
|
||||
import approvedByCurrentUser from 'test_fixtures/graphql/merge_requests/approvals/approvals.query.graphql.json';
|
||||
import { visitUrl } from '~/lib/utils/url_utility';
|
||||
import createMockApollo from 'helpers/mock_apollo_helper';
|
||||
import waitForPromises from 'helpers/wait_for_promises';
|
||||
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
|
||||
|
@ -28,6 +29,10 @@ jest.mock('~/alert', () => ({
|
|||
dismiss: mockAlertDismiss,
|
||||
})),
|
||||
}));
|
||||
jest.mock('~/lib/utils/url_utility', () => ({
|
||||
...jest.requireActual('~/lib/utils/url_utility'),
|
||||
visitUrl: jest.fn(),
|
||||
}));
|
||||
|
||||
const TEST_HELP_PATH = 'help/path';
|
||||
const testApprovedBy = () => [1, 7, 10].map((id) => ({ id }));
|
||||
|
@ -113,6 +118,7 @@ describe('MRWidget approvals', () => {
|
|||
targetProjectFullPath: 'gitlab-org/gitlab',
|
||||
id: 1,
|
||||
iid: '1',
|
||||
requireSamlAuthToApprove: false,
|
||||
};
|
||||
|
||||
jest.spyOn(eventHub, '$emit').mockImplementation(() => {});
|
||||
|
@ -172,6 +178,22 @@ describe('MRWidget approvals', () => {
|
|||
category: 'primary',
|
||||
});
|
||||
});
|
||||
|
||||
describe('with SAML auth requried for approval', () => {
|
||||
beforeEach(async () => {
|
||||
const response = createCanApproveResponse();
|
||||
mr.requireSamlAuthToApprove = true;
|
||||
createComponent({}, { query: response });
|
||||
await waitForPromises();
|
||||
});
|
||||
it('approve action is rendered with correct text', () => {
|
||||
expect(findActionData()).toEqual({
|
||||
variant: 'confirm',
|
||||
text: 'Approve with SAML',
|
||||
category: 'primary',
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('and MR is approved', () => {
|
||||
|
@ -194,6 +216,25 @@ describe('MRWidget approvals', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('with approvers, with SAML auth requried for approval', () => {
|
||||
beforeEach(async () => {
|
||||
canApproveResponse.data.project.mergeRequest.approvedBy.nodes =
|
||||
approvedByCurrentUser.data.project.mergeRequest.approvedBy.nodes;
|
||||
canApproveResponse.data.project.mergeRequest.approvedBy.nodes[0].id = 69;
|
||||
mr.requireSamlAuthToApprove = true;
|
||||
createComponent({}, { query: canApproveResponse });
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('approve additionally action is rendered with correct text', () => {
|
||||
expect(findActionData()).toEqual({
|
||||
variant: 'confirm',
|
||||
text: 'Approve additionally with SAML',
|
||||
category: 'secondary',
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('with approvers', () => {
|
||||
beforeEach(async () => {
|
||||
canApproveResponse.data.project.mergeRequest.approvedBy.nodes =
|
||||
|
@ -215,6 +256,25 @@ describe('MRWidget approvals', () => {
|
|||
});
|
||||
});
|
||||
|
||||
describe('when SAML auth is required and user clicks Approve with SAML', () => {
|
||||
const fakeGroupSamlPath = '/example_group_saml';
|
||||
|
||||
beforeEach(async () => {
|
||||
mr.requireSamlAuthToApprove = true;
|
||||
mr.samlApprovalPath = fakeGroupSamlPath;
|
||||
|
||||
createComponent({}, { query: createCanApproveResponse() });
|
||||
await waitForPromises();
|
||||
});
|
||||
|
||||
it('redirects the user to the group SAML path', async () => {
|
||||
const action = findAction();
|
||||
action.vm.$emit('click');
|
||||
await nextTick();
|
||||
expect(visitUrl).toHaveBeenCalledWith(fakeGroupSamlPath);
|
||||
});
|
||||
});
|
||||
|
||||
describe('when approve action is clicked', () => {
|
||||
beforeEach(async () => {
|
||||
createComponent({}, { query: canApproveResponse });
|
||||
|
|
|
@ -16,7 +16,7 @@ RSpec.describe Gitlab::Utils::FileInfo, feature_category: :shared do
|
|||
|
||||
describe '.linked?' do
|
||||
it 'raises an error when file does not exist' do
|
||||
expect { subject.linked?('foo') }.to raise_error(Errno::ENOENT)
|
||||
expect { subject.linked?("#{tmpdir}/foo") }.to raise_error(Errno::ENOENT)
|
||||
end
|
||||
|
||||
shared_examples 'identifies a linked file' do
|
||||
|
@ -56,7 +56,7 @@ RSpec.describe Gitlab::Utils::FileInfo, feature_category: :shared do
|
|||
|
||||
describe '.shares_hard_link?' do
|
||||
it 'raises an error when file does not exist' do
|
||||
expect { subject.shares_hard_link?('foo') }.to raise_error(Errno::ENOENT)
|
||||
expect { subject.shares_hard_link?("#{tmpdir}/foo") }.to raise_error(Errno::ENOENT)
|
||||
end
|
||||
|
||||
shared_examples 'identifies a file that shares a hard link' do
|
||||
|
|
|
@ -8,8 +8,6 @@ RSpec.describe API::MergeRequestApprovals, feature_category: :source_code_manage
|
|||
let_it_be(:bot) { create(:user, :project_bot) }
|
||||
let_it_be(:project) { create(:project, :public, :repository, creator: user, namespace: user.namespace) }
|
||||
let_it_be(:approver) { create :user }
|
||||
let_it_be(:group) { create :group }
|
||||
|
||||
let(:merge_request) { create(:merge_request, :simple, author: user, source_project: project) }
|
||||
|
||||
describe 'GET :id/merge_requests/:merge_request_iid/approvals' do
|
||||
|
|
|
@ -13,6 +13,7 @@ RSpec.describe MergeRequests::ApprovalService, feature_category: :code_review_wo
|
|||
|
||||
before do
|
||||
project.add_developer(user)
|
||||
stub_feature_flags ff_require_saml_auth_to_approve: false
|
||||
end
|
||||
|
||||
context 'with invalid approval' do
|
||||
|
|
Loading…
Reference in New Issue