diff options
Diffstat (limited to 'doc')
484 files changed, 19129 insertions, 9029 deletions
diff --git a/doc/.vale/gitlab/Acronyms.yml b/doc/.vale/gitlab/Acronyms.yml index 2c28da972da..481da94c627 100644 --- a/doc/.vale/gitlab/Acronyms.yml +++ b/doc/.vale/gitlab/Acronyms.yml @@ -58,6 +58,7 @@ exceptions: - GPL - GUI - HAML + - HEAD - HIPAA - HTML - HTTP @@ -90,6 +91,7 @@ exceptions: - NGINX - NOTE - NPM + - NTP - ONLY - OWASP - PAT diff --git a/doc/.vale/gitlab/Admin.yml b/doc/.vale/gitlab/Admin.yml index 6d01882138a..96325ad2ef4 100644 --- a/doc/.vale/gitlab/Admin.yml +++ b/doc/.vale/gitlab/Admin.yml @@ -1,7 +1,7 @@ --- # Warning: gitlab.Admin # -# You should not use "admin", but "Admin Area" is OK. +# Checks for "admin" and recommends using the full word instead. "Admin Area" is OK. # # For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles extends: substitution diff --git a/doc/.vale/gitlab/AlertBoxStyle.yml b/doc/.vale/gitlab/AlertBoxStyle.yml index bdf66236ef2..92c3a16cab8 100644 --- a/doc/.vale/gitlab/AlertBoxStyle.yml +++ b/doc/.vale/gitlab/AlertBoxStyle.yml @@ -1,9 +1,8 @@ --- # Error: gitlab.AlertBoxStyle # -# Makes sure alert boxes are used with block quotes. +# Makes sure alert boxes are used with block quotes. Checks for 3 formatting issues: # -# Checks for 3 formatting issues: # - Alert boxes inside a block quote (">") # - Alert boxes with the note text on the same line # - Alert boxes using words other than "NOTE" or "WARNING" @@ -17,5 +16,5 @@ nonword: true scope: raw raw: - '(\n *\> *(?:NOTE|WARNING)|' - - '\n(NOTE):[^\n]|' # Adding "WARNING" here causes a false positive - - '\n *(?:> )?\**(Note|note|TIP|Tip|tip|CAUTION|Caution|caution|DANGER|Danger|danger|warning):.*)' ## Adding "Warning" here causes a false positive + - '\n\n(NOTE|WARNING):[^\n]|' + - '\n\n *(?:> )?\**(Note|note|TIP|Tip|tip|CAUTION|Caution|caution|DANGER|Danger|danger|Warning|warning):.*)' diff --git a/doc/.vale/gitlab/British.yml b/doc/.vale/gitlab/British.yml index 65842ad7aa5..152723ead26 100644 --- a/doc/.vale/gitlab/British.yml +++ b/doc/.vale/gitlab/British.yml @@ -1,7 +1,7 @@ --- # Error: gitlab.British # -# Checks that US spelling is used over British spelling. +# Checks that US spelling is used instead of British spelling. # # For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles extends: substitution diff --git a/doc/.vale/gitlab/CurlStringsQuoted.yml b/doc/.vale/gitlab/CurlStringsQuoted.yml index e9fbabf5ffc..c0bc8c18c93 100644 --- a/doc/.vale/gitlab/CurlStringsQuoted.yml +++ b/doc/.vale/gitlab/CurlStringsQuoted.yml @@ -1,7 +1,7 @@ --- -# Warning: gitlab.CurlStringsQuoted +# Error: gitlab.CurlStringsQuoted # -# Ensures all code blocks using curl quote any URL strings. +# Ensures all code blocks using `curl` wrap URL strings in quotation marks. # # For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles extends: existence diff --git a/doc/.vale/gitlab/FutureTense.yml b/doc/.vale/gitlab/FutureTense.yml index d7001d57899..fc414a9c0fd 100644 --- a/doc/.vale/gitlab/FutureTense.yml +++ b/doc/.vale/gitlab/FutureTense.yml @@ -1,8 +1,7 @@ --- # Suggestion: gitlab.FutureTense # -# Checks for use of future tense in sentences. Present tense is preferred as -# much as possible. +# Checks for use of future tense in sentences. Present tense is strongly preferred. # # For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles extends: existence diff --git a/doc/.vale/gitlab/OxfordComma.yml b/doc/.vale/gitlab/OxfordComma.yml index 0425d9e1dd0..1716145b26a 100644 --- a/doc/.vale/gitlab/OxfordComma.yml +++ b/doc/.vale/gitlab/OxfordComma.yml @@ -1,8 +1,7 @@ --- # Warning: gitlab.OxfordComma # -# Checks for the lack of an Oxford comma. In some cases, will catch overly -# complex sentence structures with lots of commas. +# Checks for the lack of an Oxford comma. In some cases, will catch overly complex sentence structures with lots of commas. # # For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles extends: existence diff --git a/doc/.vale/gitlab/ReferenceLinks.yml b/doc/.vale/gitlab/ReferenceLinks.yml index 0df1f359107..160ed2e8e14 100644 --- a/doc/.vale/gitlab/ReferenceLinks.yml +++ b/doc/.vale/gitlab/ReferenceLinks.yml @@ -1,7 +1,7 @@ --- # Error: gitlab.ReferenceLinks # -# Checks for the presence of reference-style links that must be inline. +# Checks for reference-style links that should be converted to inline links. # # For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles extends: existence diff --git a/doc/.vale/gitlab/SentenceSpacing.yml b/doc/.vale/gitlab/SentenceSpacing.yml index 884d4b57508..0288abe834f 100644 --- a/doc/.vale/gitlab/SentenceSpacing.yml +++ b/doc/.vale/gitlab/SentenceSpacing.yml @@ -1,10 +1,7 @@ --- # Error: gitlab.SentenceSpacing # -# Checks for the following in common content scenarios: -# -# - No spaces. -# - More than one space. +# Checks for incorrect spacing (no spaces, or more than one space) around punctuation. # # For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles extends: existence diff --git a/doc/.vale/gitlab/Spelling.yml b/doc/.vale/gitlab/Spelling.yml index 602b7cd11e6..4ebaf7bfb70 100644 --- a/doc/.vale/gitlab/Spelling.yml +++ b/doc/.vale/gitlab/Spelling.yml @@ -1,8 +1,7 @@ --- # Warning: gitlab.Spelling # -# Checks for possible spelling mistakes in content, not code. May find false positives -# due to links using angle brackets: <https://example.com>. These can be ignored. +# Checks for possible spelling mistakes in content, not code. Results from links using angle brackets (<https://example.com>) should be corrected. # # If a word is flagged as a spelling mistake incorrectly, such as a product name, # you can submit an MR to update `spelling-exceptions.txt` with the missing word. diff --git a/doc/.vale/gitlab/SubstitutionSuggestions.yml b/doc/.vale/gitlab/SubstitutionSuggestions.yml index 82e3e789864..ab6658f0943 100644 --- a/doc/.vale/gitlab/SubstitutionSuggestions.yml +++ b/doc/.vale/gitlab/SubstitutionSuggestions.yml @@ -1,8 +1,8 @@ --- # Suggestion: gitlab.SubstitutionSuggestions # -# Suggests better options for frequently misused terms at GitLab that are -# often - but not always - incorrect. +# Suggests better options for frequently misused terms that are often - but not always - incorrect. +# SubstitutionWarning.yml and Substitutions.yml also exist. # # For a list of all options, see https://errata-ai.github.io/vale/styles/ extends: substitution @@ -13,7 +13,7 @@ ignorecase: true swap: active user: '"billable user"' active users: '"billable users"' - docs: documentation + docs: '"documentation"' once that: '"after that"' once the: '"after the"' once you: '"after you"' diff --git a/doc/.vale/gitlab/SubstitutionWarning.yml b/doc/.vale/gitlab/SubstitutionWarning.yml index ed0f8b498fe..61fd0148fd8 100644 --- a/doc/.vale/gitlab/SubstitutionWarning.yml +++ b/doc/.vale/gitlab/SubstitutionWarning.yml @@ -1,8 +1,8 @@ --- # Warning: gitlab.SubstitutionWarning # -# Warns against using common shorthand for terms. -# For substitutions flagged as errors, see Substitutions.yml +# Checks for misused terms or common shorthand that should never be used at GitLab, but can't be flagged as errors. +# Substitutions.yml and SubstitionSuggestions.yml also exist. # # For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles extends: substitution diff --git a/doc/.vale/gitlab/Substitutions.yml b/doc/.vale/gitlab/Substitutions.yml index 0a56524e3f5..987785c7a22 100644 --- a/doc/.vale/gitlab/Substitutions.yml +++ b/doc/.vale/gitlab/Substitutions.yml @@ -1,8 +1,8 @@ --- # Error: gitlab.Substitutions # -# Checks for use of some of the top misused terms at GitLab. -# For substitutions only flagged as warnings, see SubstitutionWarning.yml +# Checks for misused terms that should never be used at GitLab. +# SubstitutionWarning.yml and SubstitionSuggestions.yml also exist. # # For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles extends: substitution diff --git a/doc/.vale/gitlab/spelling-exceptions.txt b/doc/.vale/gitlab/spelling-exceptions.txt index 3d8e9b1ef72..6ce0ced52b3 100644 --- a/doc/.vale/gitlab/spelling-exceptions.txt +++ b/doc/.vale/gitlab/spelling-exceptions.txt @@ -45,6 +45,7 @@ backtraces backtracing badging Bamboo +Bazel Bitbucket blockquote blockquoted @@ -94,6 +95,7 @@ crosslinking crosslinks Crossplane CrowdIn +CSV Dangerfile datetime Debian diff --git a/doc/administration/audit_events.md b/doc/administration/audit_events.md index 7436661920a..27f6bbcd028 100644 --- a/doc/administration/audit_events.md +++ b/doc/administration/audit_events.md @@ -103,6 +103,8 @@ From there, you can see the following actions: Project events can also be accessed via the [Project Audit Events API](../api/audit_events.md#project-audit-events). +Project event queries are limited to a maximum of 30 days. + ### Instance events **(PREMIUM ONLY)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2336) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.3. diff --git a/doc/administration/auth/jwt.md b/doc/administration/auth/jwt.md index 448922230e7..59d00265a1b 100644 --- a/doc/administration/auth/jwt.md +++ b/doc/administration/auth/jwt.md @@ -38,7 +38,7 @@ JWT will provide you with a secret key for you to use. algorithm: 'HS256', # Supported algorithms: 'RS256', 'RS384', 'RS512', 'ES256', 'ES384', 'ES512', 'HS256', 'HS384', 'HS512' uid_claim: 'email', required_claims: ['name', 'email'], - info_maps: { name: 'name', email: 'email' }, + info_map: { name: 'name', email: 'email' }, auth_url: 'https://example.com/', valid_within: 3600 # 1 hour } diff --git a/doc/administration/auth/ldap/google_secure_ldap.md b/doc/administration/auth/ldap/google_secure_ldap.md index dcfb77f277e..6fecf74d935 100644 --- a/doc/administration/auth/ldap/google_secure_ldap.md +++ b/doc/administration/auth/ldap/google_secure_ldap.md @@ -20,7 +20,7 @@ The steps below cover: ## Configuring Google LDAP client -1. Navigate to <https://admin.google.com/Dashboard> and sign in as a GSuite domain administrator. +1. Navigate to <https://admin.google.com/Dashboard> and sign in as a Google Workspace domain administrator. 1. Go to **Apps > LDAP > Add Client**. diff --git a/doc/administration/auth/ldap/index.md b/doc/administration/auth/ldap/index.md index 4dedaba3754..de0f123acf1 100644 --- a/doc/administration/auth/ldap/index.md +++ b/doc/administration/auth/ldap/index.md @@ -201,9 +201,9 @@ LDAP attributes that GitLab uses to create an account for the LDAP user. The spe | ------- | ----------- | -------- | -------- | | `username` | The username is used in paths for the user's own projects (like `gitlab.example.com/username/project`) and when mentioning them in issues, merge request and comments (like `@username`). If the attribute specified for `username` contains an email address, the GitLab username is part of the email address before the `@`. | no | `['uid', 'userid', 'sAMAccountName']` | | `email` | LDAP attribute for user email. | no | `['mail', 'email', 'userPrincipalName']` | -| `name` | LDAP attribute for user display name. If no full name could be found at the attribute specified for `name`, the full name is determined using the attributes specified for `first_name` and `last_name`. | no | `'cn'` or `'displayName'` | -| `first_name` | LDAP attribute for user first name. | no | `'givenName'` | -| `last_name` | LDAP attribute for user last name. | no | `'sn'` | +| `name` | LDAP attribute for user display name. If `name` is blank, the full name is taken from the `first_name` and `last_name`. | no | Attributes `'cn'`, or `'displayName'` commonly carry full names. Alternatively, you can force the use of `first_name` and `last_name` by specifying an absent attribute such as `'somethingNonExistent'`. | +| `first_name` | LDAP attribute for user first name. Used when the attribute configured for `name` does not exist. | no | `'givenName'` | +| `last_name` | LDAP attribute for user last name. Used when the attribute configured for `name` does not exist. | no | `'sn'` | ### LDAP Sync Configuration Settings **(STARTER ONLY)** diff --git a/doc/administration/compliance.md b/doc/administration/compliance.md index 85b72d7b18f..6079e838ac6 100644 --- a/doc/administration/compliance.md +++ b/doc/administration/compliance.md @@ -13,17 +13,17 @@ documentation. The [security features](../security/README.md) in GitLab may also help you meet relevant compliance standards. -|Feature |GitLab tier |GitLab.com | -| ---------| :--------: | :-------: | -|**[Restrict SSH Keys](../security/ssh_keys_restrictions.md)**<br>Control the technology and key length of SSH keys used to access GitLab|Core+|| -|**[Granular user roles and flexible permissions](../user/permissions.md)**<br>Manage access and permissions with five different user roles and settings for external users. Set permissions according to people's role, rather than either read or write access to a repository. Don't share the source code with people that only need access to the issue tracker.|Core+|✓| -|**[Enforce TOS acceptance](../user/admin_area/settings/terms.md)**<br>Enforce your users accepting new terms of service by blocking GitLab traffic.|Core+|| -|**[Email all users of a project, group, or entire server](../tools/email.md)**<br>An admin can email groups of users based on project or group membership, or email everyone using the GitLab instance. This is great for scheduled maintenance or upgrades.|Starter+|| -|**[Omnibus package supports log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-forwarding)**<br>Forward your logs to a central system.|Starter+|| -|**[Lock project membership to group](../user/group/index.md#member-lock)**<br>Group owners can prevent new members from being added to projects within a group.|Starter+|✓| -|**[LDAP group sync](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition gives admins the ability to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your product, not configuring your tools.|Starter+|| -|**[LDAP group sync filters](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition Premium gives more flexibility to synchronize with LDAP based on filters, meaning you can leverage LDAP attributes to map GitLab permissions.|Premium+|| -|**[Audit events](audit_events.md)**<br>To maintain the integrity of your code, GitLab Enterprise Edition Premium gives admins the ability to view any modifications made within the GitLab server in an advanced audit events system, so you can control, analyze, and track every change.|Premium+|| -|**[Auditor users](auditor_users.md)**<br>Auditor users are users who are given read-only access to all projects, groups, and other resources on the GitLab instance.|Premium+|| -|**[Credentials inventory](../user/admin_area/credentials_inventory.md)**<br>With a credentials inventory, GitLab administrators can keep track of the credentials used by all of the users in their GitLab instance. |Ultimate|| -|**Separation of Duties using [Protected branches](../user/project/protected_branches.md#protected-branches-approval-by-code-owners) and [custom CI Configuration Paths](../ci/pipelines/settings.md#custom-ci-configuration-path)**<br> GitLab Silver and Premium users can leverage the GitLab cross-project YAML configurations to define deployers of code and developers of code. View the [Separation of Duties Deploy Project](https://gitlab.com/guided-explorations/separation-of-duties-deploy/blob/master/README.md) and [Separation of Duties Project](https://gitlab.com/guided-explorations/separation-of-duties/blob/master/README.md) to see how to use this set up to define these roles.|Premium+|| +|Feature |GitLab tier |GitLab.com | Product level | +| ---------| :--------: | :-------: | :-----------: | +|**[Restrict SSH Keys](../security/ssh_keys_restrictions.md)**<br>Control the technology and key length of SSH keys used to access GitLab|Core+||Instance| +|**[Granular user roles and flexible permissions](../user/permissions.md)**<br>Manage access and permissions with five different user roles and settings for external users. Set permissions according to people's role, rather than either read or write access to a repository. Don't share the source code with people that only need access to the issue tracker.|Core+|✓|Instance, Group, Project| +|**[Enforce TOS acceptance](../user/admin_area/settings/terms.md)**<br>Enforce your users accepting new terms of service by blocking GitLab traffic.|Core+||Instance| +|**[Email all users of a project, group, or entire server](../tools/email.md)**<br>An admin can email groups of users based on project or group membership, or email everyone using the GitLab instance. This is great for scheduled maintenance or upgrades.|Starter+|||Instance +|**[Omnibus package supports log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-forwarding)**<br>Forward your logs to a central system.|Starter+||Instance| +|**[Lock project membership to group](../user/group/index.md#member-lock)**<br>Group owners can prevent new members from being added to projects within a group.|Starter+|✓|Group| +|**[LDAP group sync](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition gives admins the ability to automatically sync groups and manage SSH keys, permissions, and authentication, so you can focus on building your product, not configuring your tools.|Starter+||Instance| +|**[LDAP group sync filters](auth/ldap/index.md#group-sync)**<br>GitLab Enterprise Edition Premium gives more flexibility to synchronize with LDAP based on filters, meaning you can leverage LDAP attributes to map GitLab permissions.|Premium+||Instance| +|**[Audit events](audit_events.md)**<br>To maintain the integrity of your code, GitLab Enterprise Edition Premium gives admins the ability to view any modifications made within the GitLab server in an advanced audit events system, so you can control, analyze, and track every change.|Premium+|✓|Instance, Group, Project| +|**[Auditor users](auditor_users.md)**<br>Auditor users are users who are given read-only access to all projects, groups, and other resources on the GitLab instance.|Premium+||Instance| +|**[Credentials inventory](../user/admin_area/credentials_inventory.md)**<br>With a credentials inventory, GitLab administrators can keep track of the credentials used by all of the users in their GitLab instance. |Ultimate||Instance| +|**Separation of Duties using [Protected branches](../user/project/protected_branches.md#protected-branches-approval-by-code-owners) and [custom CI Configuration Paths](../ci/pipelines/settings.md#custom-ci-configuration-path)**<br> GitLab Silver and Premium users can leverage the GitLab cross-project YAML configurations to define deployers of code and developers of code. View the [Separation of Duties Deploy Project](https://gitlab.com/guided-explorations/separation-of-duties-deploy/blob/master/README.md) and [Separation of Duties Project](https://gitlab.com/guided-explorations/separation-of-duties/blob/master/README.md) to see how to use this set up to define these roles.|Premium+|✓|Project| diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md index be84b260127..2b0a3e2f114 100644 --- a/doc/administration/geo/disaster_recovery/index.md +++ b/doc/administration/geo/disaster_recovery/index.md @@ -15,7 +15,7 @@ See [Geo limitations](../index.md#limitations) for more information. WARNING: Disaster recovery for multi-secondary configurations is in **Alpha**. -For the latest updates, check the [Disaster Recovery epic for complete maturity](https://gitlab.com/groups/gitlab-org/-/epics/590). +For the latest updates, check the [Disaster Recovery epic for complete maturity](https://gitlab.com/groups/gitlab-org/-/epics/3574). Multi-secondary configurations require the complete re-synchronization and re-configuration of all non-promoted secondaries and will cause downtime. @@ -181,7 +181,7 @@ secondary. If the node is paused, be sure to resume before promoting. This issue has been fixed in GitLab 13.4 and later. WARNING: - If the secondary node [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs +If the secondary node [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs a point-in-time recovery to the last known state. Data that was created on the primary while the secondary was paused will be lost. @@ -220,6 +220,75 @@ Data that was created on the primary while the secondary was paused will be lost previously for the **secondary**. 1. Success! The **secondary** has now been promoted to **primary**. +#### Promoting a **secondary** node with a Patroni standby cluster + +The `gitlab-ctl promote-to-primary-node` command cannot be used yet in +conjunction with a Patroni standby cluster, as it can only +perform changes on a **secondary** with only a single machine. Instead, you must +do this manually. + +WARNING: +In GitLab 13.2 and 13.3, promoting a secondary node to a primary while the +secondary is paused fails. Do not pause replication before promoting a +secondary. If the node is paused, be sure to resume before promoting. This +issue has been fixed in GitLab 13.4 and later. + +WARNING: +If the secondary node [has been paused](../../geo/index.md#pausing-and-resuming-replication), this performs +a point-in-time recovery to the last known state. +Data that was created on the primary while the secondary was paused will be lost. + +1. SSH in to the Standby Leader database node in the **secondary** and trigger PostgreSQL to + promote to read-write: + + ```shell + sudo gitlab-ctl promote-db + ``` + +1. Disable Patroni auto-failover: + + ```shell + sudo gitlab-ctl patroni pause + ``` + +1. Edit `/etc/gitlab/gitlab.rb` on every application and Sidekiq nodes in the secondary to reflect its new status as primary by removing any lines that enabled the `geo_secondary_role`: + + ```ruby + ## In pre-11.5 documentation, the role was enabled as follows. Remove this line. + geo_secondary_role['enable'] = true + + ## In 11.5+ documentation, the role was enabled as follows. Remove this line. + roles ['geo_secondary_role'] + ``` + +1. Edit `/etc/gitlab/gitlab.rb` on every Patroni node in the secondary to disable the standby cluster: + + ```ruby + patroni['standby_cluster']['enable'] = false + ``` + +1. Reconfigure GitLab on each machine for the changes to take effect: + + ```shell + sudo gitlab-ctl reconfigure + ``` + +1. Resume Patroni auto-failover: + + ```shell + sudo gitlab-ctl patroni resume + ``` + +1. Promote the **secondary** to **primary**. SSH into a single application server and execute: + + ```shell + sudo gitlab-rake geo:set_secondary_as_primary + ``` + +1. Verify you can connect to the newly promoted **primary** using the URL used previously for the **secondary**. + +1. Success! The **secondary** has now been promoted to **primary**. + #### Promoting a **secondary** node with an external PostgreSQL database The `gitlab-ctl promote-to-primary-node` command cannot be used in conjunction with @@ -278,7 +347,7 @@ required: 1. Verify you can connect to the newly promoted **primary** site using the URL used previously for the **secondary** site. -Success! The **secondary** site has now been promoted to **primary**. +1. Success! The **secondary** site has now been promoted to **primary**. ### Step 4. (Optional) Updating the primary domain DNS record diff --git a/doc/administration/geo/index.md b/doc/administration/geo/index.md index 334f05ef3ce..1985ea2e04c 100644 --- a/doc/administration/geo/index.md +++ b/doc/administration/geo/index.md @@ -292,12 +292,6 @@ This list of limitations only reflects the latest version of GitLab. If you are ### Limitations on replication/verification -You can keep track of the progress to implement the missing items in -these epics/issues: - -- [Unreplicated Data Types](https://gitlab.com/groups/gitlab-org/-/epics/893) -- [Verify all replicated data](https://gitlab.com/groups/gitlab-org/-/epics/1430) - There is a complete list of all GitLab [data types](replication/datatypes.md) and [existing support for replication and verification](replication/datatypes.md#limitations-on-replicationverification). ## Frequently Asked Questions diff --git a/doc/administration/geo/replication/configuration.md b/doc/administration/geo/replication/configuration.md index 42501e16f5f..5adf256f6fa 100644 --- a/doc/administration/geo/replication/configuration.md +++ b/doc/administration/geo/replication/configuration.md @@ -170,6 +170,11 @@ keys must be manually replicated to the **secondary** node. sudo service sshd reload ``` +1. Verify SSH is still functional. + + SSH into your GitLab **secondary** server in a new terminal. If you are unable to connect, + verify the permissions are correct according to the previous steps. + ### Step 3. Add the **secondary** node 1. SSH into your GitLab **secondary** server and login as root: diff --git a/doc/administration/geo/setup/database.md b/doc/administration/geo/setup/database.md index 9778e08a30b..6e2ddfb812c 100644 --- a/doc/administration/geo/setup/database.md +++ b/doc/administration/geo/setup/database.md @@ -497,54 +497,135 @@ For instructions about how to set up Patroni on the primary node, see the If you are currently using `repmgr` on your Geo primary, see [these instructions](#migrating-from-repmgr-to-patroni) for migrating from `repmgr` to Patroni. A production-ready and secure setup requires at least three Patroni instances on -the primary, and a similar configuration on the secondary nodes. Be sure to use -password credentials and other database best practices. +the primary site, and a similar configuration on the secondary sites. Be sure to +use password credentials and other database best practices. Similar to `repmgr`, using Patroni on a secondary node is optional. -To set up database replication with Patroni on a secondary node, configure a -_permanent replication slot_ on the primary node's Patroni cluster, and ensure -password authentication is used. - -On Patroni instances for the primary node, add the following to the -`/etc/gitlab/gitlab.rb` file: - -```ruby -# You need one entry for each secondary, with a unique name following PostgreSQL slot_name constraints: -# -# Configuration syntax will be: 'unique_slotname' => { 'type' => 'physical' }, -# We don't support setting a permanent replication slot for logical replication type -patroni['replication_slots'] = { - 'geo_secondary' => { 'type' => 'physical' } -} - -postgresql['md5_auth_cidr_addresses'] = [ - 'PATRONI_PRIMARY1_IP/32', 'PATRONI_PRIMARY2_IP/32', 'PATRONI_PRIMARY3_IP/32', 'PATRONI_PRIMARY_PGBOUNCER/32', - 'PATRONI_SECONDARY1_IP/32', 'PATRONI_SECONDARY2_IP/32', 'PATRONI_SECONDARY3_IP/32' # we list all secondary instances as they can all become a Standby Leader - # any other instance that needs access to the database as per documentation -] - -postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH' -postgresql['sql_replication_password'] = 'POSTGRESQL_REPLICATION_PASSWORD_HASH' -postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH' -``` - -On Patroni instances for the secondary node, add the following to the -`/etc/gitlab/gitlab.rb` file: - -```ruby -postgresql['md5_auth_cidr_addresses'] = [ - 'PATRONI_SECONDARY1_IP/32', 'PATRONI_SECONDARY2_IP/32', 'PATRONI_SECONDARY3_IP/32', 'PATRONI_SECONDARY_PGBOUNCER/32', - # any other instance that needs access to the database as per documentation -] - -patroni['enable'] = true -patroni['standby_cluster']['enable'] = true -patroni['standby_cluster']['host'] = 'PATRONI_PRIMARY_LEADER_IP' # this needs to be changed anytime the primary Leader changes -patroni['standby_cluster']['port'] = 5432 -patroni['standby_cluster']['primary_slot_name'] = 'geo_secondary' # or the unique replication slot name you setup before -patroni['replication_password'] = 'PLAIN_TEXT_POSTGRESQL_REPLICATION_PASSWORD' -``` +### Step 1. Configure Patroni permanent replication slot on the primary site + +To set up database replication with Patroni on a secondary node, we need to +configure a _permanent replication slot_ on the primary node's Patroni cluster, +and ensure password authentication is used. + +For each Patroni instance on the primary site **starting on the Patroni +Leader instance**: + +1. SSH into your Patroni instance and login as root: + + ```shell + sudo -i + ``` + +1. Edit `/etc/gitlab/gitlab.rb` and add the following: + + ```ruby + consul['enable'] = true + consul['configuration'] = { + retry_join: %w[CONSUL_PRIMARY1_IP CONSULT_PRIMARY2_IP CONSULT_PRIMARY3_IP] + } + + repmgr['enable'] = false + + # You need one entry for each secondary, with a unique name following PostgreSQL slot_name constraints: + # + # Configuration syntax will be: 'unique_slotname' => { 'type' => 'physical' }, + # We don't support setting a permanent replication slot for logical replication type + patroni['replication_slots'] = { + 'geo_secondary' => { 'type' => 'physical' } + } + + patroni['use_pg_rewind'] = true + patroni['postgresql']['max_wal_senders'] = 8 # Use double of the amount of patroni/reserved slots (3 patronis + 1 reserved slot for a Geo secondary). + patroni['postgresql']['max_replication_slots'] = 8 # Use double of the amount of patroni/reserved slots (3 patronis + 1 reserved slot for a Geo secondary). + + postgresql['md5_auth_cidr_addresses'] = [ + 'PATRONI_PRIMARY1_IP/32', 'PATRONI_PRIMARY2_IP/32', 'PATRONI_PRIMARY3_IP/32', 'PATRONI_PRIMARY_PGBOUNCER/32', + 'PATRONI_SECONDARY1_IP/32', 'PATRONI_SECONDARY2_IP/32', 'PATRONI_SECONDARY3_IP/32', 'PATRONI_SECONDARY_PGBOUNCER/32' # We list all secondary instances as they can all become a Standby Leader + ] + + postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH' + postgresql['sql_replication_password'] = 'POSTGRESQL_REPLICATION_PASSWORD_HASH' + postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH' + ``` + +1. Reconfigure GitLab for the changes to take effect: + + ```shell + gitlab-ctl reconfigure + ``` + +### Step 2. Configure a Standby cluster on the secondary site + +NOTE: +If you are converting a secondary site to a Patroni Cluster, you must start +on the PostgreSQL instance. It will become the Patroni Standby Leader instance, +and then you can switchover to another replica if you need. + +For each Patroni instance on the secondary site: + +1. SSH into your Patroni node and login as root: + + ```shell + sudo -i + ``` + +1. Edit `/etc/gitlab/gitlab.rb` and add the following: + + ```ruby + roles ['consul_role', 'postgres_role'] + + consul['enable'] = true + consul['configuration'] = { + retry_join: %w[CONSUL_SECONDARY1_IP CONSULT_SECONDARY2_IP CONSULT_SECONDARY3_IP] + } + + repmgr['enable'] = false + + postgresql['md5_auth_cidr_addresses'] = [ + 'PATRONI_SECONDARY1_IP/32', 'PATRONI_SECONDARY2_IP/32', 'PATRONI_SECONDARY3_IP/32', 'PATRONI_SECONDARY_PGBOUNCER/32', + # Any other instance that needs access to the database as per documentation + ] + + patroni['enable'] = false + patroni['standby_cluster']['enable'] = true + patroni['standby_cluster']['host'] = 'PATRONI_PRIMARY_LEADER_IP' # This needs to be changed anytime the primary Leader changes + patroni['standby_cluster']['port'] = 5432 + patroni['standby_cluster']['primary_slot_name'] = 'geo_secondary' # Or the unique replication slot name you setup before + patroni['replication_password'] = 'PLAIN_TEXT_POSTGRESQL_REPLICATION_PASSWORD' + patroni['use_pg_rewind'] = true + patroni['postgresql']['max_wal_senders'] = 5 # A minimum of three for one replica, plus two for each additional replica + patroni['postgresql']['max_replication_slots'] = 5 # A minimum of three for one replica, plus two for each additional replica + ``` + +1. Reconfigure GitLab for the changes to take effect. + This is required to bootstrap PostgreSQL users and settings: + + ```shell + gitlab-ctl reconfigure + ``` + +1. Remove the PostgreSQL data directory: + + WARNING: + If you are converting a secondary site to a Patroni Cluster, you must skip + this step on the PostgreSQL instance. + + ```shell + rm -rf /var/opt/gitlab/postgresql/data + ``` + +1. Edit `/etc/gitlab/gitlab.rb` to enable Patroni: + + ```ruby + patroni['enable'] = true + ``` + +1. Reconfigure GitLab for the changes to take effect: + + ```shell + gitlab-ctl reconfigure + ``` ## Migrating from repmgr to Patroni diff --git a/doc/administration/gitaly/img/gitlab_gitaly_version_mismatch_v12_4.png b/doc/administration/gitaly/img/gitlab_gitaly_version_mismatch_v12_4.png Binary files differdeleted file mode 100644 index 4d2c5cdb00c..00000000000 --- a/doc/administration/gitaly/img/gitlab_gitaly_version_mismatch_v12_4.png +++ /dev/null diff --git a/doc/administration/gitaly/index.md b/doc/administration/gitaly/index.md index e0b0d52fe3f..9577fb40abe 100644 --- a/doc/administration/gitaly/index.md +++ b/doc/administration/gitaly/index.md @@ -395,7 +395,7 @@ Gitaly makes the following assumptions: You can't define Gitaly servers with some as a local Gitaly server (without `gitaly_address`) and some as remote -server (with `gitaly_address`) unless you setup with special +server (with `gitaly_address`) unless you use [mixed configuration](#mixed-configuration). **For Omnibus GitLab** @@ -502,8 +502,8 @@ If it's excluded, default Git storage directory is used for that storage shard. ### Disable Gitaly where not required (optional) -If you are running Gitaly [as a remote service](#run-gitaly-on-its-own-server) you may want to -disable the local Gitaly service that runs on your GitLab server by default, leaving it only running +If you are running Gitaly [as a remote service](#run-gitaly-on-its-own-server), you may want to +disable the local Gitaly service that runs on your GitLab server by default and have it only running where required. Disabling Gitaly on the GitLab instance only makes sense when you run GitLab in a custom cluster configuration, where @@ -1007,7 +1007,7 @@ When GitLab calls a function that has a "Rugged patch", it performs two checks: - Is the feature flag for this patch set in the database? If so, the feature flag setting controls the GitLab use of "Rugged patch" code. -- If the feature flag is not set, GitLab tries accessing the filesystem underneath the +- If the feature flag is not set, GitLab tries accessing the file system underneath the Gitaly server directly. If it can, it uses the "Rugged patch": - If using Unicorn. - If using Puma and [thread count](../../install/requirements.md#puma-threads) is set @@ -1015,9 +1015,9 @@ When GitLab calls a function that has a "Rugged patch", it performs two checks: The result of these checks is cached. -To see if GitLab can access the repository filesystem directly, we use the following heuristic: +To see if GitLab can access the repository file system directly, we use the following heuristic: -- Gitaly ensures that the filesystem has a metadata file in its root with a UUID in it. +- Gitaly ensures that the file system has a metadata file in its root with a UUID in it. - Gitaly reports this UUID to GitLab via the `ServerInfo` RPC. - GitLab Rails tries to read the metadata file directly. If it exists, and if the UUID's match, assume we have direct access. @@ -1044,13 +1044,11 @@ The second facet presents the only real solution. For this, we developed Check [Gitaly timeouts](../../user/admin_area/settings/gitaly_timeouts.md) when troubleshooting Gitaly. -### Checking versions when using standalone Gitaly servers +### Check versions when using standalone Gitaly servers When using standalone Gitaly servers, you must make sure they are the same version -as GitLab to ensure full compatibility. Check **Admin Area > Gitaly Servers** on -your GitLab instance and confirm all Gitaly Servers are `Up to date`. - -![Gitaly standalone software versions diagram](img/gitlab_gitaly_version_mismatch_v12_4.png) +as GitLab to ensure full compatibility. Check **Admin Area > Overview > Gitaly Servers** on +your GitLab instance and confirm all Gitaly servers indicate that they are up to date. ### `gitaly-debug` diff --git a/doc/administration/gitaly/praefect.md b/doc/administration/gitaly/praefect.md index 6eaafae6015..fe8b3e5f566 100644 --- a/doc/administration/gitaly/praefect.md +++ b/doc/administration/gitaly/praefect.md @@ -5,17 +5,16 @@ info: To determine the technical writer assigned to the Stage/Group associated w type: reference --- -# Gitaly Cluster +# Gitaly Cluster **(CORE ONLY)** [Gitaly](index.md), the service that provides storage for Git repositories, can be run in a clustered configuration to increase fault tolerance. In this configuration, every Git repository is stored on every Gitaly node in the -cluster. Multiple clusters (or shards), can be configured. +cluster. Multiple clusters (or shards) can be configured. NOTE: -Gitaly Clusters can be created using [GitLab Core](https://about.gitlab.com/pricing/#self-managed) -and higher tiers. However, technical support is limited to GitLab Premium and Ultimate customers -only. Not available in GitLab.com. +Technical support for Gitaly clusters is limited to GitLab Premium and Ultimate +customers. Praefect is a router and transaction manager for Gitaly, and a required component for running a Gitaly Cluster. @@ -1364,7 +1363,7 @@ sudo /opt/gitlab/embedded/bin/praefect -config /var/opt/gitlab/praefect/config.t If your GitLab instance already has repositories on single Gitaly nodes, these aren't migrated to Gitaly Cluster automatically. -Repositories may be moved from one storage location using the [Project repository storage moves API](../../api/project_repository_storage_moves.md): +Project repositories may be moved from one storage location using the [Project repository storage moves API](../../api/project_repository_storage_moves.md): NOTE: The Project repository storage moves API [cannot move all repository types](../../api/project_repository_storage_moves.md#limitations). @@ -1388,6 +1387,8 @@ To move repositories to Gitaly Cluster: using the API to confirm that all projects have moved. No projects should be returned with `repository_storage` field set to the old storage. +In a similar way, you can move Snippet repositories using the [Snippet repository storage moves API](../../api/snippet_repository_storage_moves.md): + ## Debugging Praefect If you receive an error, check `/var/log/gitlab/gitlab-rails/production.log`. diff --git a/doc/administration/housekeeping.md b/doc/administration/housekeeping.md index 90d2f0d916d..178fc438df2 100644 --- a/doc/administration/housekeeping.md +++ b/doc/administration/housekeeping.md @@ -40,3 +40,20 @@ from your project on the same schedule as the `git gc` operation, freeing up sto You can find this option under your project's **Settings > General > Advanced**. ![Housekeeping settings](img/housekeeping_settings.png) + +## How housekeeping handles pool repositories + +Housekeeping for pool repositories is handled differently from standard repositories. +It is ultimately performed by the Gitaly RPC `FetchIntoObjectPool`. + +This is the current call stack by which it is invoked: + +1. `Repositories::HousekeepingService#execute_gitlab_shell_gc` +1. `GitGarbageCollectWorker#perform` +1. `Projects::GitDeduplicationService#fetch_from_source` +1. `ObjectPool#fetch` +1. `ObjectPoolService#fetch` +1. `Gitaly::FetchIntoObjectPoolRequest` + +To manually invoke it from a Rails console, if needed, you can call `project.pool_repository.object_pool.fetch`. +This is a potentially long-running task, though Gitaly will timeout in about 8 hours. diff --git a/doc/administration/incoming_email.md b/doc/administration/incoming_email.md index 7a49542f8bb..2eb5da7d9ab 100644 --- a/doc/administration/incoming_email.md +++ b/doc/administration/incoming_email.md @@ -251,7 +251,7 @@ incoming_email: #### Gmail -Example configuration for Gmail/G Suite. Assumes mailbox `gitlab-incoming@gmail.com`. +Example configuration for Gmail/Google Workspace. Assumes mailbox `gitlab-incoming@gmail.com`. NOTE: `incoming_email_email` cannot be a Gmail alias account. diff --git a/doc/administration/index.md b/doc/administration/index.md index 32c0b1b0712..f071fde2faa 100644 --- a/doc/administration/index.md +++ b/doc/administration/index.md @@ -33,14 +33,13 @@ Learn how to install, configure, update, and maintain your GitLab instance. ### Installing GitLab - [Install](../install/README.md): Requirements, directory structures, and installation methods. - - [Database load balancing](database_load_balancing.md): Distribute database queries among multiple database servers. **(STARTER ONLY)** - - [Omnibus support for log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only) **(STARTER ONLY)** + - [Database load balancing](database_load_balancing.md): Distribute database queries among multiple database servers. + - [Omnibus support for log forwarding](https://docs.gitlab.com/omnibus/settings/logs.html#udp-log-shipping-gitlab-enterprise-edition-only). - [Reference architectures](reference_architectures/index.md): Add additional resources to support more users. - [Installing GitLab on Amazon Web Services (AWS)](../install/aws/index.md): Set up GitLab on Amazon AWS. -- [Geo](geo/index.md): Replicate your GitLab instance to other geographic locations as a read-only fully operational version. **(PREMIUM ONLY)** -- [Disaster Recovery](geo/disaster_recovery/index.md): Quickly fail-over to a different site with minimal effort in a disaster situation. **(PREMIUM ONLY)** -- [Pivotal Tile](../install/pivotal/index.md): Deploy GitLab as a preconfigured appliance using Ops Manager (BOSH) for Pivotal Cloud Foundry. **(PREMIUM ONLY)** -- [Add License](../user/admin_area/license.md): Upload a license at install time to unlock features that are in paid tiers of GitLab. **(STARTER ONLY)** +- [Geo](geo/index.md): Replicate your GitLab instance to other geographic locations as a read-only fully operational version. +- [Disaster Recovery](geo/disaster_recovery/index.md): Quickly fail-over to a different site with minimal effort in a disaster situation. +- [Add License](../user/admin_area/license.md): Upload a license at install time to unlock features that are in paid tiers of GitLab. ### Configuring GitLab @@ -72,11 +71,9 @@ Learn how to install, configure, update, and maintain your GitLab instance. to GitLab users through the UI. - [Elasticsearch](../integration/elasticsearch.md): Enable Elasticsearch to empower Advanced Search. Useful when you deal with a huge amount of data. - **(STARTER ONLY)** -- [External Classification Policy Authorization](../user/admin_area/settings/external_authorization.md) - **(PREMIUM ONLY)** +- [External Classification Policy Authorization](../user/admin_area/settings/external_authorization.md). - [Upload a license](../user/admin_area/license.md): Upload a license to unlock - features that are in paid tiers of GitLab. **(STARTER ONLY)** + features that are in paid tiers of GitLab. - [Admin Area](../user/admin_area/index.md): for self-managed instance-wide configuration and maintenance. - [S/MIME Signing](smime_signing_email.md): how to sign all outgoing notification @@ -90,7 +87,7 @@ Learn how to install, configure, update, and maintain your GitLab instance. - [Favicon](../user/admin_area/appearance.md#favicon): Change the default favicon to your own logo. - [Branded login page](../user/admin_area/appearance.md#sign-in--sign-up-pages): Customize the login page with your own logo, title, and description. - ["New Project" page](../user/admin_area/appearance.md#new-project-pages): Customize the text to be displayed on the page that opens whenever your users create a new project. -- [Additional custom email text](../user/admin_area/settings/email.md#custom-additional-text): Add additional custom text to emails sent from GitLab. **(PREMIUM ONLY)** +- [Additional custom email text](../user/admin_area/settings/email.md#custom-additional-text): Add additional custom text to emails sent from GitLab. ### Maintaining GitLab @@ -127,15 +124,15 @@ Learn how to install, configure, update, and maintain your GitLab instance. - [Sign-up restrictions](../user/admin_area/settings/sign_up_restrictions.md): block email addresses of specific domains, or whitelist only specific domains. - [Access restrictions](../user/admin_area/settings/visibility_and_access_controls.md#enabled-git-access-protocols): Define which Git access protocols can be used to talk to GitLab (SSH, HTTP, HTTPS). - [Authentication and Authorization](auth/README.md): Configure external authentication with LDAP, SAML, CAS, and additional providers. - - [Sync LDAP](auth/ldap/index.md) **(STARTER ONLY)** - - [Kerberos authentication](../integration/kerberos.md) **(STARTER ONLY)** + - [Sync LDAP](auth/ldap/index.md). + - [Kerberos authentication](../integration/kerberos.md). - See also other [authentication](../topics/authentication/index.md#gitlab-administrators) topics (for example, enforcing 2FA). -- [Email users](../tools/email.md): Email GitLab users from within GitLab. **(STARTER ONLY)** +- [Email users](../tools/email.md): Email GitLab users from within GitLab. - [User Cohorts](../user/admin_area/analytics/user_cohorts.md): Display the monthly cohorts of new users and their activities over time. - [Audit events](audit_events.md): View the changes made within the GitLab server for: - - Groups and projects. **(STARTER)** - - Instances. **(PREMIUM ONLY)** -- [Auditor users](auditor_users.md): Users with read-only access to all projects, groups, and other resources on the GitLab instance. **(PREMIUM ONLY)** + - Groups and projects. + - Instances. +- [Auditor users](auditor_users.md): Users with read-only access to all projects, groups, and other resources on the GitLab instance. - [Incoming email](incoming_email.md): Configure incoming emails to allow users to [reply by email](reply_by_email.md), create [issues by email](../user/project/issues/managing_issues.md#new-issue-via-email) and [merge requests by email](../user/project/merge_requests/creating_merge_requests.md#new-merge-request-by-email), and to enable [Service Desk](../user/project/service_desk.md). @@ -143,7 +140,7 @@ Learn how to install, configure, update, and maintain your GitLab instance. basic Postfix mail server with IMAP authentication on Ubuntu for incoming emails. - [Abuse reports](../user/admin_area/abuse_reports.md): View and resolve abuse reports from your users. -- [Credentials Inventory](../user/admin_area/credentials_inventory.md): With Credentials inventory, GitLab administrators can keep track of the credentials used by their users in their GitLab self-managed instance. **(ULTIMATE ONLY)** +- [Credentials Inventory](../user/admin_area/credentials_inventory.md): With Credentials inventory, GitLab administrators can keep track of the credentials used by their users in their GitLab self-managed instance. ## Project settings @@ -151,7 +148,7 @@ Learn how to install, configure, update, and maintain your GitLab instance. - [Gitaly](gitaly/index.md): Configuring Gitaly, the Git repository storage service for GitLab. - [Default labels](../user/admin_area/labels.md): Create labels that are automatically added to every new project. - [Restrict the use of public or internal projects](../public_access/public_access.md#restricting-the-use-of-public-or-internal-projects): Restrict the use of visibility levels for users when they create a project or a snippet. -- [Custom project templates](../user/admin_area/custom_project_templates.md): Configure a set of projects to be used as custom templates when creating a new project. **(PREMIUM ONLY)** +- [Custom project templates](../user/admin_area/custom_project_templates.md): Configure a set of projects to be used as custom templates when creating a new project. ## Package Registry administration @@ -165,7 +162,7 @@ Learn how to install, configure, update, and maintain your GitLab instance. - [Repository storage paths](repository_storage_paths.md): Manage the paths used to store repositories. - [Repository storage types](repository_storage_types.md): Information about the different repository storage types. - [Repository storage Rake tasks](raketasks/storage.md): A collection of Rake tasks to list and migrate existing projects and attachments associated with it from Legacy storage to Hashed storage. -- [Limit repository size](../user/admin_area/settings/account_and_limit_settings.md): Set a hard limit for your repositories' size. **(STARTER ONLY)** +- [Limit repository size](../user/admin_area/settings/account_and_limit_settings.md): Set a hard limit for your repositories' size. - [Static objects external storage](static_objects_external_storage.md): Set external storage for static objects in a repository. ## Continuous Integration settings @@ -176,7 +173,7 @@ Learn how to install, configure, update, and maintain your GitLab instance. - [Job artifacts](job_artifacts.md): Enable, disable, and configure job artifacts (a set of files and directories which are outputted by a job when it completes successfully). - [Job logs](job_logs.md): Information about the job logs. - [Register runners](../ci/runners/README.md#types-of-runners): Learn how to register and configure runners. -- [Shared runners pipelines quota](../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota): Limit the usage of pipeline minutes for shared runners. **(STARTER ONLY)** +- [Shared runners pipelines quota](../user/admin_area/settings/continuous_integration.md#shared-runners-pipeline-minutes-quota): Limit the usage of pipeline minutes for shared runners. - [Enable/disable Auto DevOps](../topics/autodevops/index.md#enablingdisabling-auto-devops): Enable or disable Auto DevOps for your instance. ## Snippet settings @@ -213,7 +210,7 @@ Learn how to install, configure, update, and maintain your GitLab instance. ## Analytics -- [Pseudonymizer](pseudonymizer.md): Export data from a GitLab database to CSV files in a secure way. **(ULTIMATE)** +- [Pseudonymizer](pseudonymizer.md): Export data from a GitLab database to CSV files in a secure way. ## Troubleshooting diff --git a/doc/administration/integration/plantuml.md b/doc/administration/integration/plantuml.md index a7458999aaa..cd61dc9a2bf 100644 --- a/doc/administration/integration/plantuml.md +++ b/doc/administration/integration/plantuml.md @@ -37,7 +37,7 @@ A simple `docker-compose.yml` file would be: version: "3" services: gitlab: - image: 'gitlab/gitlab-ce:12.2.5-ce.0' + image: 'gitlab/gitlab-ee:12.2.5-ee.0' environment: GITLAB_OMNIBUS_CONFIG: | nginx['custom_gitlab_server_config'] = "location /-/plantuml/ { \n proxy_cache off; \n proxy_pass http://plantuml:8080/; \n}\n" @@ -90,8 +90,8 @@ the configuration below accordingly. ### Making local PlantUML accessible using custom GitLab setup The PlantUML server runs locally on your server, so it is not accessible -externally. As such, it is necessary to catch external PlantUML calls and -redirect them to the local server. +externally by default. As such, it is necessary to catch external PlantUML +calls and redirect them to the local server. The idea is to redirect each call to `https://gitlab.example.com/-/plantuml/` to the local PlantUML server `http://plantuml:8080/` or `http://localhost:8080/plantuml/`, depending on your setup. @@ -112,6 +112,12 @@ To activate the changes, run the following command: sudo gitlab-ctl reconfigure ``` +Note that the redirection through GitLab **must** be configured +when running [GitLab with TLS](https://docs.gitlab.com/omnibus/settings/ssl.html) +due to PlantUML's use of the insecure HTTP protocol. Newer browsers such +as [Google Chrome 86+](https://www.chromestatus.com/feature/4926989725073408) +do not load insecure HTTP resources on a page served over HTTPS. + ### Security PlantUML has features that allows fetching network resources. diff --git a/doc/administration/job_logs.md b/doc/administration/job_logs.md index 7af167de4ad..b2c6864e671 100644 --- a/doc/administration/job_logs.md +++ b/doc/administration/job_logs.md @@ -50,7 +50,7 @@ these steps to move the logs to a new location without losing any data. Jobs in progress are not affected, based on how [data flow](#data-flow) works. ```ruby - sidekiq['experimental_queue_selector'] = true + sidekiq['queue_selector'] = true sidekiq['queue_groups'] = [ "feature_category!=continuous_integration" ] @@ -185,7 +185,7 @@ Feature.enable(:ci_enable_live_trace) ``` NOTE: -The transition period is handled gracefully. Upcoming logs are +The transition period is handled gracefully. Upcoming logs are generated with the incremental architecture, and on-going logs stay with the legacy architecture, which means that on-going logs aren't forcibly re-generated with the incremental architecture. diff --git a/doc/administration/monitoring/performance/index.md b/doc/administration/monitoring/performance/index.md index 5b82696ae4b..072baa16e29 100644 --- a/doc/administration/monitoring/performance/index.md +++ b/doc/administration/monitoring/performance/index.md @@ -61,3 +61,14 @@ half above the interval. For example, for a user defined interval of 15 seconds the actual interval can be anywhere between 7.5 and 22.5. The interval is re-generated for every sampling run instead of being generated one time and reused for the duration of the process' lifetime. + +User defined intervals can be specified by means of environment variables. +The following environment variables are recognized: + +- `RUBY_SAMPLER_INTERVAL_SECONDS` +- `DATABASE_SAMPLER_INTERVAL_SECONDS` +- `ACTION_CABLE_SAMPLER_INTERVAL_SECONDS` +- `PUMA_SAMPLER_INTERVAL_SECONDS` +- `UNICORN_SAMPLER_INTERVAL_SECONDS` +- `THREADS_SAMPLER_INTERVAL_SECONDS` +- `GLOBAL_SEARCH_SAMPLER_INTERVAL_SECONDS` diff --git a/doc/administration/monitoring/prometheus/gitlab_exporter.md b/doc/administration/monitoring/prometheus/gitlab_exporter.md index 8e4d87cfa78..5add842bccc 100644 --- a/doc/administration/monitoring/prometheus/gitlab_exporter.md +++ b/doc/administration/monitoring/prometheus/gitlab_exporter.md @@ -30,3 +30,27 @@ To enable the GitLab exporter in an Omnibus GitLab instance: Prometheus automatically begins collecting performance data from the GitLab exporter exposed at `localhost:9168`. + +## Use a different Rack server + +>- Introduced in [Omnibus GitLab 13.8](https://gitlab.com/gitlab-org/omnibus-gitlab/-/merge_requests/4896). +>- WEBrick is now the default Rack server instead of Puma. + +By default, the GitLab exporter runs on [WEBrick](https://github.com/ruby/webrick), a single-threaded Ruby web server. +You can choose a different Rack server that better matches your performance needs. +For instance, in multi-node setups that contain a large number of Prometheus scrapers +but only a few monitoring nodes, you may decide to run a multi-threaded server such as Puma instead. + +To change the Rack server to Puma: + +1. Edit `/etc/gitlab/gitlab.rb`. +1. Add, or find and uncomment, the following line, and set it to `puma`: + + ```ruby + gitlab_exporter['server_name'] = 'puma' + ``` + +1. Save the file and [reconfigure GitLab](../../restart_gitlab.md#omnibus-gitlab-reconfigure) + for the changes to take effect. + +The supported Rack servers are `webrick` and `puma`. diff --git a/doc/administration/monitoring/prometheus/gitlab_metrics.md b/doc/administration/monitoring/prometheus/gitlab_metrics.md index c5e0570515d..4493c1677bc 100644 --- a/doc/administration/monitoring/prometheus/gitlab_metrics.md +++ b/doc/administration/monitoring/prometheus/gitlab_metrics.md @@ -210,6 +210,7 @@ configuration option in `gitlab.yml`. These metrics are served from the | `limited_capacity_worker_max_running_jobs` | Gauge | 13.5 | Maximum number of running jobs | `worker` | | `limited_capacity_worker_remaining_work_count` | Gauge | 13.5 | Number of jobs waiting to be enqueued | `worker` | | `destroyed_job_artifacts_count_total` | Counter | 13.6 | Number of destroyed expired job artifacts | | +| `destroyed_pipeline_artifacts_count_total` | Counter | 13.8 | Number of destroyed expired pipeline artifacts | | ## Database load balancing metrics **(PREMIUM ONLY)** diff --git a/doc/administration/nfs.md b/doc/administration/nfs.md index 1e2ac531329..bddf770180b 100644 --- a/doc/administration/nfs.md +++ b/doc/administration/nfs.md @@ -15,9 +15,10 @@ For data objects such as LFS, Uploads, Artifacts, etc., an [Object Storage servi is recommended over NFS where possible, due to better performance. WARNING: -From GitLab 13.0, using NFS for Git repositories is deprecated. In GitLab 14.0, -support for NFS for Git repositories is scheduled to be removed. Upgrade to -[Gitaly Cluster](gitaly/praefect.md) as soon as possible. +From GitLab 13.0, using NFS for Git repositories is deprecated. +From GitLab 14.0, technical support for NFS for Git repositories +will no longer be provided. Upgrade to [Gitaly Cluster](gitaly/praefect.md) +as soon as possible. Filesystem performance can impact overall GitLab performance, especially for actions that read or write to Git repositories. For steps you can use to test diff --git a/doc/administration/object_storage.md b/doc/administration/object_storage.md index a89c50a8412..999d9b87363 100644 --- a/doc/administration/object_storage.md +++ b/doc/administration/object_storage.md @@ -61,10 +61,10 @@ must be enabled, only the following providers can be used: - [Google Cloud Storage](#google-cloud-storage-gcs) - [Azure Blob storage](#azure-blob-storage) -Background upload isn't supported with the consolidated object storage -configuration. We recommend enabling direct upload mode because it doesn't -require a shared folder, and [this setting may become the -default](https://gitlab.com/gitlab-org/gitlab/-/issues/27331). +When consolidated object storage is used, direct upload is enabled +automatically. Background upload is not supported. For storage-specific +configuration, [direct upload may become the default](https://gitlab.com/gitlab-org/gitlab/-/issues/27331) +because it does not require a shared folder. Consolidated object storage configuration can't be used for backups or Mattermost. See the [full table for a complete list](#storage-specific-configuration). @@ -232,7 +232,7 @@ The connection settings match those provided by [fog-aws](https://github.com/fog | `aws_secret_access_key` | AWS credentials, or compatible | | | `aws_signature_version` | AWS signature version to use. `2` or `4` are valid options. Digital Ocean Spaces and other providers may need `2`. | `4` | | `enable_signature_v4_streaming` | Set to `true` to enable HTTP chunked transfers with [AWS v4 signatures](https://docs.aws.amazon.com/AmazonS3/latest/API/sigv4-streaming.html). Oracle Cloud S3 needs this to be `false`. | `true` | -| `region` | AWS region | us-east-1 | +| `region` | AWS region. | | | `host` | S3 compatible host for when not using AWS, e.g. `localhost` or `storage.example.com`. HTTPS and port 443 is assumed. | `s3.amazonaws.com` | | `endpoint` | Can be used when configuring an S3 compatible service such as [MinIO](https://min.io), by entering a URL such as `http://127.0.0.1:9000`. This takes precedence over `host`. | (optional) | | `path_style` | Set to `true` to use `host/bucket_name/object` style paths instead of `bucket_name.host/object`. Leave as `false` for AWS S3. | `false` | diff --git a/doc/administration/operations/extra_sidekiq_processes.md b/doc/administration/operations/extra_sidekiq_processes.md index 1f611a50a53..1b7c0edab04 100644 --- a/doc/administration/operations/extra_sidekiq_processes.md +++ b/doc/administration/operations/extra_sidekiq_processes.md @@ -114,7 +114,7 @@ you list: > - [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/45) in [GitLab Starter](https://about.gitlab.com/pricing/) 12.8. > - [Sidekiq cluster including queue selector moved](https://gitlab.com/groups/gitlab-com/gl-infra/-/epics/181) to GitLab [Core](https://about.gitlab.com/pricing/#self-managed) in GitLab 12.10. -> - [Marked as supported](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/147) in GitLab [Core](https://about.gitlab.com/pricing/#self-managed) in GitLab 13.6. Renamed from `experimental_queue_selector` to `queue_selector`. +> - [Renamed from `experimental_queue_selector` to `queue_selector`](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/147) in GitLab 13.6. In addition to selecting queues by name, as above, the `queue_selector` option allows queue groups to be selected in a more general way using diff --git a/doc/administration/operations/moving_repositories.md b/doc/administration/operations/moving_repositories.md index 7cc15f9cea4..029f3bb01ed 100644 --- a/doc/administration/operations/moving_repositories.md +++ b/doc/administration/operations/moving_repositories.md @@ -23,12 +23,14 @@ For more information, see: - [Configuring additional storage for Gitaly](../gitaly/index.md#network-architecture). Within this example, additional storage called `storage1` and `storage2` is configured. - [The API documentation](../../api/project_repository_storage_moves.md) details the endpoints for - querying and scheduling repository moves. + querying and scheduling project repository moves. +- [The API documentation](../../api/snippet_repository_storage_moves.md) details the endpoints for + querying and scheduling snippet repository moves. - [Migrate existing repositories to Gitaly Cluster](../gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster). ### Limitations -Read more in the [API documentation](../../api/project_repository_storage_moves.md#limitations). +Read more in the [API documentation for projects](../../api/project_repository_storage_moves.md#limitations) and the [API documentation for snippets](../../api/snippet_repository_storage_moves.md#limitations). ## Migrating to another GitLab instance diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md index 633129e98bd..ab6202fef4c 100644 --- a/doc/administration/packages/container_registry.md +++ b/doc/administration/packages/container_registry.md @@ -600,6 +600,28 @@ on how to achieve that. If you use an external container registry, some features associated with the container registry may be unavailable or have [inherent risks](../../user/packages/container_registry/index.md#use-with-external-container-registries). +For the integration to work, the external registry must be configured to +use a JSON Web Token to authenticate with GitLab. The +[external registry's runtime configuration](https://docs.docker.com/registry/configuration/#token) +**must** have the following entries: + +```yaml +auth: + token: + realm: https://gitlab.example.com/jwt/auth + service: container_registry + issuer: gitlab-issuer + rootcertbundle: /root/certs/certbundle +``` + +Without these entries, the registry logins cannot authenticate with GitLab. +GitLab also remains unaware of +[nested image names](../../user/packages/container_registry/#image-naming-convention) +under the project hierarchy, like +`registry.example.com/group/project/image-name:tag` or +`registry.example.com/group/project/my/image-name:tag`, and only recognizes +`registry.example.com/group/project:tag`. + **Omnibus GitLab** You can use GitLab as an auth endpoint with an external container registry. @@ -609,18 +631,23 @@ You can use GitLab as an auth endpoint with an external container registry. ```ruby gitlab_rails['registry_enabled'] = true gitlab_rails['registry_api_url'] = "http://localhost:5000" - gitlab_rails['registry_issuer'] = "omnibus-gitlab-issuer" + gitlab_rails['registry_issuer'] = "gitlab-issuer" ``` `gitlab_rails['registry_enabled'] = true` is needed to enable GitLab Container Registry features and authentication endpoint. The GitLab bundled Container Registry service does not start, even with this enabled. + `gitlab_rails['registry_api_url'] = "http://localhost:5000"` can + carry a different hostname and port depending on where the external registry + is hosted. It must also specify `https` if the external registry is + configured to use TLS. + 1. A certificate-key pair is required for GitLab and the external container registry to communicate securely. You need to create a certificate-key pair, configuring the external container registry with the public - certificate and configuring GitLab with the private key. To do that, add - the following to `/etc/gitlab/gitlab.rb`: + certificate (`rootcertbundle`) and configuring GitLab with the private key. + To do that, add the following to `/etc/gitlab/gitlab.rb`: ```ruby # registry['internal_key'] should contain the contents of the custom key @@ -664,7 +691,7 @@ You can use GitLab as an auth endpoint with an external container registry. api_url: "http://localhost:5000" path: /var/opt/gitlab/gitlab-rails/shared/registry key: /var/opt/gitlab/gitlab-rails/certificate.key - issuer: omnibus-gitlab-issuer + issuer: gitlab-issuer ``` 1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect. @@ -840,6 +867,26 @@ understand the implications. WARNING: This is a destructive operation. +When you run `registry-garbage-collect` with the -m flag, garbage collection unlinks manifests that +are part of a multi-arch manifest, unless they're tagged in the same repository. +See [this issue](https://gitlab.com/gitlab-org/container-registry/-/issues/149) for details. + +To work around this issue, instead of: + +```plaintext +myrepo/multiarchmanifest:latest +myrepo/manifest/amd-64:latest +myrepo/manifest/arm:latest +``` + +Use: + +```plaintext +myrepo/multiarchmanifest:latest +myrepo/manifest:amd-64-latest +myrepo/manifest:arm-latest +``` + The GitLab Container Registry follows the same default workflow as Docker Distribution: retain untagged manifests and all layers, even ones that are not referenced directly. All content can be accessed by using context addressable identifiers. diff --git a/doc/administration/pages/index.md b/doc/administration/pages/index.md index af0476b72e9..9e949468805 100644 --- a/doc/administration/pages/index.md +++ b/doc/administration/pages/index.md @@ -38,20 +38,20 @@ which you can set it up: - Run the Pages daemon in the same server as GitLab, listening on a **secondary IP**. - Run the Pages daemon in a [separate server](#running-gitlab-pages-on-a-separate-server). In that case, the [Pages path](#change-storage-path) must also be present in the server that - the Pages daemon is installed, so you will have to share it via network. + the Pages daemon is installed, so you must share it through the network. - Run the Pages daemon in the same server as GitLab, listening on the same IP - but on different ports. In that case, you will have to proxy the traffic with + but on different ports. In that case, you must proxy the traffic with a load balancer. If you choose that route note that you should use TCP load - balancing for HTTPS. If you use TLS-termination (HTTPS-load balancing) the - pages will not be able to be served with user provided certificates. For + balancing for HTTPS. If you use TLS-termination (HTTPS-load balancing), the + pages can't be served with user-provided certificates. For HTTP it's OK to use HTTP or TCP load balancing. -In this document, we will proceed assuming the first option. If you are not +In this document, we proceed assuming the first option. If you are not supporting custom domains a secondary IP is not needed. ## Prerequisites -Before proceeding with the Pages configuration, you will need to: +Before proceeding with the Pages configuration, you must: 1. Have a domain for Pages that is not a subdomain of your GitLab instance domain. @@ -69,7 +69,7 @@ Before proceeding with the Pages configuration, you will need to: 1. (Only for custom domains) Have a **secondary IP**. NOTE: -If your GitLab instance and the Pages daemon are deployed in a private network or behind a firewall, your GitLab Pages websites will only be accessible to devices/users that have access to the private network. +If your GitLab instance and the Pages daemon are deployed in a private network or behind a firewall, your GitLab Pages websites are only accessible to devices/users that have access to the private network. ### Add the domain to the Public Suffix List @@ -94,13 +94,34 @@ host that GitLab runs. For example, an entry would look like this: ```plaintext *.example.io. 1800 IN A 192.0.2.1 -*.example.io. 1800 IN AAAA 2001::1 +*.example.io. 1800 IN AAAA 2001:db8::1 ``` -where `example.io` is the domain under which GitLab Pages will be served -and `192.0.2.1` is the IPv4 address of your GitLab instance and `2001::1` is the +Where `example.io` is the domain GitLab Pages is served from, +`192.0.2.1` is the IPv4 address of your GitLab instance, and `2001:db8::1` is the IPv6 address. If you don't have IPv6, you can omit the AAAA record. +#### Custom domains + +If support for custom domains is needed, the Pages root domain and its subdomains should point to +the secondary IP (which is dedicated for the Pages daemon). `<namespace>.<pages root domain>` should +point at Pages directly. Without this, users aren't able to use `CNAME` records to point their +custom domains to their GitLab Pages. + +For example, an entry could look like this: + +```plaintext +example.com 1800 IN A 192.0.2.1 +*.example.io. 1800 IN A 192.0.2.2 +``` + +This example contains the following: + +- `example.com`: The GitLab domain. +- `example.io`: The domain GitLab Pages is served from. +- `192.0.2.1`: The primary IP of your GitLab instance. +- `192.0.2.2`: The secondary IP, which is dedicated to GitLab Pages. + NOTE: You should not use the GitLab domain to serve user pages. For more information see the [security section](#security). @@ -123,7 +144,7 @@ since that is needed in all configurations. URL scheme: `http://<namespace>.example.io/<project_slug>` This is the minimum setup that you can use Pages with. It is the base for all -other setups as described below. NGINX will proxy all requests to the daemon. +other setups as described below. NGINX proxies all requests to the daemon. The Pages daemon doesn't listen to the outside world. 1. Set the external URL for GitLab Pages in `/etc/gitlab/gitlab.rb`: @@ -147,7 +168,7 @@ Watch the [video tutorial](https://youtu.be/dD8c7WNcc6s) for this configuration. URL scheme: `https://<namespace>.example.io/<project_slug>` -NGINX will proxy all requests to the daemon. Pages daemon doesn't listen to the +NGINX proxies all requests to the daemon. Pages daemon doesn't listen to the outside world. 1. Place the certificate and key inside `/etc/gitlab/ssl` @@ -168,8 +189,8 @@ outside world. ### Additional configuration for Docker container -The GitLab Pages daemon will not have permissions to bind mounts when it runs -in a Docker container. To overcome this issue you'll need to change the chroot +The GitLab Pages daemon doesn't have permissions to bind mounts when it runs +in a Docker container. To overcome this issue, you must change the chroot behavior: 1. Edit `/etc/gitlab/gitlab.rb`. @@ -189,7 +210,7 @@ The [GitLab Pages README](https://gitlab.com/gitlab-org/gitlab-pages#caveats) ha Below is a table of all configuration settings known to Pages in Omnibus GitLab, and what they do. These options can be adjusted in `/etc/gitlab/gitlab.rb`, -and will take effect after you [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). +and take effect after you [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). Most of these settings don't need to be configured manually unless you need more granular control over how the Pages daemon runs and serves content in your environment. @@ -218,7 +239,7 @@ control over how the Pages daemon runs and serves content in your environment. | `inplace_chroot` | On [systems that don't support bind-mounts](index.md#additional-configuration-for-docker-container), this instructs GitLab Pages to chroot into its `pages_path` directory. Some caveats exist when using inplace chroot; refer to the GitLab Pages [README](https://gitlab.com/gitlab-org/gitlab-pages/blob/master/README.md#caveats) for more information. | `insecure_ciphers` | Use default list of cipher suites, may contain insecure ones like 3DES and RC4. | `internal_gitlab_server` | Internal GitLab server address used exclusively for API requests. Useful if you want to send that traffic over an internal load balancer. Defaults to GitLab `external_url`. -| `listen_proxy` | The addresses to listen on for reverse-proxy requests. Pages will bind to these addresses' network socket and receives incoming requests from it. Sets the value of `proxy_pass` in `$nginx-dir/conf/gitlab-pages.conf`. +| `listen_proxy` | The addresses to listen on for reverse-proxy requests. Pages binds to these addresses' network sockets and receives incoming requests from them. Sets the value of `proxy_pass` in `$nginx-dir/conf/gitlab-pages.conf`. | `log_directory` | Absolute path to a log directory. | `log_format` | The log output format: `text` or `json`. | `log_verbose` | Verbose logging, true/false. @@ -250,7 +271,7 @@ control over how the Pages daemon runs and serves content in your environment. In addition to the wildcard domains, you can also have the option to configure GitLab Pages to work with custom domains. Again, there are two options here: support custom domains with and without TLS certificates. The easiest setup is -that without TLS certificates. In either case, you'll need a **secondary IP**. If +that without TLS certificates. In either case, you need a **secondary IP**. If you have IPv6 as well as IPv4 addresses, you can use them both. ### Custom domains @@ -274,11 +295,11 @@ world. Custom domains are supported, but no TLS. pages_external_url "http://example.io" nginx['listen_addresses'] = ['192.0.2.1'] pages_nginx['enable'] = false - gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001::2]:80'] + gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001:db8::2]:80'] ``` where `192.0.2.1` is the primary IP address that GitLab is listening to and - `192.0.2.2` and `2001::2` are the secondary IPs the GitLab Pages daemon + `192.0.2.2` and `2001:db8::2` are the secondary IPs the GitLab Pages daemon listens on. If you don't have IPv6, you can omit the IPv6 address. 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). @@ -307,12 +328,12 @@ world. Custom domains and TLS are supported. pages_nginx['enable'] = false gitlab_pages['cert'] = "/etc/gitlab/ssl/example.io.crt" gitlab_pages['cert_key'] = "/etc/gitlab/ssl/example.io.key" - gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001::2]:80'] - gitlab_pages['external_https'] = ['192.0.2.2:443', '[2001::2]:443'] + gitlab_pages['external_http'] = ['192.0.2.2:80', '[2001:db8::2]:80'] + gitlab_pages['external_https'] = ['192.0.2.2:443', '[2001:db8::2]:443'] ``` where `192.0.2.1` is the primary IP address that GitLab is listening to and - `192.0.2.2` and `2001::2` are the secondary IPs where the GitLab Pages daemon + `192.0.2.2` and `2001:db8::2` are the secondary IPs where the GitLab Pages daemon listens on. If you don't have IPv6, you can omit the IPv6 address. 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure). @@ -321,7 +342,7 @@ world. Custom domains and TLS are supported. To prevent malicious users from hijacking domains that don't belong to them, GitLab supports [custom domain verification](../../user/project/pages/custom_domains_ssl_tls_certification/index.md#steps). -When adding a custom domain, users will be required to prove they own it by +When adding a custom domain, users are required to prove they own it by adding a GitLab-controlled verification code to the DNS records for that domain. If your user base is private or otherwise trusted, you can disable the @@ -337,11 +358,11 @@ This setting is enabled by default. allows users to add Let's Encrypt SSL certificates for GitLab Pages sites served under a custom domain. -To enable it, you'll need to: +To enable it, you must: -1. Choose an email on which you will receive notifications about expiring domains. +1. Choose an email address on which you want to receive notifications about expiring domains. 1. Navigate to your instance's **Admin Area > Settings > Preferences** and expand **Pages** settings. -1. Enter the email for receiving notifications and accept Let's Encrypt's Terms of Service as shown below. +1. Enter the email address for receiving notifications and accept Let's Encrypt's Terms of Service as shown below. 1. Click **Save changes**. ![Let's Encrypt settings](img/lets_encrypt_integration_v12_1.png) @@ -384,7 +405,7 @@ all the App nodes and Sidekiq nodes. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32095) in GitLab 12.7. You can enforce [Access Control](#access-control) for all GitLab Pages websites hosted -on your GitLab instance. By doing so, only logged-in users will have access to them. +on your GitLab instance. By doing so, only logged-in users have access to them. This setting overrides Access Control set by users in individual projects. This can be useful to preserve information published with Pages websites to the users @@ -417,7 +438,7 @@ internet connectivity is gated by a proxy. To use a proxy for GitLab Pages: When using certificates issued by a custom CA, [Access Control](../../user/project/pages/pages_access_control.md#gitlab-pages-access-control) and the [online view of HTML job artifacts](../../ci/pipelines/job_artifacts.md#browsing-artifacts) -will fail to work if the custom CA is not recognized. +fails to work if the custom CA is not recognized. This usually results in this error: `Post /oauth/token: x509: certificate signed by unknown authority`. @@ -501,7 +522,7 @@ the below steps to do a no downtime transfer to a new storage location. 1. Pause Pages deployments by setting the following in `/etc/gitlab/gitlab.rb`: ```ruby - sidekiq['experimental_queue_selector'] = true + sidekiq['queue_selector'] = true sidekiq['queue_groups'] = [ "feature_category!=pages" ] @@ -602,7 +623,7 @@ database encryption. Proceed with caution. changes to take effect. The `gitlab-secrets.json` file is now updated with the new configuration. -1. Set up a new server. This will become the **Pages server**. +1. Set up a new server. This becomes the **Pages server**. 1. Create an [NFS share](../nfs.md) on the **Pages server** and configure this share to @@ -668,7 +689,7 @@ Pages server. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/217912) in GitLab 13.3. GitLab Pages can use different sources to get domain configuration. -The default value is `nil`; however, GitLab Pages will default to `auto`. +The default value is `nil`. However, GitLab Pages defaults to `auto`. ```ruby gitlab_pages['domain_config_source'] = nil @@ -806,10 +827,10 @@ provided at `/etc/ssl/ca-bundle.pem`. It's from `/opt/gitlab/embedded/ssl/certs/cacert.pem` as part of starting up Pages. -If the permissions on the source file are incorrect (they should be `0644`) then -the file inside the chroot jail will also be wrong. +If the permissions on the source file are incorrect (they should be `0644`), then +the file inside the chroot jail is also wrong. -Pages will log errors in `/var/log/gitlab/gitlab-pages/current` like: +Pages logs errors in `/var/log/gitlab/gitlab-pages/current` like: ```plaintext x509: failed to load system roots and no roots provided diff --git a/doc/administration/pages/source.md b/doc/administration/pages/source.md index c7c25f0f3a7..0aebeaf2ebe 100644 --- a/doc/administration/pages/source.md +++ b/doc/administration/pages/source.md @@ -17,8 +17,8 @@ You are encouraged to read the [Omnibus documentation](index.md) as it provides some invaluable information to the configuration of GitLab Pages. Please proceed to read it before going forward with this guide. -We also highly recommend that you use the Omnibus GitLab packages, as we -optimize them specifically for GitLab, and we will take care of upgrading GitLab +We also highly recommend that you use the Omnibus GitLab packages. We +optimize them specifically for GitLab, and we take care of upgrading GitLab Pages to the latest supported version. ## Overview @@ -38,22 +38,22 @@ which you can set it up: 1. Run the Pages daemon in the same server as GitLab, listening on a secondary IP. 1. Run the Pages daemon in a separate server. In that case, the [Pages path](#change-storage-path) must also be present in the server that - the Pages daemon is installed, so you will have to share it via network. + the Pages daemon is installed, so you must share it through the network. 1. Run the Pages daemon in the same server as GitLab, listening on the same IP - but on different ports. In that case, you will have to proxy the traffic with - a load balancer. If you choose that route note that you should use TCP load - balancing for HTTPS. If you use TLS-termination (HTTPS-load balancing) the - pages will not be able to be served with user provided certificates. For - HTTP it's OK to use HTTP or TCP load balancing. + but on different ports. In that case, you must proxy the traffic with + a load balancer. If you choose that route, note that you should use TCP load + balancing for HTTPS. If you use TLS-termination (HTTPS-load balancing), the + pages aren't able to be served with user-provided certificates. For + HTTP, it's OK to use HTTP or TCP load balancing. -In this document, we will proceed assuming the first option. If you are not -supporting custom domains a secondary IP is not needed. +In this document, we proceed assuming the first option. If you aren't +supporting custom domains, a secondary IP isn't needed. ## Prerequisites Before proceeding with the Pages configuration, make sure that: -1. You have a separate domain under which GitLab Pages will be served. In +1. You have a separate domain to serve GitLab Pages from. In this document we assume that to be `example.io`. 1. You have configured a **wildcard DNS record** for that domain. 1. You have installed the `zip` and `unzip` packages in the same server that @@ -74,7 +74,7 @@ host that GitLab runs. For example, an entry would look like this: *.example.io. 1800 IN A 192.0.2.1 ``` -where `example.io` is the domain under which GitLab Pages will be served +Where `example.io` is the domain to serve GitLab Pages from, and `192.0.2.1` is the IP address of your GitLab instance. NOTE: @@ -97,7 +97,7 @@ since that is needed in all configurations. URL scheme: `http://<namespace>.example.io/<project_slug>` This is the minimum setup that you can use Pages with. It is the base for all -other setups as described below. NGINX will proxy all requests to the daemon. +other setups as described below. NGINX proxies all requests to the daemon. The Pages daemon doesn't listen to the outside world. 1. Install the Pages daemon: @@ -117,7 +117,7 @@ The Pages daemon doesn't listen to the outside world. ``` 1. Edit `gitlab.yml` and under the `pages` setting, set `enabled` to `true` and - the `host` to the FQDN under which GitLab Pages will be served: + the `host` to the FQDN to serve GitLab Pages from: ```yaml ## GitLab Pages @@ -159,7 +159,7 @@ The Pages daemon doesn't listen to the outside world. URL scheme: `https://<namespace>.example.io/<project_slug>` -NGINX will proxy all requests to the daemon. Pages daemon doesn't listen to the +NGINX proxies all requests to the daemon. Pages daemon doesn't listen to the outside world. 1. Install the Pages daemon: @@ -238,8 +238,8 @@ world. Custom domains are supported, but no TLS. ``` 1. Edit `gitlab.yml` to look like the example below. You need to change the - `host` to the FQDN under which GitLab Pages will be served. Set - `external_http` to the secondary IP on which the pages daemon will listen + `host` to the FQDN to serve GitLab Pages from. Set + `external_http` to the secondary IP on which the pages daemon listens for connections: ```yaml @@ -303,9 +303,9 @@ world. Custom domains and TLS are supported. ``` 1. Edit `gitlab.yml` to look like the example below. You need to change the - `host` to the FQDN under which GitLab Pages will be served. Set + `host` to the FQDN to serve GitLab Pages from. Set `external_http` and `external_https` to the secondary IP on which the pages - daemon will listen for connections: + daemon listens for connections: ```yaml ## GitLab Pages diff --git a/doc/administration/postgresql/pgbouncer.md b/doc/administration/postgresql/pgbouncer.md index f09ac3052f4..951edfeaec2 100644 --- a/doc/administration/postgresql/pgbouncer.md +++ b/doc/administration/postgresql/pgbouncer.md @@ -66,6 +66,12 @@ This content has been moved to a [new location](replication_and_failover.md#conf 1. At this point, your instance should connect to the database through PgBouncer. If you are having issues, see the [Troubleshooting](#troubleshooting) section +## Backups + +Do not backup or restore GitLab through a PgBouncer connection: this will cause a GitLab outage. + +[Read more about this and how to reconfigure backups](../../raketasks/backup_restore.md#backup-and-restore-for-installations-using-pgbouncer). + ## Enable Monitoring > [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/3786) in GitLab 12.0. @@ -150,7 +156,10 @@ ote_pid | tls ## Procedure for bypassing PgBouncer -Some database changes have to be done directly, and not through PgBouncer. This includes database restores and GitLab upgrades (because of the database migrations). +Some database changes have to be done directly, and not through PgBouncer. + +Read more about the affected tasks: [database restores](../../raketasks/backup_restore.md#backup-and-restore-for-installations-using-pgbouncer) +and [GitLab upgrades](https://docs.gitlab.com/omnibus/update/README.html#use-postgresql-ha). 1. To find the primary node, run the following on a database node: diff --git a/doc/administration/postgresql/replication_and_failover.md b/doc/administration/postgresql/replication_and_failover.md index 303246c9c82..75d0c558962 100644 --- a/doc/administration/postgresql/replication_and_failover.md +++ b/doc/administration/postgresql/replication_and_failover.md @@ -46,22 +46,19 @@ Each database node runs three services: `PostgreSQL` - The database itself. -`repmgrd` - Communicates with other repmgrd services in the cluster and handles -failover when issues with the master server occurs. The failover procedure +`Patroni` - Communicates with other patroni services in the cluster and handles +failover when issues with the leader server occurs. The failover procedure consists of: -- Selecting a new master for the cluster. -- Promoting the new node to master. -- Instructing remaining servers to follow the new master node. -- The old master node is automatically evicted from the cluster and should be - rejoined manually once recovered. +- Selecting a new leader for the cluster. +- Promoting the new node to leader. +- Instructing remaining servers to follow the new leader node. -`Consul` agent - Monitors the status of each node in the database cluster and -tracks its health in a service definition on the Consul cluster. +`Consul` agent - To communicate with Consul cluster which stores the current Patroni state. The agent monitors the status of each node in the database cluster and tracks its health in a service definition on the Consul cluster. ### Consul server node -The Consul server node runs the Consul server service. +The Consul server node runs the Consul server service. These nodes must have reached the quorum and elected a leader _before_ Patroni cluster bootstrap otherwise database nodes will wait until such Consul leader is elected. ### PgBouncer node @@ -80,7 +77,7 @@ Each service in the package comes with a set of [default ports](https://docs.git - Application servers connect to either PgBouncer directly via its [default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#pgbouncer) or via a configured Internal Load Balancer (TCP) that serves multiple PgBouncers. - PgBouncer connects to the primary database servers [PostgreSQL default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#postgresql) -- Repmgr connects to the database servers [PostgreSQL default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#postgresql) +- Patroni actively manages the running PostgreSQL processes and configuration. - PostgreSQL secondaries connect to the primary database servers [PostgreSQL default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#postgresql) - Consul servers and agents connect to each others [Consul default ports](https://docs.gitlab.com/omnibus/package-information/defaults.html#consul) @@ -141,7 +138,7 @@ available database connections. In this document we are assuming 3 database nodes, which makes this configuration: ```ruby -postgresql['max_wal_senders'] = 4 +patroni['postgresql']['max_wal_senders'] = 4 ``` As previously mentioned, you'll have to prepare the network subnets that will @@ -186,18 +183,6 @@ Few notes on the service itself: - `/etc/gitlab/gitlab.rb`: hashed, and in plain text - `/var/opt/gitlab/pgbouncer/pg_auth`: hashed -#### Repmgr information - -When using default setup, you will only have to prepare the network subnets that will -be allowed to authenticate with the service. - -Few notes on the service itself: - -- The service runs under the same system account as the database - - In the package, this is by default `gitlab-psql` -- The service will have a superuser database user account generated for it - - This defaults to `gitlab_repmgr` - ### Installing Omnibus GitLab First, make sure to [download/install](https://about.gitlab.com/install/) @@ -212,72 +197,80 @@ When installing the GitLab package, do not supply `EXTERNAL_URL` value. 1. Make sure to [configure the Consul nodes](../consul.md). 1. Make sure you collect [`CONSUL_SERVER_NODES`](#consul-information), [`PGBOUNCER_PASSWORD_HASH`](#pgbouncer-information), [`POSTGRESQL_PASSWORD_HASH`](#postgresql-information), the [number of db nodes](#postgresql-information), and the [network address](#network-information) before executing the next step. -1. On the master database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: +#### Configuring Patroni cluster - ```ruby - # Disable all components except PostgreSQL and Repmgr and Consul - roles ['postgres_role'] +You must enable Patroni explicitly to be able to use it (with `patroni['enable'] = true`). When Patroni is enabled +repmgr will be disabled automatically. - # PostgreSQL configuration - postgresql['listen_address'] = '0.0.0.0' - postgresql['hot_standby'] = 'on' - postgresql['wal_level'] = 'replica' - postgresql['shared_preload_libraries'] = 'repmgr_funcs' +Any PostgreSQL configuration item that controls replication, for example `wal_level`, `max_wal_senders`, etc, are strictly +controlled by Patroni and will override the original settings that you make with the `postgresql[...]` configuration key. +Hence, they are all separated and placed under `patroni['postgresql'][...]`. This behavior is limited to replication. +Patroni honours any other PostgreSQL configuration that was made with the `postgresql[...]` configuration key. For example, +`max_wal_senders` by default is set to `5`. If you wish to change this you must set it with the `patroni['postgresql']['max_wal_senders']` +configuration key. - # Disable automatic database migrations - gitlab_rails['auto_migrate'] = false +NOTE: +The configuration of a Patroni node is very similar to a repmgr but shorter. When Patroni is enabled, first you can ignore +any replication setting of PostgreSQL (it will be overwritten anyway). Then you can remove any `repmgr[...]` or +repmgr-specific configuration as well. Especially, make sure that you remove `postgresql['shared_preload_libraries'] = 'repmgr_funcs'`. - # Configure the Consul agent - consul['services'] = %w(postgresql) +Here is an example similar to [the one that was done with repmgr](#configuring-repmgr-nodes): - # START user configuration - # Please set the real values as explained in Required Information section - # - # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value - postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH' - # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value - postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH' - # Replace X with value of number of db nodes + 1 - postgresql['max_wal_senders'] = X - postgresql['max_replication_slots'] = X +```ruby +# Disable all components except PostgreSQL, Patroni (or Repmgr), and Consul +roles['postgres_role'] - # Replace XXX.XXX.XXX.XXX/YY with Network Address - postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY) - repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 XXX.XXX.XXX.XXX/YY) +# Enable Patroni (which automatically disables Repmgr). +patroni['enable'] = true - # Replace placeholders: - # - # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z - # with the addresses gathered for CONSUL_SERVER_NODES - consul['configuration'] = { - retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z) - } - # - # END user configuration - ``` +# PostgreSQL configuration +postgresql['listen_address'] = '0.0.0.0' - > `postgres_role` was introduced with GitLab 10.3 +# Disable automatic database migrations +gitlab_rails['auto_migrate'] = false -1. On secondary nodes, add all the configuration specified above for primary node - to `/etc/gitlab/gitlab.rb`. In addition, append the following configuration - to inform `gitlab-ctl` that they are standby nodes initially and it need not - attempt to register them as primary node +# Configure the Consul agent +consul['services'] = %w(postgresql) - ```ruby - # Specify if a node should attempt to be master on initialization - repmgr['master_on_initialization'] = false - ``` +# START user configuration +# Please set the real values as explained in Required Information section +# +# Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value +postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH' +# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value +postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH' -1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. -1. [Enable Monitoring](#enable-monitoring) +# Replace X with value of number of db nodes + 1 (OPTIONAL the default value is 5) +patroni['postgresql']['max_wal_senders'] = X +patroni['postgresql']['max_replication_slots'] = X -> Please note: -> -> - If you want your database to listen on a specific interface, change the configuration: -> `postgresql['listen_address'] = '0.0.0.0'`. -> - If your PgBouncer service runs under a different user account, -> you also need to specify: `postgresql['pgbouncer_user'] = PGBOUNCER_USERNAME` in -> your configuration. +# Replace XXX.XXX.XXX.XXX/YY with Network Address +postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY) + +# Replace placeholders: +# +# Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z +# with the addresses gathered for CONSUL_SERVER_NODES +consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z) +} +# +# END user configuration +``` + +You do not need an additional or different configuration for replica nodes. As a matter of fact, you don't have to have +a predetermined primary node. Therefore all database nodes use the same configuration. + +Once the configuration of a node is done, you must [reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) +on each node for the changes to take effect. + +Generally, when Consul cluster is ready, the first node that [reconfigures](../restart_gitlab.md#omnibus-gitlab-reconfigure) +becomes the leader. You do not need to sequence the nodes reconfiguration. You can run them in parallel or in any order. +If you choose an arbitrary order you do not have any predetermined master. + +NOTE: +As opposed to repmgr, once the nodes are reconfigured you do not need any further action or additional command to join +the replicas. #### Enable Monitoring @@ -298,129 +291,6 @@ If you enable Monitoring, it must be enabled on **all** database servers. 1. Run `sudo gitlab-ctl reconfigure` to compile the configuration. -#### Database nodes post-configuration - -##### Primary node - -Select one node as a primary node. - -1. Open a database prompt: - - ```shell - gitlab-psql -d gitlabhq_production - ``` - -1. Enable the `pg_trgm` extension: - - ```shell - CREATE EXTENSION pg_trgm; - ``` - -1. Enable the `btree_gist` extension: - - ```shell - CREATE EXTENSION btree_gist; - ``` - -1. Exit the database prompt by typing `\q` and Enter. - -1. Verify the cluster is initialized with one node: - - ```shell - gitlab-ctl repmgr cluster show - ``` - - The output should be similar to the following: - - ```plaintext - Role | Name | Upstream | Connection String - ----------+----------|----------|---------------------------------------- - * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr - ``` - -1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will - refer to the hostname in the next section as `MASTER_NODE_NAME`. If the value - is not an IP address, it will need to be a resolvable name (via DNS or - `/etc/hosts`) - -##### Secondary nodes - -1. Set up the repmgr standby: - - ```shell - gitlab-ctl repmgr standby setup MASTER_NODE_NAME - ``` - - Do note that this will remove the existing data on the node. The command - has a wait time. - - The output should be similar to the following: - - ```console - # gitlab-ctl repmgr standby setup MASTER_NODE_NAME - Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data - If this is not what you want, hit Ctrl-C now to exit - To skip waiting, rerun with the -w option - Sleeping for 30 seconds - Stopping the database - Removing the data - Cloning the data - Starting the database - Registering the node with the cluster - ok: run: repmgrd: (pid 19068) 0s - ``` - -1. Verify the node now appears in the cluster: - - ```shell - gitlab-ctl repmgr cluster show - ``` - - The output should be similar to the following: - - ```plaintext - Role | Name | Upstream | Connection String - ----------+---------|-----------|------------------------------------------------ - * master | MASTER | | host=MASTER_NODE_NAME user=gitlab_repmgr dbname=gitlab_repmgr - standby | STANDBY | MASTER | host=STANDBY_HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr - ``` - -Repeat the above steps on all secondary nodes. - -#### Database checkpoint - -Before moving on, make sure the databases are configured correctly. Run the -following command on the **primary** node to verify that replication is working -properly: - -```shell -gitlab-ctl repmgr cluster show -``` - -The output should be similar to: - -```plaintext -Role | Name | Upstream | Connection String -----------+--------------|--------------|-------------------------------------------------------------------- -* master | MASTER | | host=MASTER port=5432 user=gitlab_repmgr dbname=gitlab_repmgr - standby | STANDBY | MASTER | host=STANDBY port=5432 user=gitlab_repmgr dbname=gitlab_repmgr -``` - -If the 'Role' column for any node says "FAILED", check the -[Troubleshooting section](#troubleshooting) before proceeding. - -Also, check that the check master command works successfully on each node: - -```shell -su - gitlab-consul -gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' -``` - -This command relies on exit codes to tell Consul whether a particular node is a master -or secondary. The most important thing here is that this command does not produce errors. -If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions. -Check the [Troubleshooting section](#troubleshooting) before proceeding. - ### Configuring the PgBouncer node 1. Make sure you collect [`CONSUL_SERVER_NODES`](#consul-information), [`CONSUL_PASSWORD_HASH`](#consul-information), and [`PGBOUNCER_PASSWORD_HASH`](#pgbouncer-information) before executing the next step. @@ -577,6 +447,12 @@ PostgreSQL's `trust_auth_cidr_addresses` in `gitlab.rb` on your database nodes. [PgBouncer error `ERROR: pgbouncer cannot connect to server`](#pgbouncer-error-error-pgbouncer-cannot-connect-to-server) in the Troubleshooting section before proceeding. +### Backups + +Do not backup or restore GitLab through a PgBouncer connection: this will cause a GitLab outage. + +[Read more about this and how to reconfigure backups](../../raketasks/backup_restore.md#backup-and-restore-for-installations-using-pgbouncer). + ### Ensure GitLab is running At this point, your GitLab instance should be up and running. Verify you're able @@ -605,9 +481,9 @@ Here is a list and description of each machine and the assigned IP: - `10.6.0.21`: PgBouncer 1 - `10.6.0.22`: PgBouncer 2 - `10.6.0.23`: PgBouncer 3 -- `10.6.0.31`: PostgreSQL master -- `10.6.0.32`: PostgreSQL secondary -- `10.6.0.33`: PostgreSQL secondary +- `10.6.0.31`: PostgreSQL 1 +- `10.6.0.32`: PostgreSQL 2 +- `10.6.0.33`: PostgreSQL 3 - `10.6.0.41`: GitLab application All passwords are set to `toomanysecrets`, please do not use this password or derived hashes and the `external_url` for GitLab is `http://gitlab.example.com`. @@ -667,29 +543,28 @@ An internal load balancer (TCP) is then required to be setup to serve each PgBou #### Example recommended setup for PostgreSQL servers -##### Primary node - -On primary node edit `/etc/gitlab/gitlab.rb`: +On database nodes edit `/etc/gitlab/gitlab.rb`: ```ruby -# Disable all components except PostgreSQL and Repmgr and Consul +# Disable all components except PostgreSQL, Patroni (or Repmgr), and Consul roles ['postgres_role'] # PostgreSQL configuration postgresql['listen_address'] = '0.0.0.0' postgresql['hot_standby'] = 'on' postgresql['wal_level'] = 'replica' -postgresql['shared_preload_libraries'] = 'repmgr_funcs' + +# Enable Patroni (which automatically disables Repmgr). +patroni['enable'] = true # Disable automatic database migrations gitlab_rails['auto_migrate'] = false postgresql['pgbouncer_user_password'] = '771a8625958a529132abe6f1a4acb19c' postgresql['sql_user_password'] = '450409b85a0223a214b5fb1484f34d0f' -postgresql['max_wal_senders'] = 4 +patroni['postgresql']['max_wal_senders'] = 4 postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/16) -repmgr['trust_auth_cidr_addresses'] = %w(10.6.0.0/16) # Configure the Consul agent consul['services'] = %w(postgresql) @@ -702,85 +577,27 @@ consul['monitoring_service_discovery'] = true [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. -##### Secondary nodes - -On secondary nodes, edit `/etc/gitlab/gitlab.rb` and add all the configuration -added to primary node, noted above. In addition, append the following -configuration: - -```ruby -# Specify if a node should attempt to be master on initialization -repmgr['master_on_initialization'] = false -``` - -[Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. - -###### Example recommended setup for application server - -On the server edit `/etc/gitlab/gitlab.rb`: - -```ruby -external_url 'http://gitlab.example.com' - -gitlab_rails['db_host'] = '10.6.0.20' # Internal Load Balancer for PgBouncer nodes -gitlab_rails['db_port'] = 6432 -gitlab_rails['db_password'] = 'toomanysecrets' -gitlab_rails['auto_migrate'] = false - -postgresql['enable'] = false -pgbouncer['enable'] = false -consul['enable'] = true - -# Configure Consul agent -consul['watchers'] = %w(postgresql) - -pgbouncer['users'] = { - 'gitlab-consul': { - password: '5e0e3263571e3704ad655076301d6ebe' - }, - 'pgbouncer': { - password: '771a8625958a529132abe6f1a4acb19c' - } -} - -consul['configuration'] = { - retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13) -} -``` - -[Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. - #### Example recommended setup manual steps After deploying the configuration follow these steps: -1. On `10.6.0.31`, our primary database: - - Enable the `pg_trgm` and `btree_gist` extensions: - - ```shell - gitlab-psql -d gitlabhq_production - ``` +1. Find the primary database node: ```shell - CREATE EXTENSION pg_trgm; - CREATE EXTENSION btree_gist; + gitlab-ctl get-postgresql-primary ``` -1. On `10.6.0.32`, our first standby database: +1. On the primary database node: - Make this node a standby of the primary: + Enable the `pg_trgm` and `btree_gist` extensions: ```shell - gitlab-ctl repmgr standby setup 10.6.0.21 + gitlab-psql -d gitlabhq_production ``` -1. On `10.6.0.33`, our second standby database: - - Make this node a standby of the primary: - ```shell - gitlab-ctl repmgr standby setup 10.6.0.21 + CREATE EXTENSION pg_trgm; + CREATE EXTENSION btree_gist; ``` 1. On `10.6.0.41`, our application server: @@ -802,15 +619,15 @@ After deploying the configuration follow these steps: This example uses 3 PostgreSQL servers, and 1 application node (with PgBouncer setup alongside). It differs from the [recommended setup](#example-recommended-setup) by moving the Consul servers into the same servers we use for PostgreSQL. -The trade-off is between reducing server counts, against the increased operational complexity of needing to deal with PostgreSQL [failover](#failover-procedure) and [restore](#restore-procedure) procedures in addition to [Consul outage recovery](../consul.md#outage-recovery) on the same set of machines. +The trade-off is between reducing server counts, against the increased operational complexity of needing to deal with PostgreSQL [failover](#manual-failover-procedure-for-patroni) procedures in addition to [Consul outage recovery](../consul.md#outage-recovery) on the same set of machines. In this example we start with all servers on the same 10.6.0.0/16 private network range, they can connect to each freely other on those addresses. Here is a list and description of each machine and the assigned IP: -- `10.6.0.21`: PostgreSQL master -- `10.6.0.22`: PostgreSQL secondary -- `10.6.0.23`: PostgreSQL secondary +- `10.6.0.21`: PostgreSQL 1 +- `10.6.0.22`: PostgreSQL 2 +- `10.6.0.23`: PostgreSQL 3 - `10.6.0.31`: GitLab application All passwords are set to `toomanysecrets`, please do not use this password or derived hashes. @@ -821,9 +638,7 @@ Please note that after the initial configuration, if a failover occurs, the Post #### Example minimal configuration for database servers -##### Primary node - -On primary database node edit `/etc/gitlab/gitlab.rb`: +On database nodes edit `/etc/gitlab/gitlab.rb`: ```ruby # Disable all components except PostgreSQL, Repmgr, and Consul @@ -833,7 +648,9 @@ roles ['postgres_role'] postgresql['listen_address'] = '0.0.0.0' postgresql['hot_standby'] = 'on' postgresql['wal_level'] = 'replica' -postgresql['shared_preload_libraries'] = 'repmgr_funcs' + +# Enable Patroni (which automatically disables Repmgr). +patroni['enable'] = true # Disable automatic database migrations gitlab_rails['auto_migrate'] = false @@ -843,10 +660,9 @@ consul['services'] = %w(postgresql) postgresql['pgbouncer_user_password'] = '771a8625958a529132abe6f1a4acb19c' postgresql['sql_user_password'] = '450409b85a0223a214b5fb1484f34d0f' -postgresql['max_wal_senders'] = 4 +patroni['postgresql']['max_wal_senders'] = 4 postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/16) -repmgr['trust_auth_cidr_addresses'] = %w(10.6.0.0/16) consul['configuration'] = { server: true, @@ -856,16 +672,6 @@ consul['configuration'] = { [Reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. -##### Secondary nodes - -On secondary nodes, edit `/etc/gitlab/gitlab.rb` and add all the information added -to primary node, noted above. In addition, append the following configuration - -```ruby -# Specify if a node should attempt to be master on initialization -repmgr['master_on_initialization'] = false -``` - #### Example minimal configuration for application server On the server edit `/etc/gitlab/gitlab.rb`: @@ -908,249 +714,10 @@ consul['configuration'] = { The manual steps for this configuration are the same as for the [example recommended setup](#example-recommended-setup-manual-steps). -### Failover procedure - -By default, if the master database fails, `repmgrd` should promote one of the -standby nodes to master automatically, and Consul will update PgBouncer with -the new master. - -If you need to failover manually, you have two options: - -**Shutdown the current master database** - -Run: - -```shell -gitlab-ctl stop postgresql -``` - -The automated failover process will see this and failover to one of the -standby nodes. - -**Or perform a manual failover** - -1. Ensure the old master node is not still active. -1. Login to the server that should become the new master and run: - - ```shell - gitlab-ctl repmgr standby promote - ``` - -1. If there are any other standby servers in the cluster, have them follow - the new master server: - - ```shell - gitlab-ctl repmgr standby follow NEW_MASTER - ``` - -### Restore procedure - -If a node fails, it can be removed from the cluster, or added back as a standby -after it has been restored to service. - -#### Remove a standby from the cluster - - From any other node in the cluster, run: - - ```shell - gitlab-ctl repmgr standby unregister --node=X - ``` - - where X is the value of node in `repmgr.conf` on the old server. - - To find this, you can use: - - ```shell - awk -F = '$1 == "node" { print $2 }' /var/opt/gitlab/postgresql/repmgr.conf - ``` - - It will output something like: - - ```plaintext - 959789412 - ``` - - Then you will use this ID to unregister the node: - - ```shell - gitlab-ctl repmgr standby unregister --node=959789412 - ``` - -#### Add a node as a standby server - - From the standby node, run: - - ```shell - gitlab-ctl repmgr standby follow NEW_MASTER - gitlab-ctl restart repmgrd - ``` - - WARNING: - When the server is brought back online, and before - you switch it to a standby node, repmgr will report that there are two masters. - If there are any clients that are still attempting to write to the old master, - this will cause a split, and the old master will need to be resynced from - scratch by performing a `gitlab-ctl repmgr standby setup NEW_MASTER`. - -#### Add a failed master back into the cluster as a standby node - - Once `repmgrd` and PostgreSQL are running, the node will need to follow the new - as a standby node. - - ```shell - gitlab-ctl repmgr standby follow NEW_MASTER - ``` - - Once the node is following the new master as a standby, the node needs to be - [unregistered from the cluster on the new master node](#remove-a-standby-from-the-cluster). - - Once the old master node has been unregistered from the cluster, it will need - to be setup as a new standby: - - ```shell - gitlab-ctl repmgr standby setup NEW_MASTER - ``` - - Failure to unregister and read the old master node can lead to subsequent failovers - not working. - -### Alternate configurations - -#### Database authorization - -By default, we give any host on the database network the permission to perform -repmgr operations using PostgreSQL's `trust` method. If you do not want this -level of trust, there are alternatives. - -You can trust only the specific nodes that will be database clusters, or you -can require md5 authentication. - -#### Trust specific addresses - -If you know the IP address, or FQDN of all database and PgBouncer nodes in the -cluster, you can trust only those nodes. - -In `/etc/gitlab/gitlab.rb` on all of the database nodes, set -`repmgr['trust_auth_cidr_addresses']` to an array of strings containing all of -the addresses. - -If setting to a node's FQDN, they must have a corresponding PTR record in DNS. -If setting to a node's IP address, specify it as `XXX.XXX.XXX.XXX/32`. - -For example: - -```ruby -repmgr['trust_auth_cidr_addresses'] = %w(192.168.1.44/32 db2.example.com) -``` - -#### MD5 Authentication - -If you are running on an untrusted network, repmgr can use md5 authentication -with a [`.pgpass` file](https://www.postgresql.org/docs/11/libpq-pgpass.html) -to authenticate. - -You can specify by IP address, FQDN, or by subnet, using the same format as in -the previous section: - -1. On the current master node, create a password for the `gitlab` and - `gitlab_repmgr` user: - - ```shell - gitlab-psql -d template1 - template1=# \password gitlab_repmgr - Enter password: **** - Confirm password: **** - template1=# \password gitlab - ``` - -1. On each database node: - - 1. Edit `/etc/gitlab/gitlab.rb`: - 1. Ensure `repmgr['trust_auth_cidr_addresses']` is **not** set - 1. Set `postgresql['md5_auth_cidr_addresses']` to the desired value - 1. Set `postgresql['sql_replication_user'] = 'gitlab_repmgr'` - 1. Reconfigure with `gitlab-ctl reconfigure` - 1. Restart PostgreSQL with `gitlab-ctl restart postgresql` - - 1. Create a `.pgpass` file. Enter the `gitlab_repmgr` password twice to - when asked: - - ```shell - gitlab-ctl write-pgpass --user gitlab_repmgr --hostuser gitlab-psql --database '*' - ``` - -1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`: - 1. Ensure `gitlab_rails['db_password']` is set to the plaintext password for - the `gitlab` database user - 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect - -## Troubleshooting - -### Consul and PostgreSQL changes not taking effect - -Due to the potential impacts, `gitlab-ctl reconfigure` only reloads Consul and PostgreSQL, it will not restart the services. However, not all changes can be activated by reloading. - -To restart either service, run `gitlab-ctl restart SERVICE` - -For PostgreSQL, it is usually safe to restart the master node by default. Automatic failover defaults to a 1 minute timeout. Provided the database returns before then, nothing else needs to be done. To be safe, you can stop `repmgrd` on the standby nodes first with `gitlab-ctl stop repmgrd`, then start afterwards with `gitlab-ctl start repmgrd`. - -On the Consul server nodes, it is important to [restart the Consul service](../consul.md#restart-consul) in a controlled manner. - -### `gitlab-ctl repmgr-check-master` command produces errors - -If this command displays errors about database permissions it is likely that something failed during -install, resulting in the `gitlab-consul` database user getting incorrect permissions. Follow these -steps to fix the problem: - -1. On the master database node, connect to the database prompt - `gitlab-psql -d template1` -1. Delete the `gitlab-consul` user - `DROP USER "gitlab-consul";` -1. Exit the database prompt - `\q` -1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) and the user will be re-added with the proper permissions. -1. Change to the `gitlab-consul` user - `su - gitlab-consul` -1. Try the check command again - `gitlab-ctl repmgr-check-master`. - -Now there should not be errors. If errors still occur then there is another problem. - -### PgBouncer error `ERROR: pgbouncer cannot connect to server` - -You may get this error when running `gitlab-rake gitlab:db:configure` or you -may see the error in the PgBouncer log file. - -```plaintext -PG::ConnectionBad: ERROR: pgbouncer cannot connect to server -``` - -The problem may be that your PgBouncer node's IP address is not included in the -`trust_auth_cidr_addresses` setting in `/etc/gitlab/gitlab.rb` on the database nodes. - -You can confirm that this is the issue by checking the PostgreSQL log on the master -database node. If you see the following error then `trust_auth_cidr_addresses` -is the problem. - -```plaintext -2018-03-29_13:59:12.11776 FATAL: no pg_hba.conf entry for host "123.123.123.123", user "pgbouncer", database "gitlabhq_production", SSL off -``` - -To fix the problem, add the IP address to `/etc/gitlab/gitlab.rb`. - -```ruby -postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 <other_cidrs>) -``` - -[Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. - -### Issues with other components - -If you're running into an issue with a component not outlined here, be sure to check the troubleshooting section of their specific documentation page: - -- [Consul](../consul.md#troubleshooting-consul) -- [PostgreSQL](https://docs.gitlab.com/omnibus/settings/database.html#troubleshooting) - ## Patroni NOTE: -Starting from GitLab 13.1, Patroni is available for **experimental** use to replace repmgr. Due to its -experimental nature, Patroni support is **subject to change without notice.** +Using Patroni instead of Repmgr is supported for PostgreSQL 11 and required for PostgreSQL 12. Patroni is an opinionated solution for PostgreSQL high-availability. It takes the control of PostgreSQL, overrides its configuration and manages its lifecycle (start, stop, restart). This is a more active approach when compared to repmgr. @@ -1174,80 +741,44 @@ functional or does not have a leader, Patroni and by extension PostgreSQL will n API which can be accessed via its [default port](https://docs.gitlab.com/omnibus/package-information/defaults.html#patroni) on each node. -### Configuring Patroni cluster - -You must enable Patroni explicitly to be able to use it (with `patroni['enable'] = true`). When Patroni is enabled -repmgr will be disabled automatically. +### Selecting the appropriate Patroni replication method -Any PostgreSQL configuration item that controls replication, for example `wal_level`, `max_wal_senders`, etc, are strictly -controlled by Patroni and will override the original settings that you make with the `postgresql[...]` configuration key. -Hence, they are all separated and placed under `patroni['postgresql'][...]`. This behavior is limited to replication. -Patroni honours any other PostgreSQL configuration that was made with the `postgresql[...]` configuration key. For example, -`max_wal_senders` by default is set to `5`. If you wish to change this you must set it with the `patroni['postgresql']['max_wal_senders']` -configuration key. +[Review the Patroni documentation carefully](https://patroni.readthedocs.io/en/latest/SETTINGS.html#postgresql) +before making changes as **_some of the options carry a risk of potential data +loss if not fully understood_**. The [replication mode](https://patroni.readthedocs.io/en/latest/replication_modes.html) +configured determines the amount of tolerable data loss. -The configuration of Patroni node is very similar to a repmgr but shorter. When Patroni is enabled, first you can ignore -any replication setting of PostgreSQL (it will be overwritten anyway). Then you can remove any `repmgr[...]` or -repmgr-specific configuration as well. Especially, make sure that you remove `postgresql['shared_preload_libraries'] = 'repmgr_funcs'`. +WARNING: +Replication is not a backup strategy! There is no replacement for a well-considered and tested backup solution. -Here is an example similar to [the one that was done with repmgr](#configuring-the-database-nodes): +Omnibus GitLab defaults [`synchronous_commit`](https://www.postgresql.org/docs/11/runtime-config-wal.html#GUC-SYNCHRONOUS-COMMIT) to `on`. ```ruby -# Disable all components except PostgreSQL and Repmgr and Consul -roles['postgres_role'] +postgresql['synchronous_commit'] = 'on' +gitlab['geo-postgresql']['synchronous_commit'] = 'on' +``` -# Enable Patroni -patroni['enable'] = true +#### Customizing Patroni failover behavior -# PostgreSQL configuration -postgresql['listen_address'] = '0.0.0.0' +Omnibus GitLab exposes several options allowing more control over the [Patroni restoration process](#recovering-the-patroni-cluster). -# Disable automatic database migrations -gitlab_rails['auto_migrate'] = false +Each option is shown below with its default value in `/etc/gitlab/gitlab.rb`. -# Configure the Consul agent -consul['services'] = %w(postgresql) - -# START user configuration -# Please set the real values as explained in Required Information section -# -# Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value -postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH' -# Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value -postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH' - -# Replace X with value of number of db nodes + 1 (OPTIONAL the default value is 5) -patroni['postgresql']['max_wal_senders'] = X -patroni['postgresql']['max_replication_slots'] = X - -# Replace XXX.XXX.XXX.XXX/YY with Network Address -postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY) - -# Replace placeholders: -# -# Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z -# with the addresses gathered for CONSUL_SERVER_NODES -consul['configuration'] = { - retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z) -} -# -# END user configuration +```ruby +patroni['use_pg_rewind'] = true +patroni['remove_data_directory_on_rewind_failure'] = false +patroni['remove_data_directory_on_diverged_timelines'] = false ``` -You do not need an additional or different configuration for replica nodes. As a matter of fact, you don't have to have -a predetermined primary node. Therefore all database nodes use the same configuration. +[The upstream documentation will always be more up to date](https://patroni.readthedocs.io/en/latest/SETTINGS.html#postgresql), but the table below should provide a minimal overview of functionality. -Once the configuration of a node is done, you must [reconfigure Omnibus GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) -on each node for the changes to take effect. +|Setting|Overview| +|-|-| +|`use_pg_rewind`|Try running `pg_rewind` on the former cluster leader before it rejoins the database cluster.| +|`remove_data_directory_on_rewind_failure`|If `pg_rewind` fails, remove the local PostgreSQL data directory and re-replicate from the current cluster leader.| +|`remove_data_directory_on_diverged_timelines`|If `pg_rewind` cannot be used and the former leader's timeline has diverged from the current one, then delete the local data directory and re-replicate from the current cluster leader.| -Generally, when Consul cluster is ready, the first node that [reconfigures](../restart_gitlab.md#omnibus-gitlab-reconfigure) -becomes the leader. You do not need to sequence the nodes reconfiguration. You can run them in parallel or in any order. -If you choose an arbitrary order you do not have any predetermined master. - -As opposed to repmgr, once the nodes are reconfigured you do not need any further action or additional command to join -the replicas. - -#### Database authorization for Patroni +### Database authorization for Patroni Patroni uses Unix socket to manage PostgreSQL instance. Therefore, the connection from the `local` socket must be trusted. @@ -1297,6 +828,16 @@ a manual one, where you have two slightly different options: For further details on this subject, see the [Patroni documentation](https://patroni.readthedocs.io/en/latest/rest_api.html#switchover-and-failover-endpoints). +#### Geo secondary site considerations + +Similar to `repmgr`, when a Geo secondary site is replicating from a primary site that uses `Patroni` and `PgBouncer`, [replicating through PgBouncer is not supported](https://github.com/pgbouncer/pgbouncer/issues/382#issuecomment-517911529) and the secondary must replicate directly from the leader node in the `Patroni` cluster. Therefore, when there is an automatic or manual failover in the `Patroni` cluster, you will need to manually re-point your secondary site to replicate from the new leader with: + +```shell +sudo gitlab-ctl replicate-geo-database --host=<new_leader_ip> --replication-slot=<slot_name> +``` + +Otherwise, the replication will not happen anymore, even if the original node gets re-added as a follower node. This will re-sync your secondary site database and may take a long time depending on the amount of data to sync. You may also need to run `gitlab-ctl reconfigure` if replication is still not working after re-syncing. + ### Recovering the Patroni cluster To recover the old primary and rejoin it to the cluster as a replica, you can simply start Patroni with: @@ -1363,9 +904,9 @@ You can switch an exiting database cluster to use Patroni instead of repmgr with ### Upgrading PostgreSQL major version in a Patroni cluster -As of GitLab 13.3, PostgreSQL 11.7 and 12.3 are both shipped with Omnibus GitLab. GitLab still -uses PostgreSQL 11 by default. Therefore `gitlab-ctl pg-upgrade` does not automatically upgrade -to PostgreSQL 12. If you want to upgrade to PostgreSQL 12, you must ask for it explicitly. +As of GitLab 13.3, PostgreSQL 11.7 and 12.3 are both shipped with Omnibus GitLab, and as of GitLab 13.7 +PostgreSQL 12 is used by default. If you want to upgrade to PostgreSQL 12 in versions prior to GitLab 13.7, +you must ask for it explicitly. WARNING: The procedure for upgrading PostgreSQL in a Patroni cluster is different than when upgrading using repmgr. @@ -1450,3 +991,448 @@ NOTE: Reverting PostgreSQL upgrade with `gitlab-ctl revert-pg-upgrade` has the same considerations as `gitlab-ctl pg-upgrade`. You should follow the same procedure by first stopping the replicas, then reverting the leader, and finally reverting the replicas. + +## Repmgr + +NOTE: +Using Patroni instead of Repmgr is supported for PostgreSQL 11 and required for PostgreSQL 12. + +### Configuring Repmgr Nodes + +1. On the master database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: + + ```ruby + # Disable all components except PostgreSQL and Repmgr and Consul + roles ['postgres_role'] + + # PostgreSQL configuration + postgresql['listen_address'] = '0.0.0.0' + postgresql['hot_standby'] = 'on' + postgresql['wal_level'] = 'replica' + postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Disable automatic database migrations + gitlab_rails['auto_migrate'] = false + + # Configure the Consul agent + consul['services'] = %w(postgresql) + + # START user configuration + # Please set the real values as explained in Required Information section + # + # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value + postgresql['pgbouncer_user_password'] = 'PGBOUNCER_PASSWORD_HASH' + # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value + postgresql['sql_user_password'] = 'POSTGRESQL_PASSWORD_HASH' + # Replace X with value of number of db nodes + 1 + postgresql['max_wal_senders'] = X + postgresql['max_replication_slots'] = X + + # Replace XXX.XXX.XXX.XXX/YY with Network Address + postgresql['trust_auth_cidr_addresses'] = %w(XXX.XXX.XXX.XXX/YY) + repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 XXX.XXX.XXX.XXX/YY) + + # Replace placeholders: + # + # Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z + # with the addresses gathered for CONSUL_SERVER_NODES + consul['configuration'] = { + retry_join: %w(Y.Y.Y.Y consul1.gitlab.example.com Z.Z.Z.Z) + } + # + # END user configuration + ``` + + > `postgres_role` was introduced with GitLab 10.3 + +1. On secondary nodes, add all the configuration specified above for primary node + to `/etc/gitlab/gitlab.rb`. In addition, append the following configuration + to inform `gitlab-ctl` that they are standby nodes initially and it need not + attempt to register them as primary node + + ```ruby + # Specify if a node should attempt to be master on initialization + repmgr['master_on_initialization'] = false + ``` + +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. +1. [Enable Monitoring](#enable-monitoring) + +> Please note: +> +> - If you want your database to listen on a specific interface, change the configuration: +> `postgresql['listen_address'] = '0.0.0.0'`. +> - If your PgBouncer service runs under a different user account, +> you also need to specify: `postgresql['pgbouncer_user'] = PGBOUNCER_USERNAME` in +> your configuration. + +#### Database nodes post-configuration + +##### Primary node + +Select one node as a primary node. + +1. Open a database prompt: + + ```shell + gitlab-psql -d gitlabhq_production + ``` + +1. Enable the `pg_trgm` extension: + + ```shell + CREATE EXTENSION pg_trgm; + ``` + +1. Enable the `btree_gist` extension: + + ```shell + CREATE EXTENSION btree_gist; + ``` + +1. Exit the database prompt by typing `\q` and Enter. + +1. Verify the cluster is initialized with one node: + + ```shell + gitlab-ctl repmgr cluster show + ``` + + The output should be similar to the following: + + ```plaintext + Role | Name | Upstream | Connection String + ----------+----------|----------|---------------------------------------- + * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr + ``` + +1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will + refer to the hostname in the next section as `MASTER_NODE_NAME`. If the value + is not an IP address, it will need to be a resolvable name (via DNS or + `/etc/hosts`) + +##### Secondary nodes + +1. Set up the repmgr standby: + + ```shell + gitlab-ctl repmgr standby setup MASTER_NODE_NAME + ``` + + Do note that this will remove the existing data on the node. The command + has a wait time. + + The output should be similar to the following: + + ```console + # gitlab-ctl repmgr standby setup MASTER_NODE_NAME + Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data + If this is not what you want, hit Ctrl-C now to exit + To skip waiting, rerun with the -w option + Sleeping for 30 seconds + Stopping the database + Removing the data + Cloning the data + Starting the database + Registering the node with the cluster + ok: run: repmgrd: (pid 19068) 0s + ``` + +1. Verify the node now appears in the cluster: + + ```shell + gitlab-ctl repmgr cluster show + ``` + + The output should be similar to the following: + + ```plaintext + Role | Name | Upstream | Connection String + ----------+---------|-----------|------------------------------------------------ + * master | MASTER | | host=MASTER_NODE_NAME user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host=STANDBY_HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr + ``` + +Repeat the above steps on all secondary nodes. + +#### Database checkpoint + +Before moving on, make sure the databases are configured correctly. Run the +following command on the **primary** node to verify that replication is working +properly: + +```shell +gitlab-ctl repmgr cluster show +``` + +The output should be similar to: + +```plaintext +Role | Name | Upstream | Connection String +----------+--------------|--------------|-------------------------------------------------------------------- +* master | MASTER | | host=MASTER port=5432 user=gitlab_repmgr dbname=gitlab_repmgr + standby | STANDBY | MASTER | host=STANDBY port=5432 user=gitlab_repmgr dbname=gitlab_repmgr +``` + +If the 'Role' column for any node says "FAILED", check the +[Troubleshooting section](#troubleshooting) before proceeding. + +Also, check that the check master command works successfully on each node: + +```shell +su - gitlab-consul +gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' +``` + +This command relies on exit codes to tell Consul whether a particular node is a master +or secondary. The most important thing here is that this command does not produce errors. +If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions. +Check the [Troubleshooting section](#troubleshooting) before proceeding. + +### Repmgr failover procedure + +By default, if the master database fails, `repmgrd` should promote one of the +standby nodes to master automatically, and Consul will update PgBouncer with +the new master. + +If you need to failover manually, you have two options: + +**Shutdown the current master database** + +Run: + +```shell +gitlab-ctl stop postgresql +``` + +The automated failover process will see this and failover to one of the +standby nodes. + +**Or perform a manual failover** + +1. Ensure the old master node is not still active. +1. Login to the server that should become the new master and run: + + ```shell + gitlab-ctl repmgr standby promote + ``` + +1. If there are any other standby servers in the cluster, have them follow + the new master server: + + ```shell + gitlab-ctl repmgr standby follow NEW_MASTER + ``` + +#### Geo secondary site considerations + +When a Geo secondary site is replicating from a primary site that uses `repmgr` and `PgBouncer`, [replicating through PgBouncer is not supported](https://github.com/pgbouncer/pgbouncer/issues/382#issuecomment-517911529) and the secondary must replicate directly from the leader node in the `repmgr` cluster. Therefore, when there is a failover in the `repmgr` cluster, you will need to manually re-point your secondary site to replicate from the new leader with: + +```shell +sudo gitlab-ctl replicate-geo-database --host=<new_leader_ip> --replication-slot=<slot_name> +``` + +Otherwise, the replication will not happen anymore, even if the original node gets re-added as a follower node. This will re-sync your secondary site database and may take a long time depending on the amount of data to sync. You may also need to run `gitlab-ctl reconfigure` if replication is still not working after re-syncing. + +### Repmgr Restore procedure + +If a node fails, it can be removed from the cluster, or added back as a standby +after it has been restored to service. + +#### Remove a standby from the cluster + + From any other node in the cluster, run: + + ```shell + gitlab-ctl repmgr standby unregister --node=X + ``` + + where X is the value of node in `repmgr.conf` on the old server. + + To find this, you can use: + + ```shell + awk -F = '$1 == "node" { print $2 }' /var/opt/gitlab/postgresql/repmgr.conf + ``` + + It will output something like: + + ```plaintext + 959789412 + ``` + + Then you will use this ID to unregister the node: + + ```shell + gitlab-ctl repmgr standby unregister --node=959789412 + ``` + +#### Add a node as a standby server + + From the standby node, run: + + ```shell + gitlab-ctl repmgr standby follow NEW_MASTER + gitlab-ctl restart repmgrd + ``` + + WARNING: + When the server is brought back online, and before + you switch it to a standby node, repmgr will report that there are two masters. + If there are any clients that are still attempting to write to the old master, + this will cause a split, and the old master will need to be resynced from + scratch by performing a `gitlab-ctl repmgr standby setup NEW_MASTER`. + +#### Add a failed master back into the cluster as a standby node + + Once `repmgrd` and PostgreSQL are running, the node will need to follow the new + as a standby node. + + ```shell + gitlab-ctl repmgr standby follow NEW_MASTER + ``` + + Once the node is following the new master as a standby, the node needs to be + [unregistered from the cluster on the new master node](#remove-a-standby-from-the-cluster). + + Once the old master node has been unregistered from the cluster, it will need + to be setup as a new standby: + + ```shell + gitlab-ctl repmgr standby setup NEW_MASTER + ``` + + Failure to unregister and read the old master node can lead to subsequent failovers + not working. + +### Alternate configurations + +#### Database authorization + +By default, we give any host on the database network the permission to perform +repmgr operations using PostgreSQL's `trust` method. If you do not want this +level of trust, there are alternatives. + +You can trust only the specific nodes that will be database clusters, or you +can require md5 authentication. + +#### Trust specific addresses + +If you know the IP address, or FQDN of all database and PgBouncer nodes in the +cluster, you can trust only those nodes. + +In `/etc/gitlab/gitlab.rb` on all of the database nodes, set +`repmgr['trust_auth_cidr_addresses']` to an array of strings containing all of +the addresses. + +If setting to a node's FQDN, they must have a corresponding PTR record in DNS. +If setting to a node's IP address, specify it as `XXX.XXX.XXX.XXX/32`. + +For example: + +```ruby +repmgr['trust_auth_cidr_addresses'] = %w(192.168.1.44/32 db2.example.com) +``` + +#### MD5 Authentication + +If you are running on an untrusted network, repmgr can use md5 authentication +with a [`.pgpass` file](https://www.postgresql.org/docs/11/libpq-pgpass.html) +to authenticate. + +You can specify by IP address, FQDN, or by subnet, using the same format as in +the previous section: + +1. On the current master node, create a password for the `gitlab` and + `gitlab_repmgr` user: + + ```shell + gitlab-psql -d template1 + template1=# \password gitlab_repmgr + Enter password: **** + Confirm password: **** + template1=# \password gitlab + ``` + +1. On each database node: + + 1. Edit `/etc/gitlab/gitlab.rb`: + 1. Ensure `repmgr['trust_auth_cidr_addresses']` is **not** set + 1. Set `postgresql['md5_auth_cidr_addresses']` to the desired value + 1. Set `postgresql['sql_replication_user'] = 'gitlab_repmgr'` + 1. Reconfigure with `gitlab-ctl reconfigure` + 1. Restart PostgreSQL with `gitlab-ctl restart postgresql` + + 1. Create a `.pgpass` file. Enter the `gitlab_repmgr` password twice to + when asked: + + ```shell + gitlab-ctl write-pgpass --user gitlab_repmgr --hostuser gitlab-psql --database '*' + ``` + +1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`: + 1. Ensure `gitlab_rails['db_password']` is set to the plaintext password for + the `gitlab` database user + 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect + +## Troubleshooting + +### Consul and PostgreSQL changes not taking effect + +Due to the potential impacts, `gitlab-ctl reconfigure` only reloads Consul and PostgreSQL, it will not restart the services. However, not all changes can be activated by reloading. + +To restart either service, run `gitlab-ctl restart SERVICE` + +For PostgreSQL, it is usually safe to restart the master node by default. Automatic failover defaults to a 1 minute timeout. Provided the database returns before then, nothing else needs to be done. To be safe, you can stop `repmgrd` on the standby nodes first with `gitlab-ctl stop repmgrd`, then start afterwards with `gitlab-ctl start repmgrd`. + +On the Consul server nodes, it is important to [restart the Consul service](../consul.md#restart-consul) in a controlled manner. + +### `gitlab-ctl repmgr-check-master` command produces errors + +If this command displays errors about database permissions it is likely that something failed during +install, resulting in the `gitlab-consul` database user getting incorrect permissions. Follow these +steps to fix the problem: + +1. On the master database node, connect to the database prompt - `gitlab-psql -d template1` +1. Delete the `gitlab-consul` user - `DROP USER "gitlab-consul";` +1. Exit the database prompt - `\q` +1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) and the user will be re-added with the proper permissions. +1. Change to the `gitlab-consul` user - `su - gitlab-consul` +1. Try the check command again - `gitlab-ctl repmgr-check-master`. + +Now there should not be errors. If errors still occur then there is another problem. + +### PgBouncer error `ERROR: pgbouncer cannot connect to server` + +You may get this error when running `gitlab-rake gitlab:db:configure` or you +may see the error in the PgBouncer log file. + +```plaintext +PG::ConnectionBad: ERROR: pgbouncer cannot connect to server +``` + +The problem may be that your PgBouncer node's IP address is not included in the +`trust_auth_cidr_addresses` setting in `/etc/gitlab/gitlab.rb` on the database nodes. + +You can confirm that this is the issue by checking the PostgreSQL log on the master +database node. If you see the following error then `trust_auth_cidr_addresses` +is the problem. + +```plaintext +2018-03-29_13:59:12.11776 FATAL: no pg_hba.conf entry for host "123.123.123.123", user "pgbouncer", database "gitlabhq_production", SSL off +``` + +To fix the problem, add the IP address to `/etc/gitlab/gitlab.rb`. + +```ruby +postgresql['trust_auth_cidr_addresses'] = %w(123.123.123.123/32 <other_cidrs>) +``` + +[Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + +### Issues with other components + +If you're running into an issue with a component not outlined here, be sure to check the troubleshooting section of their specific documentation page: + +- [Consul](../consul.md#troubleshooting-consul) +- [PostgreSQL](https://docs.gitlab.com/omnibus/settings/database.html#troubleshooting) diff --git a/doc/administration/raketasks/check.md b/doc/administration/raketasks/check.md index 25869fd425d..41defd89df5 100644 --- a/doc/administration/raketasks/check.md +++ b/doc/administration/raketasks/check.md @@ -51,6 +51,62 @@ sudo gitlab-rake gitlab:git:fsck sudo -u git -H bundle exec rake gitlab:git:fsck RAILS_ENV=production ``` +## Checksum of repository refs + +One Git repository can be compared to another by checksumming all refs of each +repository. If both repositories have the same refs, and if both repositories +pass an integrity check, then we can be confident that both repositories are the +same. + +For example, this can be used to compare a backup of a repository against the +source repository. + +### Check all GitLab repositories + +This task loops through all repositories on the GitLab server and outputs +checksums in the format `<PROJECT ID>,<CHECKSUM>`. + +- If a repository doesn't exist, the project ID will have a blank checksum. +- If a repository exists but is empty, the output checksum is `0000000000000000000000000000000000000000`. +- Projects which don't exist are skipped. + +**Omnibus Installation** + +```shell +sudo gitlab-rake gitlab:git:checksum_projects +``` + +**Source Installation** + +```shell +sudo -u git -H bundle exec rake gitlab:git:checksum_projects RAILS_ENV=production +``` + +For example, if: + +- Project with ID#2 doesn't exist, it will be skipped. +- Project with ID#4 doesn't have a repository, its checksum will be blank. +- Project with ID#5 has an empty repository, its checksum will be `0000000000000000000000000000000000000000`. + +The output would then look something like: + +```plaintext +1,cfa3f06ba235c13df0bb28e079bcea62c5848af2 +3,3f3fb58a8106230e3a6c6b48adc2712fb3b6ef87 +4, +5,0000000000000000000000000000000000000000 +6,6c6b48adc2712fb3b6ef87cfa3f06ba235c13df0 +``` + +### Check specific GitLab repositories + +Optionally, specific project IDs can be checksummed by setting an environment +variable `CHECKSUM_PROJECT_IDS` with a list of comma-separated integers, for example: + +```shell +CHECKSUM_PROJECT_IDS="1,3" sudo gitlab-rake gitlab:git:checksum_projects +``` + ## Uploaded files integrity Various types of files can be uploaded to a GitLab installation by users. @@ -158,7 +214,7 @@ If the issue persists, try triggering `gc` via the ```ruby p = Project.find_by_path("project-name") -Projects::HousekeepingService.new(p, :gc).execute +Repositories::HousekeepingService.new(p, :gc).execute ``` ### Delete references to missing remote uploads diff --git a/doc/administration/raketasks/github_import.md b/doc/administration/raketasks/github_import.md index 5c0bc721a9a..630570cb81f 100644 --- a/doc/administration/raketasks/github_import.md +++ b/doc/administration/raketasks/github_import.md @@ -19,7 +19,7 @@ before/after the brackets. Also, some shells (for example, `zsh`) can interpret ## Caveats -If the GitHub [rate limit](https://developer.github.com/v3/#rate-limiting) is reached while importing, +If the GitHub [rate limit](https://docs.github.com/v3/#rate-limiting) is reached while importing, the importing process waits (`sleep()`) until it can continue importing. ## Importing multiple projects diff --git a/doc/administration/raketasks/storage.md b/doc/administration/raketasks/storage.md index c7afebf15bd..158b541b36b 100644 --- a/doc/administration/raketasks/storage.md +++ b/doc/administration/raketasks/storage.md @@ -82,8 +82,8 @@ Support for legacy storage will be removed in GitLab 14.0. If you're on GitLab The option to choose between hashed and legacy storage in the admin area has been disabled. -This task must be run on any machine that has Rails/Sidekiq configured and will -schedule all your existing projects and attachments associated with it to be +This task must be run on any machine that has Rails/Sidekiq configured and will +schedule all your existing projects and attachments associated with it to be migrated to the **Hashed** storage type: - **Omnibus installation** diff --git a/doc/administration/reference_architectures/10k_users.md b/doc/administration/reference_architectures/10k_users.md index 216d3867d0a..afa53b5efa8 100644 --- a/doc/administration/reference_architectures/10k_users.md +++ b/doc/administration/reference_architectures/10k_users.md @@ -422,9 +422,9 @@ install the necessary dependencies from step 1, and add the GitLab package repository from step 2. When installing GitLab in the second step, do not supply the `EXTERNAL_URL` value. -#### PostgreSQL primary node +#### PostgreSQL nodes -1. SSH in to the PostgreSQL primary node. +1. SSH in to one of the PostgreSQL nodes. 1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default username of `gitlab` (recommended). The command will request a password and confirmation. Use the value that is output by this command in the next @@ -452,23 +452,33 @@ in the second step, do not supply the `EXTERNAL_URL` value. sudo gitlab-ctl pg-password-md5 gitlab-consul ``` -1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: +1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: ```ruby - # Disable all components except PostgreSQL and Repmgr and Consul + # Disable all components except PostgreSQL, Patroni, and Consul roles ['postgres_role'] # PostgreSQL configuration postgresql['listen_address'] = '0.0.0.0' - postgresql['hot_standby'] = 'on' - postgresql['wal_level'] = 'replica' - postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Enable Patroni + patroni['enable'] = true + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + patroni['postgresql']['max_wal_senders'] = 4 + patroni['postgresql']['max_replication_slots'] = 4 + # Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691. + patroni['postgresql']['max_connections'] = 500 # Disable automatic database migrations gitlab_rails['auto_migrate'] = false # Configure the Consul agent + consul['enable'] = true consul['services'] = %w(postgresql) + ## Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true # START user configuration # Please set the real values as explained in Required Information section @@ -477,18 +487,9 @@ in the second step, do not supply the `EXTERNAL_URL` value. postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>' # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value postgresql['sql_user_password'] = '<postgresql_password_hash>' - # Set `max_wal_senders` to one more than the number of database nodes in the cluster. - # This is used to prevent replication from using up all of the - # available database connections. - postgresql['max_wal_senders'] = 4 - postgresql['max_replication_slots'] = 4 # Replace XXX.XXX.XXX.XXX/YY with Network Address postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) - repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - - ## Enable service discovery for Prometheus - consul['monitoring_service_discovery'] = true # Set the network addresses that the exporters will listen on for monitoring node_exporter['listen_address'] = '0.0.0.0:9100' @@ -503,70 +504,9 @@ in the second step, do not supply the `EXTERNAL_URL` value. # END user configuration ``` -1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace - the file of the same name on this server. If that file is not on this server, - add the file from your Consul server to this server. - -1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. - -<div align="right"> - <a type="button" class="btn btn-default" href="#setup-components"> - Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> - </a> -</div> - -#### PostgreSQL secondary nodes - -1. On both the secondary nodes, add the same configuration specified above for the primary node - with an additional setting (`repmgr['master_on_initialization'] = false`) that will inform `gitlab-ctl` that they are standby nodes initially - and there's no need to attempt to register them as a primary node: - - ```ruby - # Disable all components except PostgreSQL and Repmgr and Consul - roles ['postgres_role'] - - # PostgreSQL configuration - postgresql['listen_address'] = '0.0.0.0' - postgresql['hot_standby'] = 'on' - postgresql['wal_level'] = 'replica' - postgresql['shared_preload_libraries'] = 'repmgr_funcs' - - # Disable automatic database migrations - gitlab_rails['auto_migrate'] = false - - # Configure the Consul agent - consul['services'] = %w(postgresql) - - # Specify if a node should attempt to be primary on initialization. - repmgr['master_on_initialization'] = false - - # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value - postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>' - # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value - postgresql['sql_user_password'] = '<postgresql_password_hash>' - # Set `max_wal_senders` to one more than the number of database nodes in the cluster. - # This is used to prevent replication from using up all of the - # available database connections. - postgresql['max_wal_senders'] = 4 - postgresql['max_replication_slots'] = 4 - - # Replace with your network addresses - postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) - repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - - ## Enable service discovery for Prometheus - consul['monitoring_service_discovery'] = true - - # Set the network addresses that the exporters will listen on for monitoring - node_exporter['listen_address'] = '0.0.0.0:9100' - postgres_exporter['listen_address'] = '0.0.0.0:9187' - - ## The IPs of the Consul server nodes - ## You can also use FQDNs and intermix them with IPs - consul['configuration'] = { - retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), - } - ``` +PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts. +Like most failover handling methods, this has a small chance of leading to data loss. +Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method). 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace the file of the same name on this server. If that file is not on this server, @@ -601,84 +541,25 @@ SSH in to the **primary node**: 1. Exit the database prompt by typing `\q` and Enter. -1. Verify the cluster is initialized with one node: +1. Check the status of the leader and cluster: ```shell - gitlab-ctl repmgr cluster show + gitlab-ctl patroni members ``` The output should be similar to the following: ```plaintext - Role | Name | Upstream | Connection String - ----------+----------|----------|---------------------------------------- - * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr - ``` - -1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will - refer to the hostname in the next section as `<primary_node_name>`. If the value - is not an IP address, it will need to be a resolvable name (via DNS or - `/etc/hosts`) - -SSH in to the **secondary node**: - -1. Set up the repmgr standby: - - ```shell - gitlab-ctl repmgr standby setup <primary_node_name> + | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | + |---------------|-----------------------------------|-----------|--------|---------|-----|-----------|-----------------| + | postgresql-ha | <PostgreSQL primary hostname> | 10.6.0.21 | Leader | running | 175 | | * | + | postgresql-ha | <PostgreSQL secondary 1 hostname> | 10.6.0.22 | | running | 175 | 0 | * | + | postgresql-ha | <PostgreSQL secondary 2 hostname> | 10.6.0.23 | | running | 175 | 0 | * | ``` - Do note that this will remove the existing data on the node. The command - has a wait time. - - The output should be similar to the following: - - ```console - Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data - If this is not what you want, hit Ctrl-C now to exit - To skip waiting, rerun with the -w option - Sleeping for 30 seconds - Stopping the database - Removing the data - Cloning the data - Starting the database - Registering the node with the cluster - ok: run: repmgrd: (pid 19068) 0s - ``` - -Before moving on, make sure the databases are configured correctly. Run the -following command on the **primary** node to verify that replication is working -properly and the secondary nodes appear in the cluster: - -```shell -gitlab-ctl repmgr cluster show -``` - -The output should be similar to the following: - -```plaintext -Role | Name | Upstream | Connection String -----------+---------|-----------|------------------------------------------------ -* master | MASTER | | host=<primary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr - standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr - standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr -``` - -If the 'Role' column for any node says "FAILED", check the +If the 'State' column for any node doesn't say "running", check the [Troubleshooting section](troubleshooting.md) before proceeding. -Also, check that the `repmgr-check-master` command works successfully on each node: - -```shell -su - gitlab-consul -gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' -``` - -This command relies on exit codes to tell Consul whether a particular node is a master -or secondary. The most important thing here is that this command does not produce errors. -If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions. -Check the [Troubleshooting section](troubleshooting.md) before proceeding. - <div align="right"> <a type="button" class="btn btn-default" href="#setup-components"> Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> @@ -696,7 +577,7 @@ The following IPs will be used as an example: 1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace `<consul_password_hash>` and `<pgbouncer_password_hash>` with the - password hashes you [set up previously](#postgresql-primary-node): + password hashes you [set up previously](#postgresql-nodes): ```ruby # Disable all components except Pgbouncer and Consul agent @@ -704,15 +585,16 @@ The following IPs will be used as an example: # Configure PgBouncer pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) - pgbouncer['users'] = { - 'gitlab-consul': { - password: '<consul_password_hash>' - }, - 'pgbouncer': { - password: '<pgbouncer_password_hash>' - } + 'gitlab-consul': { + password: '<consul_password_hash>' + }, + 'pgbouncer': { + password: '<pgbouncer_password_hash>' + } } + # Incoming recommended value for max db connections is 150. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691. + pgbouncer['max_db_connections'] = 150 # Configure Consul agent consul['watchers'] = %w(postgresql) @@ -2125,6 +2007,12 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag See how to [configure NFS](../nfs.md). +WARNING: +From GitLab 13.0, using NFS for Git repositories is deprecated. +From GitLab 14.0, technical support for NFS for Git repositories +will no longer be provided. Upgrade to [Gitaly Cluster](../gitaly/praefect.md) +as soon as possible. + <div align="right"> <a type="button" class="btn btn-default" href="#setup-components"> Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> diff --git a/doc/administration/reference_architectures/1k_users.md b/doc/administration/reference_architectures/1k_users.md index 5b75c7ac9c4..161964353f5 100644 --- a/doc/administration/reference_architectures/1k_users.md +++ b/doc/administration/reference_architectures/1k_users.md @@ -16,7 +16,8 @@ requirements, a single-node solution with many organizations . > - **Supported users (approximate):** 1,000 -> - **High Availability:** No +> - **High Availability:** No. For a highly-available environment, you can +> follow the [3K reference architecture](3k_users.md). | Users | Configuration | GCP | AWS | Azure | |--------------|-------------------------|----------------|-----------------|----------------| diff --git a/doc/administration/reference_architectures/25k_users.md b/doc/administration/reference_architectures/25k_users.md index c5a8c3927c0..d96e93d4ab4 100644 --- a/doc/administration/reference_architectures/25k_users.md +++ b/doc/administration/reference_architectures/25k_users.md @@ -422,9 +422,9 @@ install the necessary dependencies from step 1, and add the GitLab package repository from step 2. When installing GitLab in the second step, do not supply the `EXTERNAL_URL` value. -#### PostgreSQL primary node +#### PostgreSQL nodes -1. SSH in to the PostgreSQL primary node. +1. SSH in to one of the PostgreSQL nodes. 1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default username of `gitlab` (recommended). The command will request a password and confirmation. Use the value that is output by this command in the next @@ -452,23 +452,33 @@ in the second step, do not supply the `EXTERNAL_URL` value. sudo gitlab-ctl pg-password-md5 gitlab-consul ``` -1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: +1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: ```ruby - # Disable all components except PostgreSQL and Repmgr and Consul + # Disable all components except PostgreSQL, Patroni, and Consul roles ['postgres_role'] # PostgreSQL configuration postgresql['listen_address'] = '0.0.0.0' - postgresql['hot_standby'] = 'on' - postgresql['wal_level'] = 'replica' - postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Enable Patroni + patroni['enable'] = true + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + patroni['postgresql']['max_wal_senders'] = 4 + patroni['postgresql']['max_replication_slots'] = 4 + # Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691. + patroni['postgresql']['max_connections'] = 500 # Disable automatic database migrations gitlab_rails['auto_migrate'] = false # Configure the Consul agent + consul['enable'] = true consul['services'] = %w(postgresql) + ## Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true # START user configuration # Please set the real values as explained in Required Information section @@ -477,18 +487,9 @@ in the second step, do not supply the `EXTERNAL_URL` value. postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>' # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value postgresql['sql_user_password'] = '<postgresql_password_hash>' - # Set `max_wal_senders` to one more than the number of database nodes in the cluster. - # This is used to prevent replication from using up all of the - # available database connections. - postgresql['max_wal_senders'] = 4 - postgresql['max_replication_slots'] = 4 # Replace XXX.XXX.XXX.XXX/YY with Network Address postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) - repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - - ## Enable service discovery for Prometheus - consul['monitoring_service_discovery'] = true # Set the network addresses that the exporters will listen on for monitoring node_exporter['listen_address'] = '0.0.0.0:9100' @@ -503,70 +504,9 @@ in the second step, do not supply the `EXTERNAL_URL` value. # END user configuration ``` -1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace - the file of the same name on this server. If that file is not on this server, - add the file from your Consul server to this server. - -1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. - -<div align="right"> - <a type="button" class="btn btn-default" href="#setup-components"> - Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> - </a> -</div> - -#### PostgreSQL secondary nodes - -1. On both the secondary nodes, add the same configuration specified above for the primary node - with an additional setting (`repmgr['master_on_initialization'] = false`) that will inform `gitlab-ctl` that they are standby nodes initially - and there's no need to attempt to register them as a primary node: - - ```ruby - # Disable all components except PostgreSQL and Repmgr and Consul - roles ['postgres_role'] - - # PostgreSQL configuration - postgresql['listen_address'] = '0.0.0.0' - postgresql['hot_standby'] = 'on' - postgresql['wal_level'] = 'replica' - postgresql['shared_preload_libraries'] = 'repmgr_funcs' - - # Disable automatic database migrations - gitlab_rails['auto_migrate'] = false - - # Configure the Consul agent - consul['services'] = %w(postgresql) - - # Specify if a node should attempt to be primary on initialization. - repmgr['master_on_initialization'] = false - - # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value - postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>' - # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value - postgresql['sql_user_password'] = '<postgresql_password_hash>' - # Set `max_wal_senders` to one more than the number of database nodes in the cluster. - # This is used to prevent replication from using up all of the - # available database connections. - postgresql['max_wal_senders'] = 4 - postgresql['max_replication_slots'] = 4 - - # Replace with your network addresses - postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) - repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - - ## Enable service discovery for Prometheus - consul['monitoring_service_discovery'] = true - - # Set the network addresses that the exporters will listen on for monitoring - node_exporter['listen_address'] = '0.0.0.0:9100' - postgres_exporter['listen_address'] = '0.0.0.0:9187' - - ## The IPs of the Consul server nodes - ## You can also use FQDNs and intermix them with IPs - consul['configuration'] = { - retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), - } - ``` +PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts. +Like most failover handling methods, this has a small chance of leading to data loss. +Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method). 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace the file of the same name on this server. If that file is not on this server, @@ -601,84 +541,25 @@ SSH in to the **primary node**: 1. Exit the database prompt by typing `\q` and Enter. -1. Verify the cluster is initialized with one node: +1. Check the status of the leader and cluster: ```shell - gitlab-ctl repmgr cluster show + gitlab-ctl patroni members ``` The output should be similar to the following: ```plaintext - Role | Name | Upstream | Connection String - ----------+----------|----------|---------------------------------------- - * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr - ``` - -1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will - refer to the hostname in the next section as `<primary_node_name>`. If the value - is not an IP address, it will need to be a resolvable name (via DNS or - `/etc/hosts`) - -SSH in to the **secondary node**: - -1. Set up the repmgr standby: - - ```shell - gitlab-ctl repmgr standby setup <primary_node_name> + | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | + |---------------|-----------------------------------|-----------|--------|---------|-----|-----------|-----------------| + | postgresql-ha | <PostgreSQL primary hostname> | 10.6.0.21 | Leader | running | 175 | | * | + | postgresql-ha | <PostgreSQL secondary 1 hostname> | 10.6.0.22 | | running | 175 | 0 | * | + | postgresql-ha | <PostgreSQL secondary 2 hostname> | 10.6.0.23 | | running | 175 | 0 | * | ``` - Do note that this will remove the existing data on the node. The command - has a wait time. - - The output should be similar to the following: - - ```console - Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data - If this is not what you want, hit Ctrl-C now to exit - To skip waiting, rerun with the -w option - Sleeping for 30 seconds - Stopping the database - Removing the data - Cloning the data - Starting the database - Registering the node with the cluster - ok: run: repmgrd: (pid 19068) 0s - ``` - -Before moving on, make sure the databases are configured correctly. Run the -following command on the **primary** node to verify that replication is working -properly and the secondary nodes appear in the cluster: - -```shell -gitlab-ctl repmgr cluster show -``` - -The output should be similar to the following: - -```plaintext -Role | Name | Upstream | Connection String -----------+---------|-----------|------------------------------------------------ -* master | MASTER | | host=<primary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr - standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr - standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr -``` - -If the 'Role' column for any node says "FAILED", check the +If the 'State' column for any node doesn't say "running", check the [Troubleshooting section](troubleshooting.md) before proceeding. -Also, check that the `repmgr-check-master` command works successfully on each node: - -```shell -su - gitlab-consul -gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' -``` - -This command relies on exit codes to tell Consul whether a particular node is a master -or secondary. The most important thing here is that this command does not produce errors. -If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions. -Check the [Troubleshooting section](troubleshooting.md) before proceeding. - <div align="right"> <a type="button" class="btn btn-default" href="#setup-components"> Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> @@ -696,7 +577,7 @@ The following IPs will be used as an example: 1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace `<consul_password_hash>` and `<pgbouncer_password_hash>` with the - password hashes you [set up previously](#postgresql-primary-node): + password hashes you [set up previously](#postgresql-nodes): ```ruby # Disable all components except Pgbouncer and Consul agent @@ -704,15 +585,16 @@ The following IPs will be used as an example: # Configure PgBouncer pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) - pgbouncer['users'] = { - 'gitlab-consul': { - password: '<consul_password_hash>' - }, - 'pgbouncer': { - password: '<pgbouncer_password_hash>' - } + 'gitlab-consul': { + password: '<consul_password_hash>' + }, + 'pgbouncer': { + password: '<pgbouncer_password_hash>' + } } + # Incoming recommended value for max db connections is 150. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691. + pgbouncer['max_db_connections'] = 150 # Configure Consul agent consul['watchers'] = %w(postgresql) @@ -2125,6 +2007,12 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag See how to [configure NFS](../nfs.md). +WARNING: +From GitLab 13.0, using NFS for Git repositories is deprecated. +From GitLab 14.0, technical support for NFS for Git repositories +will no longer be provided. Upgrade to [Gitaly Cluster](../gitaly/praefect.md) +as soon as possible. + <div align="right"> <a type="button" class="btn btn-default" href="#setup-components"> Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> diff --git a/doc/administration/reference_architectures/2k_users.md b/doc/administration/reference_architectures/2k_users.md index c341ff5baec..3d38586fa62 100644 --- a/doc/administration/reference_architectures/2k_users.md +++ b/doc/administration/reference_architectures/2k_users.md @@ -12,7 +12,8 @@ For a full list of reference architectures, see [Available reference architectures](index.md#available-reference-architectures). > - **Supported users (approximate):** 2,000 -> - **High Availability:** No +> - **High Availability:** No. For a highly-available environment, you can +> follow the [3K reference architecture](3k_users.md). > - **Test requests per second (RPS) rates:** API: 40 RPS, Web: 4 RPS, Git: 4 RPS | Service | Nodes | Configuration | GCP | AWS | Azure | @@ -271,7 +272,7 @@ further configuration steps. ```ruby # Disable all components except PostgreSQL roles ['postgres_role'] - repmgr['enable'] = false + patroni['enable'] = false consul['enable'] = false prometheus['enable'] = false alertmanager['enable'] = false @@ -954,7 +955,13 @@ along with [Gitaly](#configure-gitaly), are recommended over using NFS whenever possible. However, if you intend to use GitLab Pages, [you must use NFS](troubleshooting.md#gitlab-pages-requires-nfs). -For information about configuring NFS, see the [NFS documentation page](../nfs.md). +See how to [configure NFS](../nfs.md). + +WARNING: +From GitLab 13.0, using NFS for Git repositories is deprecated. +From GitLab 14.0, technical support for NFS for Git repositories +will no longer be provided. Upgrade to [Gitaly Cluster](../gitaly/praefect.md) +as soon as possible. <div align="right"> <a type="button" class="btn btn-default" href="#setup-components"> diff --git a/doc/administration/reference_architectures/3k_users.md b/doc/administration/reference_architectures/3k_users.md index 370247ed856..648fac8025f 100644 --- a/doc/administration/reference_architectures/3k_users.md +++ b/doc/administration/reference_architectures/3k_users.md @@ -7,16 +7,17 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Reference architecture: up to 3,000 users **(PREMIUM ONLY)** -This page describes GitLab reference architecture for up to 3,000 users. For a -full list of reference architectures, see -[Available reference architectures](index.md#available-reference-architectures). - -NOTE: -This reference architecture is designed to help your organization achieve a +This page describes GitLab reference architecture for up to 3,000 users. +It is designed to help your organization achieve a highly-available GitLab deployment. If you do not have the expertise or need to maintain a highly-available environment, you can have a simpler and less costly-to-operate environment by using the [2,000-user reference architecture](2k_users.md). +If you have fewer than 3,000 users and still want a highly-available GitLab deployment, +you should still use this reference architecture but scale down the node sizes. + +For a full list of reference architectures, see +[Available reference architectures](index.md#available-reference-architectures). > - **Supported users (approximate):** 3,000 > - **High Availability:** Yes @@ -670,9 +671,9 @@ install the necessary dependencies from step 1, and add the GitLab package repository from step 2. When installing GitLab in the second step, do not supply the `EXTERNAL_URL` value. -#### PostgreSQL primary node +#### PostgreSQL nodes -1. SSH in to the PostgreSQL primary node. +1. SSH in to one of the PostgreSQL nodes. 1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default username of `gitlab` (recommended). The command will request a password and confirmation. Use the value that is output by this command in the next @@ -700,114 +701,33 @@ in the second step, do not supply the `EXTERNAL_URL` value. sudo gitlab-ctl pg-password-md5 gitlab-consul ``` -1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: +1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: ```ruby - # Disable all components except PostgreSQL and Repmgr and Consul + # Disable all components except PostgreSQL, Patroni, and Consul roles ['postgres_role'] # PostgreSQL configuration postgresql['listen_address'] = '0.0.0.0' - postgresql['hot_standby'] = 'on' - postgresql['wal_level'] = 'replica' - postgresql['shared_preload_libraries'] = 'repmgr_funcs' - - # Disable automatic database migrations - gitlab_rails['auto_migrate'] = false - - # Configure the Consul agent - consul['services'] = %w(postgresql) - # START user configuration - # Please set the real values as explained in Required Information section - # - # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value - postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>' - # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value - postgresql['sql_user_password'] = '<postgresql_password_hash>' + # Enable Patroni + patroni['enable'] = true # Set `max_wal_senders` to one more than the number of database nodes in the cluster. # This is used to prevent replication from using up all of the # available database connections. - postgresql['max_wal_senders'] = 4 - postgresql['max_replication_slots'] = 4 - - # Replace XXX.XXX.XXX.XXX/YY with Network Address - postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - - ## Enable service discovery for Prometheus - consul['enable'] = true - consul['monitoring_service_discovery'] = true - - # Set the network addresses that the exporters will listen on for monitoring - node_exporter['listen_address'] = '0.0.0.0:9100' - postgres_exporter['listen_address'] = '0.0.0.0:9187' - postgres_exporter['dbname'] = 'gitlabhq_production' - postgres_exporter['password'] = '<postgresql_password_hash>' - - ## The IPs of the Consul server nodes - ## You can also use FQDNs and intermix them with IPs - consul['configuration'] = { - retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), - } - # - # END user configuration - ``` - -1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. -1. You can list the current PostgreSQL primary, secondary nodes status via: - - ```shell - sudo /opt/gitlab/bin/gitlab-ctl repmgr cluster show - ``` - -1. Verify the GitLab services are running: - - ```shell - sudo gitlab-ctl status - ``` - - The output should be similar to the following: - - ```plaintext - run: consul: (pid 30593) 77133s; run: log: (pid 29912) 77156s - run: logrotate: (pid 23449) 3341s; run: log: (pid 29794) 77175s - run: node-exporter: (pid 30613) 77133s; run: log: (pid 29824) 77170s - run: postgres-exporter: (pid 30620) 77132s; run: log: (pid 29894) 77163s - run: postgresql: (pid 30630) 77132s; run: log: (pid 29618) 77181s - run: repmgrd: (pid 30639) 77132s; run: log: (pid 29985) 77150s - ``` - -<div align="right"> - <a type="button" class="btn btn-default" href="#setup-components"> - Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> - </a> -</div> - -#### PostgreSQL secondary nodes - -1. On both the secondary nodes, add the same configuration specified above for the primary node - with an additional setting that will inform `gitlab-ctl` that they are standby nodes initially - and there's no need to attempt to register them as a primary node: - - ```ruby - # Disable all components except PostgreSQL and Repmgr and Consul - roles ['postgres_role'] - - # PostgreSQL configuration - postgresql['listen_address'] = '0.0.0.0' - postgresql['hot_standby'] = 'on' - postgresql['wal_level'] = 'replica' - postgresql['shared_preload_libraries'] = 'repmgr_funcs' + patroni['postgresql']['max_wal_senders'] = 4 + patroni['postgresql']['max_replication_slots'] = 4 + # Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691. + patroni['postgresql']['max_connections'] = 500 # Disable automatic database migrations gitlab_rails['auto_migrate'] = false # Configure the Consul agent + consul['enable'] = true consul['services'] = %w(postgresql) - - # Specify if a node should attempt to be primary on initialization. - repmgr['master_on_initialization'] = false + ## Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true # START user configuration # Please set the real values as explained in Required Information section @@ -816,34 +736,31 @@ in the second step, do not supply the `EXTERNAL_URL` value. postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>' # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value postgresql['sql_user_password'] = '<postgresql_password_hash>' - # Set `max_wal_senders` to one more than the number of database nodes in the cluster. - # This is used to prevent replication from using up all of the - # available database connections. - postgresql['max_wal_senders'] = 4 - postgresql['max_replication_slots'] = 4 # Replace XXX.XXX.XXX.XXX/YY with Network Address - postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - - ## Enable service discovery for Prometheus - consul['enable'] = true - consul['monitoring_service_discovery'] = true + postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) # Set the network addresses that the exporters will listen on for monitoring node_exporter['listen_address'] = '0.0.0.0:9100' postgres_exporter['listen_address'] = '0.0.0.0:9187' - postgres_exporter['dbname'] = 'gitlabhq_production' - postgres_exporter['password'] = '<postgresql_password_hash>' ## The IPs of the Consul server nodes ## You can also use FQDNs and intermix them with IPs consul['configuration'] = { retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), } + # # END user configuration ``` +PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts. +Like most failover handling methods, this has a small chance of leading to data loss. +Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method). + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/database.html) @@ -874,84 +791,25 @@ SSH in to the **primary node**: 1. Exit the database prompt by typing `\q` and Enter. -1. Verify the cluster is initialized with one node: +1. Check the status of the leader and cluster: ```shell - gitlab-ctl repmgr cluster show + gitlab-ctl patroni members ``` The output should be similar to the following: ```plaintext - Role | Name | Upstream | Connection String - ----------+----------|----------|---------------------------------------- - * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr - ``` - -1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will - refer to the hostname in the next section as `<primary_node_name>`. If the value - is not an IP address, it will need to be a resolvable name (via DNS or - `/etc/hosts`) - -SSH in to the **secondary node**: - -1. Set up the repmgr standby: - - ```shell - gitlab-ctl repmgr standby setup <primary_node_name> - ``` - - Do note that this will remove the existing data on the node. The command - has a wait time. - - The output should be similar to the following: - - ```console - Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data - If this is not what you want, hit Ctrl-C now to exit - To skip waiting, rerun with the -w option - Sleeping for 30 seconds - Stopping the database - Removing the data - Cloning the data - Starting the database - Registering the node with the cluster - ok: run: repmgrd: (pid 19068) 0s + | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | + |---------------|-----------------------------------|-----------|--------|---------|-----|-----------|-----------------| + | postgresql-ha | <PostgreSQL primary hostname> | 10.6.0.31 | Leader | running | 175 | | * | + | postgresql-ha | <PostgreSQL secondary 1 hostname> | 10.6.0.32 | | running | 175 | 0 | * | + | postgresql-ha | <PostgreSQL secondary 2 hostname> | 10.6.0.33 | | running | 175 | 0 | * | ``` -Before moving on, make sure the databases are configured correctly. Run the -following command on the **primary** node to verify that replication is working -properly and the secondary nodes appear in the cluster: - -```shell -gitlab-ctl repmgr cluster show -``` - -The output should be similar to the following: - -```plaintext -Role | Name | Upstream | Connection String -----------+---------|-----------|------------------------------------------------ -* master | MASTER | | host=<primary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr - standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr - standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr -``` - -If the 'Role' column for any node says "FAILED", check the +If the 'State' column for any node doesn't say "running", check the [Troubleshooting section](troubleshooting.md) before proceeding. -Also, check that the `repmgr-check-master` command works successfully on each node: - -```shell -su - gitlab-consul -gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' -``` - -This command relies on exit codes to tell Consul whether a particular node is a master -or secondary. The most important thing here is that this command does not produce errors. -If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions. -Check the [Troubleshooting section](troubleshooting.md) before proceeding. - <div align="right"> <a type="button" class="btn btn-default" href="#setup-components"> Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> @@ -969,7 +827,7 @@ The following IPs will be used as an example: 1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace `<consul_password_hash>` and `<pgbouncer_password_hash>` with the - password hashes you [set up previously](#postgresql-primary-node): + password hashes you [set up previously](#postgresql-nodes): ```ruby # Disable all components except Pgbouncer and Consul agent @@ -977,15 +835,16 @@ The following IPs will be used as an example: # Configure PgBouncer pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) - pgbouncer['users'] = { - 'gitlab-consul': { - password: '<consul_password_hash>' - }, - 'pgbouncer': { - password: '<pgbouncer_password_hash>' - } + 'gitlab-consul': { + password: '<consul_password_hash>' + }, + 'pgbouncer': { + password: '<pgbouncer_password_hash>' + } } + # Incoming recommended value for max db connections is 150. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691. + pgbouncer['max_db_connections'] = 150 # Configure Consul agent consul['watchers'] = %w(postgresql) @@ -1841,6 +1700,12 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag See how to [configure NFS](../nfs.md). +WARNING: +From GitLab 13.0, using NFS for Git repositories is deprecated. +From GitLab 14.0, technical support for NFS for Git repositories +will no longer be provided. Upgrade to [Gitaly Cluster](../gitaly/praefect.md) +as soon as possible. + <div align="right"> <a type="button" class="btn btn-default" href="#setup-components"> Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> diff --git a/doc/administration/reference_architectures/50k_users.md b/doc/administration/reference_architectures/50k_users.md index f76c8a8a877..093869d331b 100644 --- a/doc/administration/reference_architectures/50k_users.md +++ b/doc/administration/reference_architectures/50k_users.md @@ -422,9 +422,9 @@ install the necessary dependencies from step 1, and add the GitLab package repository from step 2. When installing GitLab in the second step, do not supply the `EXTERNAL_URL` value. -#### PostgreSQL primary node +#### PostgreSQL nodes -1. SSH in to the PostgreSQL primary node. +1. SSH in to one of the PostgreSQL nodes. 1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default username of `gitlab` (recommended). The command will request a password and confirmation. Use the value that is output by this command in the next @@ -452,23 +452,33 @@ in the second step, do not supply the `EXTERNAL_URL` value. sudo gitlab-ctl pg-password-md5 gitlab-consul ``` -1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: +1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: ```ruby - # Disable all components except PostgreSQL and Repmgr and Consul + # Disable all components except PostgreSQL, Patroni, and Consul roles ['postgres_role'] # PostgreSQL configuration postgresql['listen_address'] = '0.0.0.0' - postgresql['hot_standby'] = 'on' - postgresql['wal_level'] = 'replica' - postgresql['shared_preload_libraries'] = 'repmgr_funcs' + + # Enable Patroni + patroni['enable'] = true + # Set `max_wal_senders` to one more than the number of database nodes in the cluster. + # This is used to prevent replication from using up all of the + # available database connections. + patroni['postgresql']['max_wal_senders'] = 4 + patroni['postgresql']['max_replication_slots'] = 4 + # Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691. + patroni['postgresql']['max_connections'] = 500 # Disable automatic database migrations gitlab_rails['auto_migrate'] = false # Configure the Consul agent + consul['enable'] = true consul['services'] = %w(postgresql) + ## Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true # START user configuration # Please set the real values as explained in Required Information section @@ -477,18 +487,9 @@ in the second step, do not supply the `EXTERNAL_URL` value. postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>' # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value postgresql['sql_user_password'] = '<postgresql_password_hash>' - # Set `max_wal_senders` to one more than the number of database nodes in the cluster. - # This is used to prevent replication from using up all of the - # available database connections. - postgresql['max_wal_senders'] = 4 - postgresql['max_replication_slots'] = 4 # Replace XXX.XXX.XXX.XXX/YY with Network Address postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) - repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - - ## Enable service discovery for Prometheus - consul['monitoring_service_discovery'] = true # Set the network addresses that the exporters will listen on for monitoring node_exporter['listen_address'] = '0.0.0.0:9100' @@ -503,70 +504,9 @@ in the second step, do not supply the `EXTERNAL_URL` value. # END user configuration ``` -1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace - the file of the same name on this server. If that file is not on this server, - add the file from your Consul server to this server. - -1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. - -<div align="right"> - <a type="button" class="btn btn-default" href="#setup-components"> - Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> - </a> -</div> - -#### PostgreSQL secondary nodes - -1. On both the secondary nodes, add the same configuration specified above for the primary node - with an additional setting (`repmgr['master_on_initialization'] = false`) that will inform `gitlab-ctl` that they are standby nodes initially - and there's no need to attempt to register them as a primary node: - - ```ruby - # Disable all components except PostgreSQL and Repmgr and Consul - roles ['postgres_role'] - - # PostgreSQL configuration - postgresql['listen_address'] = '0.0.0.0' - postgresql['hot_standby'] = 'on' - postgresql['wal_level'] = 'replica' - postgresql['shared_preload_libraries'] = 'repmgr_funcs' - - # Disable automatic database migrations - gitlab_rails['auto_migrate'] = false - - # Configure the Consul agent - consul['services'] = %w(postgresql) - - # Specify if a node should attempt to be primary on initialization. - repmgr['master_on_initialization'] = false - - # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value - postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>' - # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value - postgresql['sql_user_password'] = '<postgresql_password_hash>' - # Set `max_wal_senders` to one more than the number of database nodes in the cluster. - # This is used to prevent replication from using up all of the - # available database connections. - postgresql['max_wal_senders'] = 4 - postgresql['max_replication_slots'] = 4 - - # Replace with your network addresses - postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) - repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - - ## Enable service discovery for Prometheus - consul['monitoring_service_discovery'] = true - - # Set the network addresses that the exporters will listen on for monitoring - node_exporter['listen_address'] = '0.0.0.0:9100' - postgres_exporter['listen_address'] = '0.0.0.0:9187' - - ## The IPs of the Consul server nodes - ## You can also use FQDNs and intermix them with IPs - consul['configuration'] = { - retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), - } - ``` +PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts. +Like most failover handling methods, this has a small chance of leading to data loss. +Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method). 1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace the file of the same name on this server. If that file is not on this server, @@ -601,84 +541,25 @@ SSH in to the **primary node**: 1. Exit the database prompt by typing `\q` and Enter. -1. Verify the cluster is initialized with one node: +1. Check the status of the leader and cluster: ```shell - gitlab-ctl repmgr cluster show + gitlab-ctl patroni members ``` The output should be similar to the following: ```plaintext - Role | Name | Upstream | Connection String - ----------+----------|----------|---------------------------------------- - * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr - ``` - -1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will - refer to the hostname in the next section as `<primary_node_name>`. If the value - is not an IP address, it will need to be a resolvable name (via DNS or - `/etc/hosts`) - -SSH in to the **secondary node**: - -1. Set up the repmgr standby: - - ```shell - gitlab-ctl repmgr standby setup <primary_node_name> + | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | + |---------------|-----------------------------------|-----------|--------|---------|-----|-----------|-----------------| + | postgresql-ha | <PostgreSQL primary hostname> | 10.6.0.21 | Leader | running | 175 | | * | + | postgresql-ha | <PostgreSQL secondary 1 hostname> | 10.6.0.22 | | running | 175 | 0 | * | + | postgresql-ha | <PostgreSQL secondary 2 hostname> | 10.6.0.23 | | running | 175 | 0 | * | ``` - Do note that this will remove the existing data on the node. The command - has a wait time. - - The output should be similar to the following: - - ```console - Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data - If this is not what you want, hit Ctrl-C now to exit - To skip waiting, rerun with the -w option - Sleeping for 30 seconds - Stopping the database - Removing the data - Cloning the data - Starting the database - Registering the node with the cluster - ok: run: repmgrd: (pid 19068) 0s - ``` - -Before moving on, make sure the databases are configured correctly. Run the -following command on the **primary** node to verify that replication is working -properly and the secondary nodes appear in the cluster: - -```shell -gitlab-ctl repmgr cluster show -``` - -The output should be similar to the following: - -```plaintext -Role | Name | Upstream | Connection String -----------+---------|-----------|------------------------------------------------ -* master | MASTER | | host=<primary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr - standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr - standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr -``` - -If the 'Role' column for any node says "FAILED", check the +If the 'State' column for any node doesn't say "running", check the [Troubleshooting section](troubleshooting.md) before proceeding. -Also, check that the `repmgr-check-master` command works successfully on each node: - -```shell -su - gitlab-consul -gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' -``` - -This command relies on exit codes to tell Consul whether a particular node is a master -or secondary. The most important thing here is that this command does not produce errors. -If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions. -Check the [Troubleshooting section](troubleshooting.md) before proceeding. - <div align="right"> <a type="button" class="btn btn-default" href="#setup-components"> Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> @@ -696,7 +577,7 @@ The following IPs will be used as an example: 1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace `<consul_password_hash>` and `<pgbouncer_password_hash>` with the - password hashes you [set up previously](#postgresql-primary-node): + password hashes you [set up previously](#postgresql-nodes): ```ruby # Disable all components except Pgbouncer and Consul agent @@ -704,15 +585,16 @@ The following IPs will be used as an example: # Configure PgBouncer pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) - pgbouncer['users'] = { - 'gitlab-consul': { - password: '<consul_password_hash>' - }, - 'pgbouncer': { - password: '<pgbouncer_password_hash>' - } + 'gitlab-consul': { + password: '<consul_password_hash>' + }, + 'pgbouncer': { + password: '<pgbouncer_password_hash>' + } } + # Incoming recommended value for max db connections is 150. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691. + pgbouncer['max_db_connections'] = 150 # Configure Consul agent consul['watchers'] = %w(postgresql) @@ -2125,6 +2007,12 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag See how to [configure NFS](../nfs.md). +WARNING: +From GitLab 13.0, using NFS for Git repositories is deprecated. +From GitLab 14.0, technical support for NFS for Git repositories +will no longer be provided. Upgrade to [Gitaly Cluster](../gitaly/praefect.md) +as soon as possible. + <div align="right"> <a type="button" class="btn btn-default" href="#setup-components"> Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> diff --git a/doc/administration/reference_architectures/5k_users.md b/doc/administration/reference_architectures/5k_users.md index 6a0547aeaf9..16ad866a108 100644 --- a/doc/administration/reference_architectures/5k_users.md +++ b/doc/administration/reference_architectures/5k_users.md @@ -671,9 +671,9 @@ install the necessary dependencies from step 1, and add the GitLab package repository from step 2. When installing GitLab in the second step, do not supply the `EXTERNAL_URL` value. -#### PostgreSQL primary node +#### PostgreSQL nodes -1. SSH in to the PostgreSQL primary node. +1. SSH in to one of the PostgreSQL nodes. 1. Generate a password hash for the PostgreSQL username/password pair. This assumes you will use the default username of `gitlab` (recommended). The command will request a password and confirmation. Use the value that is output by this command in the next @@ -701,114 +701,33 @@ in the second step, do not supply the `EXTERNAL_URL` value. sudo gitlab-ctl pg-password-md5 gitlab-consul ``` -1. On the primary database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: +1. On every database node, edit `/etc/gitlab/gitlab.rb` replacing values noted in the `# START user configuration` section: ```ruby - # Disable all components except PostgreSQL and Repmgr and Consul + # Disable all components except PostgreSQL, Patroni, and Consul roles ['postgres_role'] # PostgreSQL configuration postgresql['listen_address'] = '0.0.0.0' - postgresql['hot_standby'] = 'on' - postgresql['wal_level'] = 'replica' - postgresql['shared_preload_libraries'] = 'repmgr_funcs' - # Disable automatic database migrations - gitlab_rails['auto_migrate'] = false - - # Configure the Consul agent - consul['services'] = %w(postgresql) - - # START user configuration - # Please set the real values as explained in Required Information section - # - # Replace PGBOUNCER_PASSWORD_HASH with a generated md5 value - postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>' - # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value - postgresql['sql_user_password'] = '<postgresql_password_hash>' + # Enable Patroni + patroni['enable'] = true # Set `max_wal_senders` to one more than the number of database nodes in the cluster. # This is used to prevent replication from using up all of the # available database connections. - postgresql['max_wal_senders'] = 4 - postgresql['max_replication_slots'] = 4 - - # Replace XXX.XXX.XXX.XXX/YY with Network Address - postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - - ## Enable service discovery for Prometheus - consul['enable'] = true - consul['monitoring_service_discovery'] = true - - # Set the network addresses that the exporters will listen on for monitoring - node_exporter['listen_address'] = '0.0.0.0:9100' - postgres_exporter['listen_address'] = '0.0.0.0:9187' - postgres_exporter['dbname'] = 'gitlabhq_production' - postgres_exporter['password'] = '<postgresql_password_hash>' - - ## The IPs of the Consul server nodes - ## You can also use FQDNs and intermix them with IPs - consul['configuration'] = { - retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), - } - # - # END user configuration - ``` - -1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. -1. You can list the current PostgreSQL primary, secondary nodes status via: - - ```shell - sudo /opt/gitlab/bin/gitlab-ctl repmgr cluster show - ``` - -1. Verify the GitLab services are running: - - ```shell - sudo gitlab-ctl status - ``` - - The output should be similar to the following: - - ```plaintext - run: consul: (pid 30593) 77133s; run: log: (pid 29912) 77156s - run: logrotate: (pid 23449) 3341s; run: log: (pid 29794) 77175s - run: node-exporter: (pid 30613) 77133s; run: log: (pid 29824) 77170s - run: postgres-exporter: (pid 30620) 77132s; run: log: (pid 29894) 77163s - run: postgresql: (pid 30630) 77132s; run: log: (pid 29618) 77181s - run: repmgrd: (pid 30639) 77132s; run: log: (pid 29985) 77150s - ``` - -<div align="right"> - <a type="button" class="btn btn-default" href="#setup-components"> - Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> - </a> -</div> - -#### PostgreSQL secondary nodes - -1. On both the secondary nodes, add the same configuration specified above for the primary node - with an additional setting that will inform `gitlab-ctl` that they are standby nodes initially - and there's no need to attempt to register them as a primary node: - - ```ruby - # Disable all components except PostgreSQL and Repmgr and Consul - roles ['postgres_role'] - - # PostgreSQL configuration - postgresql['listen_address'] = '0.0.0.0' - postgresql['hot_standby'] = 'on' - postgresql['wal_level'] = 'replica' - postgresql['shared_preload_libraries'] = 'repmgr_funcs' + patroni['postgresql']['max_wal_senders'] = 4 + patroni['postgresql']['max_replication_slots'] = 4 + # Incoming recommended value for max connections is 500. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691. + patroni['postgresql']['max_connections'] = 500 # Disable automatic database migrations gitlab_rails['auto_migrate'] = false # Configure the Consul agent + consul['enable'] = true consul['services'] = %w(postgresql) - - # Specify if a node should attempt to be primary on initialization. - repmgr['master_on_initialization'] = false + ## Enable service discovery for Prometheus + consul['monitoring_service_discovery'] = true # START user configuration # Please set the real values as explained in Required Information section @@ -817,34 +736,31 @@ in the second step, do not supply the `EXTERNAL_URL` value. postgresql['pgbouncer_user_password'] = '<pgbouncer_password_hash>' # Replace POSTGRESQL_PASSWORD_HASH with a generated md5 value postgresql['sql_user_password'] = '<postgresql_password_hash>' - # Set `max_wal_senders` to one more than the number of database nodes in the cluster. - # This is used to prevent replication from using up all of the - # available database connections. - postgresql['max_wal_senders'] = 4 - postgresql['max_replication_slots'] = 4 # Replace XXX.XXX.XXX.XXX/YY with Network Address - postgresql['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - repmgr['trust_auth_cidr_addresses'] = %w(127.0.0.1/32 10.6.0.0/24) - - ## Enable service discovery for Prometheus - consul['enable'] = true - consul['monitoring_service_discovery'] = true + postgresql['trust_auth_cidr_addresses'] = %w(10.6.0.0/24) # Set the network addresses that the exporters will listen on for monitoring node_exporter['listen_address'] = '0.0.0.0:9100' postgres_exporter['listen_address'] = '0.0.0.0:9187' - postgres_exporter['dbname'] = 'gitlabhq_production' - postgres_exporter['password'] = '<postgresql_password_hash>' ## The IPs of the Consul server nodes ## You can also use FQDNs and intermix them with IPs consul['configuration'] = { retry_join: %w(10.6.0.11 10.6.0.12 10.6.0.13), } + # # END user configuration ``` +PostgreSQL, with Patroni managing its failover, will default to use `pg_rewind` by default to handle conflicts. +Like most failover handling methods, this has a small chance of leading to data loss. +Learn more about the various [Patroni replication methods](../postgresql/replication_and_failover.md#selecting-the-appropriate-patroni-replication-method). + +1. Copy the `/etc/gitlab/gitlab-secrets.json` file from your Consul server, and replace + the file of the same name on this server. If that file is not on this server, + add the file from your Consul server to this server. + 1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. Advanced [configuration options](https://docs.gitlab.com/omnibus/settings/database.html) @@ -874,84 +790,25 @@ SSH in to the **primary node**: 1. Exit the database prompt by typing `\q` and Enter. -1. Verify the cluster is initialized with one node: +1. Check the status of the leader and cluster: ```shell - gitlab-ctl repmgr cluster show + gitlab-ctl patroni members ``` The output should be similar to the following: ```plaintext - Role | Name | Upstream | Connection String - ----------+----------|----------|---------------------------------------- - * master | HOSTNAME | | host=HOSTNAME user=gitlab_repmgr dbname=gitlab_repmgr - ``` - -1. Note down the hostname or IP address in the connection string: `host=HOSTNAME`. We will - refer to the hostname in the next section as `<primary_node_name>`. If the value - is not an IP address, it will need to be a resolvable name (via DNS or - `/etc/hosts`) - -SSH in to the **secondary node**: - -1. Set up the repmgr standby: - - ```shell - gitlab-ctl repmgr standby setup <primary_node_name> + | Cluster | Member | Host | Role | State | TL | Lag in MB | Pending restart | + |---------------|-----------------------------------|-----------|--------|---------|-----|-----------|-----------------| + | postgresql-ha | <PostgreSQL primary hostname> | 10.6.0.31 | Leader | running | 175 | | * | + | postgresql-ha | <PostgreSQL secondary 1 hostname> | 10.6.0.32 | | running | 175 | 0 | * | + | postgresql-ha | <PostgreSQL secondary 2 hostname> | 10.6.0.33 | | running | 175 | 0 | * | ``` - Do note that this will remove the existing data on the node. The command - has a wait time. - - The output should be similar to the following: - - ```console - Doing this will delete the entire contents of /var/opt/gitlab/postgresql/data - If this is not what you want, hit Ctrl-C now to exit - To skip waiting, rerun with the -w option - Sleeping for 30 seconds - Stopping the database - Removing the data - Cloning the data - Starting the database - Registering the node with the cluster - ok: run: repmgrd: (pid 19068) 0s - ``` - -Before moving on, make sure the databases are configured correctly. Run the -following command on the **primary** node to verify that replication is working -properly and the secondary nodes appear in the cluster: - -```shell -gitlab-ctl repmgr cluster show -``` - -The output should be similar to the following: - -```plaintext -Role | Name | Upstream | Connection String -----------+---------|-----------|------------------------------------------------ -* master | MASTER | | host=<primary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr - standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr - standby | STANDBY | MASTER | host=<secondary_node_name> user=gitlab_repmgr dbname=gitlab_repmgr -``` - -If the 'Role' column for any node says "FAILED", check the +If the 'State' column for any node doesn't say "running", check the [Troubleshooting section](troubleshooting.md) before proceeding. -Also, check that the `repmgr-check-master` command works successfully on each node: - -```shell -su - gitlab-consul -gitlab-ctl repmgr-check-master || echo 'This node is a standby repmgr node' -``` - -This command relies on exit codes to tell Consul whether a particular node is a master -or secondary. The most important thing here is that this command does not produce errors. -If there are errors it's most likely due to incorrect `gitlab-consul` database user permissions. -Check the [Troubleshooting section](troubleshooting.md) before proceeding. - <div align="right"> <a type="button" class="btn btn-default" href="#setup-components"> Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> @@ -969,7 +826,7 @@ The following IPs will be used as an example: 1. On each PgBouncer node, edit `/etc/gitlab/gitlab.rb`, and replace `<consul_password_hash>` and `<pgbouncer_password_hash>` with the - password hashes you [set up previously](#postgresql-primary-node): + password hashes you [set up previously](#postgresql-nodes): ```ruby # Disable all components except Pgbouncer and Consul agent @@ -977,15 +834,16 @@ The following IPs will be used as an example: # Configure PgBouncer pgbouncer['admin_users'] = %w(pgbouncer gitlab-consul) - pgbouncer['users'] = { - 'gitlab-consul': { - password: '<consul_password_hash>' - }, - 'pgbouncer': { - password: '<pgbouncer_password_hash>' - } + 'gitlab-consul': { + password: '<consul_password_hash>' + }, + 'pgbouncer': { + password: '<pgbouncer_password_hash>' + } } + # Incoming recommended value for max db connections is 150. See https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5691. + pgbouncer['max_db_connections'] = 150 # Configure Consul agent consul['watchers'] = %w(postgresql) @@ -1841,6 +1699,12 @@ to use GitLab Pages, this currently [requires NFS](troubleshooting.md#gitlab-pag See how to [configure NFS](../nfs.md). +WARNING: +From GitLab 13.0, using NFS for Git repositories is deprecated. +From GitLab 14.0, technical support for NFS for Git repositories +will no longer be provided. Upgrade to [Gitaly Cluster](../gitaly/praefect.md) +as soon as possible. + <div align="right"> <a type="button" class="btn btn-default" href="#setup-components"> Back to setup components <i class="fa fa-angle-double-up" aria-hidden="true"></i> diff --git a/doc/administration/reference_architectures/index.md b/doc/administration/reference_architectures/index.md index 6b04dad9baf..b90b8d67b68 100644 --- a/doc/administration/reference_architectures/index.md +++ b/doc/administration/reference_architectures/index.md @@ -95,7 +95,6 @@ have more actual perceived uptime for your users. > - Level of complexity: **Low** > - Required domain knowledge: PostgreSQL, GitLab configurations, Git -> - Supported tiers: [GitLab Core, Starter, Premium, and Ultimate](https://about.gitlab.com/pricing/) This solution is appropriate for many teams that have the default GitLab installation. With automatic backups of the GitLab repositories, configuration, and the database, @@ -107,7 +106,6 @@ is the least complex to setup. This provides a point-in-time recovery of a prede > - Level of complexity: **Medium** > - Required domain knowledge: HAProxy, shared storage, distributed systems -> - Supported tiers: [GitLab Starter, Premium, and Ultimate](https://about.gitlab.com/pricing/) This requires separating out GitLab into multiple application nodes with an added [load balancer](../load_balancer.md). The load balancer will distribute traffic @@ -123,11 +121,13 @@ to the default installation: - Enable zero-downtime upgrades. - Increase availability. +For more details on how to configure a traffic load balancer with GitLab, you can refer +to any of the [available reference architectures](#available-reference-architectures) with more than 1,000 users. + ### Zero downtime updates **(STARTER ONLY)** > - Level of complexity: **Medium** > - Required domain knowledge: PostgreSQL, HAProxy, shared storage, distributed systems -> - Supported tiers: [GitLab Starter, Premium, and Ultimate](https://about.gitlab.com/pricing/) GitLab supports [zero-downtime updates](https://docs.gitlab.com/omnibus/update/#zero-downtime-updates). Single GitLab nodes can be updated with only a [few minutes of downtime](https://docs.gitlab.com/omnibus/update/README.html#single-node-deployment). @@ -138,7 +138,6 @@ As long as at least one of each component is online and capable of handling the > - Level of complexity: **High** > - Required domain knowledge: PgBouncer, Repmgr or Patroni, shared storage, distributed systems -> - Supported tiers: [GitLab Premium and Ultimate](https://about.gitlab.com/pricing/) By adding automatic failover for database systems, you can enable higher uptime with additional database nodes. This extends the default database with @@ -150,7 +149,6 @@ is recommended. > - Level of complexity: **Very High** > - Required domain knowledge: Storage replication -> - Supported tiers: [GitLab Premium and Ultimate](https://about.gitlab.com/pricing/) [GitLab Geo](../geo/index.md) allows you to replicate your GitLab instance to other geographical locations as a read-only fully operational instance diff --git a/doc/administration/reference_architectures/troubleshooting.md b/doc/administration/reference_architectures/troubleshooting.md index 406ff57c66d..835231ac584 100644 --- a/doc/administration/reference_architectures/troubleshooting.md +++ b/doc/administration/reference_architectures/troubleshooting.md @@ -23,12 +23,12 @@ with the Fog library that GitLab uses. Symptoms include: ### GitLab Pages requires NFS If you intend to use [GitLab Pages](../../user/project/pages/index.md), this currently requires -[NFS](../nfs.md). There is [work in progress](https://gitlab.com/gitlab-org/gitlab-pages/-/issues/196) -to remove this dependency. In the future, GitLab Pages may use -[object storage](https://gitlab.com/gitlab-org/gitlab/-/issues/208135). +[NFS](../nfs.md). There is [work in progress](https://gitlab.com/groups/gitlab-org/-/epics/3901) +to remove this dependency. In the future, GitLab Pages will use +object storage. The dependency on disk storage also prevents Pages being deployed using the -[GitLab Helm chart](https://gitlab.com/gitlab-org/charts/gitlab/-/issues/37). +[GitLab Helm chart](https://gitlab.com/groups/gitlab-org/-/epics/4283). ### Incremental logging is required for CI to use object storage @@ -206,13 +206,8 @@ To make sure your configuration is correct: ## Troubleshooting Gitaly -### Checking versions when using standalone Gitaly nodes - -When using standalone Gitaly nodes, you must make sure they are the same version -as GitLab to ensure full compatibility. Check **Admin Area > Gitaly Servers** on -your GitLab instance and confirm all Gitaly Servers are `Up to date`. - -![Gitaly standalone software versions diagram](../gitaly/img/gitlab_gitaly_version_mismatch_v12_4.png) +If you have any problems when using standalone Gitaly nodes, first +[check all the versions are up to date](../gitaly/index.md#check-versions-when-using-standalone-gitaly-servers). ### `gitaly-debug` @@ -514,39 +509,24 @@ See the suggested fix [in Geo documentation](../geo/replication/troubleshooting. See the suggested fix [in Geo documentation](../geo/replication/troubleshooting.md#message-log--invalid-ip-mask-md5-name-or-service-not-known). -## Troubleshooting PostgreSQL +## Troubleshooting PostgreSQL with Patroni -In case you are experiencing any issues connecting through PgBouncer, the first place to check is always the logs: +In case you are experiencing any issues connecting through PgBouncer, the first place to check is always the logs for PostgreSQL (which is run through Patroni): ```shell -sudo gitlab-ctl tail postgresql +sudo gitlab-ctl tail patroni ``` -### Consul and PostgreSQL changes not taking effect +### Consul and PostgreSQL with Patroni changes not taking effect Due to the potential impacts, `gitlab-ctl reconfigure` only reloads Consul and PostgreSQL, it will not restart the services. However, not all changes can be activated by reloading. -To restart either service, run `gitlab-ctl restart SERVICE` +To restart either service, run `gitlab-ctl restart consul` or `gitlab-ctl restart patroni` respectively. -For PostgreSQL, it is usually safe to restart the master node by default. Automatic failover defaults to a 1 minute timeout. Provided the database returns before then, nothing else needs to be done. To be safe, you can stop `repmgrd` on the standby nodes first with `gitlab-ctl stop repmgrd`, then start afterwards with `gitlab-ctl start repmgrd`. +For PostgreSQL with Patroni, to prevent the primary node from being failed over automatically, it's safest to stop all secondaries first, then restart the primary and finally restart the secondaries again. On the Consul server nodes, it is important to restart the Consul service in a controlled fashion. Read our [Consul documentation](../consul.md#restart-consul) for instructions on how to restart the service. -### `gitlab-ctl repmgr-check-master` command produces errors - -If this command displays errors about database permissions it is likely that something failed during -install, resulting in the `gitlab-consul` database user getting incorrect permissions. Follow these -steps to fix the problem: - -1. On the master database node, connect to the database prompt - `gitlab-psql -d template1` -1. Delete the `gitlab-consul` user - `DROP USER "gitlab-consul";` -1. Exit the database prompt - `\q` -1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) and the user will be re-added with the proper permissions. -1. Change to the `gitlab-consul` user - `su - gitlab-consul` -1. Try the check command again - `gitlab-ctl repmgr-check-master`. - -Now there should not be errors. If errors still occur then there is another problem. - ### PgBouncer error `ERROR: pgbouncer cannot connect to server` You may get this error when running `gitlab-rake gitlab:db:configure` or you diff --git a/doc/administration/repository_storage_paths.md b/doc/administration/repository_storage_paths.md index 090f95eca12..c71d1a5714c 100644 --- a/doc/administration/repository_storage_paths.md +++ b/doc/administration/repository_storage_paths.md @@ -122,3 +122,9 @@ weights are used to determine the storage location the repository is created on. Beginning with GitLab 8.13.4, multiple paths can be chosen. New repositories are randomly placed on one of the selected paths. + +## Move a repository to a different repository path + +To move a repository to a different repository path, use the +[Project repository storage moves](../api/project_repository_storage_moves.md) API. Use +the same process as [migrating existing repositories to Gitaly Cluster](gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster). diff --git a/doc/administration/terraform_state.md b/doc/administration/terraform_state.md index edd44380f30..be5647aa133 100644 --- a/doc/administration/terraform_state.md +++ b/doc/administration/terraform_state.md @@ -20,11 +20,8 @@ These locations can be configured using the options described below. ## Using local storage -NOTE: -This is the default configuration - -To change the location where Terraform state files are stored locally, follow the steps -below. +The default configuration uses local storage. To change the location where +Terraform state files are stored locally, follow the steps below. **In Omnibus installations:** diff --git a/doc/administration/troubleshooting/elasticsearch.md b/doc/administration/troubleshooting/elasticsearch.md index 755273eb06e..fb153adfeab 100644 --- a/doc/administration/troubleshooting/elasticsearch.md +++ b/doc/administration/troubleshooting/elasticsearch.md @@ -36,6 +36,7 @@ The type of problem will determine what steps to take. The possible troubleshoot - Indexing. - Integration. - Performance. +- Background Migrations. ### Search Results workflow @@ -147,6 +148,30 @@ graph TD; F7(Escalate to<br>GitLab support.) ``` +### Background Migrations workflow + +```mermaid +graph TD; + D --> |No| D1 + D --> |Yes| D2 + D2 --> |No| D3 + D2 --> |Yes| D4 + D4 --> |No| D5 + D4 --> |Yes| D6 + D6 --> |No| D8 + D6 --> |Yes| D7 + + D{Is there a halted migration?} + D1[Migrations run in the<br>background and will<br>stop when completed.] + D2{Does the elasticsearch.log<br>file contain errors?} + D3[This is likely a bug/issue<br>in GitLab and will require<br>deeper investigation. Escalate<br>to GitLab support.] + D4{Have the errors<br>been addressed?} + D5[Have an Elasticsearch admin<br>review and address<br>the errors.] + D6{Has the migration<br>been retried?} + D7[This is likely a bug/issue<br>in GitLab and will require<br>deeper investigation. Escalate<br>to GitLab support.] + D8[Retry the migration from<br>the Admin > Settings ><br>Advanced Search UI.] +``` + ## Troubleshooting walkthrough Most Elasticsearch troubleshooting can be broken down into 4 categories: @@ -155,6 +180,7 @@ Most Elasticsearch troubleshooting can be broken down into 4 categories: - [Troubleshooting indexing](#troubleshooting-indexing) - [Troubleshooting integration](#troubleshooting-integration) - [Troubleshooting performance](#troubleshooting-performance) +- [Troubleshooting background migrations](#troubleshooting-background-migrations) Generally speaking, if it does not fall into those four categories, it is either: @@ -330,6 +356,18 @@ dig further into these. Feel free to reach out to GitLab support, but this is likely to be something a skilled Elasticsearch admin has more experience with. +### Troubleshooting background migrations + +Troubleshooting background migration failures can be difficult and may require contacting +an Elasticsearch admin or GitLab Support. + +The best place to start while debugging issues with a background migration is the +[`elasticsearch.log` file](../logs.md#elasticsearchlog). Migrations will +print information while a migration is in progress and any errors encountered. +Apply fixes for any errors found in the log and retry the migration. + +If you still encounter issues after retrying the migration, reach out to GitLab support. + ## Common issues All common issues [should be documented](../../integration/elasticsearch.md#troubleshooting). If not, diff --git a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md index 2482a4fe7ad..4a112733bfa 100644 --- a/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md +++ b/doc/administration/troubleshooting/gitlab_rails_cheat_sheet.md @@ -384,7 +384,7 @@ project = Project.find_by_full_path('PROJECT_PATH') Projects::ImportExport::ExportService.new(project, user).execute ``` -If the project you wish to export is available at `https://gitlab.example.com/baltig/pipeline-templates`, the value to use for `PROJECT_PATH` would be `baltig/pipeline-templates`. +If the project you wish to export is available at `https://gitlab.example.com/baltig/pipeline-templates`, the value to use for `PROJECT_PATH` would be `baltig/pipeline-templates`. If this all runs successfully, you will see output like the following before being returned to the Rails console prompt: @@ -392,7 +392,7 @@ If this all runs successfully, you will see output like the following before bei => nil ``` -The exported project will be located within a `.tar.gz` file in `/var/opt/gitlab/gitlab-rails/uploads/-/system/import_export_upload/export_file/`. +The exported project will be located within a `.tar.gz` file in `/var/opt/gitlab/gitlab-rails/uploads/-/system/import_export_upload/export_file/`. ## Repository @@ -598,7 +598,7 @@ group = Group.find_by_path_or_name('group-name') group.project_creation_level=0 ``` -### Modify group - disable 2FA requirement +### Modify group - disable 2FA requirement WARNING: When disabling the 2FA Requirement on a subgroup, the whole parent group (including all subgroups) is affected by this change. @@ -743,7 +743,7 @@ m.project.try(:ci_service) ```ruby project = Project.find_by_full_path 'group/project' content = project.repository.gitlab_ci_yml_for(project.repository.root_ref_sha) -Gitlab::Ci::YamlProcessor.validation_message(content, user: User.first) +Gitlab::Ci::Lint.new(project: project, current_user: User.first).validate(content) ``` ### Disable AutoDevOps on Existing Projects diff --git a/doc/administration/troubleshooting/postgresql.md b/doc/administration/troubleshooting/postgresql.md index 7052b68370c..4ccae10e5b3 100644 --- a/doc/administration/troubleshooting/postgresql.md +++ b/doc/administration/troubleshooting/postgresql.md @@ -157,7 +157,7 @@ See current settings with: ```shell sudo gitlab-rails runner "c = ApplicationRecord.connection ; puts c.execute('SHOW statement_timeout').to_a ; -puts c.execute('SHOW lock_timeout').to_a ; +puts c.execute('SHOW deadlock_timeout').to_a ; puts c.execute('SHOW idle_in_transaction_session_timeout').to_a ;" ``` @@ -165,9 +165,19 @@ It may take a little while to respond. ```ruby {"statement_timeout"=>"1min"} -{"lock_timeout"=>"0"} +{"deadlock_timeout"=>"0"} {"idle_in_transaction_session_timeout"=>"1min"} ``` +These settings can be updated in `/etc/gitlab/gitlab.rb` with: + +```ruby +postgresql['deadlock_timeout'] = '5s' +postgresql['statement_timeout'] = '15s' +postgresql['idle_in_transaction_session_timeout'] = '60s' +``` + +Once saved, [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. + NOTE: These are Omnibus GitLab settings. If an external database, such as a customer's PostgreSQL installation or Amazon RDS is being used, these values don't get set, and would have to be set externally. diff --git a/doc/administration/troubleshooting/tracing_correlation_id.md b/doc/administration/troubleshooting/tracing_correlation_id.md index 2981b9e1368..ad2b8586b8b 100644 --- a/doc/administration/troubleshooting/tracing_correlation_id.md +++ b/doc/administration/troubleshooting/tracing_correlation_id.md @@ -29,7 +29,7 @@ documentation for some popular browsers. - [Network Monitor - Firefox Developer Tools](https://developer.mozilla.org/en-US/docs/Tools/Network_Monitor) - [Inspect Network Activity In Chrome DevTools](https://developers.google.com/web/tools/chrome-devtools/network/) - [Safari Web Development Tools](https://developer.apple.com/safari/tools/) -- [Microsoft Edge Network panel](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide/network#request-details) +- [Microsoft Edge Network panel](https://docs.microsoft.com/en-us/microsoft-edge/devtools-guide-chromium/network/) To locate a relevant request and view its correlation ID: diff --git a/doc/administration/uploads.md b/doc/administration/uploads.md index 94e7bbe2cff..49af8358e29 100644 --- a/doc/administration/uploads.md +++ b/doc/administration/uploads.md @@ -8,46 +8,17 @@ info: To determine the technical writer assigned to the Stage/Group associated w Uploads represent all user data that may be sent to GitLab as a single file. As an example, avatars and notes' attachments are uploads. Uploads are integral to GitLab functionality, and therefore cannot be disabled. -## Upload parameters - -> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/214785) in GitLab 13.5. -> - It's [deployed behind a feature flag](../user/feature_flags.md), enabled by default. -> - It's enabled on GitLab.com. -> - It's recommended for production use. -> - For GitLab self-managed instances, GitLab administrators can opt to disable it. **(CORE ONLY)** - -In 13.5 and later, upload parameters are passed [between Workhorse and GitLab Rails](../development/architecture.md#simplified-component-overview) differently than they -were before. - -This change is deployed behind a feature flag that is **enabled by default**. - -If you experience any issues with upload, -[GitLab administrators with access to the GitLab Rails console](feature_flags.md) -can opt to disable it. - -To enable it: - -```ruby -Feature.enable(:upload_middleware_jwt_params_handler) -``` - -To disable it: - -```ruby -Feature.disable(:upload_middleware_jwt_params_handler) -``` - ## Using local storage This is the default configuration. To change the location where the uploads are stored locally, use the steps in this section based on your installation method: -**In Omnibus GitLab installations:** - NOTE: -For historical reasons, uploads are stored into a base directory, which by -default is `uploads/-/system`. It's strongly discouraged to change this -configuration option for an existing GitLab installation. +For historical reasons, instance level uploads (for example the [favicon](../user/admin_area/appearance.md#favicon)) are stored into a base directory, +which by default is `uploads/-/system`. It is strongly discouraged to change the base +directory on an existing GitLab installation. + +**In Omnibus GitLab installations:** _The uploads are stored by default in `/var/opt/gitlab/gitlab-rails/uploads`._ @@ -55,16 +26,17 @@ _The uploads are stored by default in `/var/opt/gitlab/gitlab-rails/uploads`._ `/etc/gitlab/gitlab.rb` and add the following line: ```ruby - gitlab_rails['uploads_storage_path'] = "/mnt/storage/" - gitlab_rails['uploads_base_dir'] = "uploads" + gitlab_rails['uploads_directory'] = "/mnt/storage/uploads" ``` + This setting only applies if you haven't changed the `gitlab_rails['uploads_storage_path']` directory. + 1. Save the file and [reconfigure GitLab](restart_gitlab.md#omnibus-gitlab-reconfigure) for the changes to take effect. **In installations from source:** _The uploads are stored by default in -`/home/git/gitlab/public/uploads/-/system`._ +`/home/git/gitlab/public/uploads`._ 1. To change the storage path for example to `/mnt/storage/uploads`, edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines: @@ -93,7 +65,7 @@ This configuration relies on valid AWS credentials to be configured already. We recommend using the [consolidated object storage settings](object_storage.md#consolidated-object-storage-configuration). The following instructions apply to the original configuration format. -## Object Storage Settings +### Object Storage Settings For source installations the following settings are nested under `uploads:` and then `object_store:`. On Omnibus GitLab installs they are prefixed by `uploads_object_store_`. @@ -106,14 +78,14 @@ For source installations the following settings are nested under `uploads:` and | `proxy_download` | Set to `true` to enable proxying all files served. Option allows to reduce egress traffic as this allows clients to download directly from remote storage instead of proxying all data | `false` | | `connection` | Various connection options described below | | -### Connection settings +#### Connection settings See [the available connection settings for different providers](object_storage.md#connection-settings). **In Omnibus installations:** _The uploads are stored by default in -`/var/opt/gitlab/gitlab-rails/public/uploads/-/system`._ +`/var/opt/gitlab/gitlab-rails/uploads`._ 1. Edit `/etc/gitlab/gitlab.rb` and add the following lines by replacing with the values you want: @@ -145,7 +117,7 @@ _The uploads are stored by default in **In installations from source:** _The uploads are stored by default in -`/home/git/gitlab/public/uploads/-/system`._ +`/home/git/gitlab/public/uploads`._ 1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines: @@ -165,12 +137,12 @@ _The uploads are stored by default in 1. Save the file and [restart GitLab](restart_gitlab.md#installations-from-source) for the changes to take effect. 1. Migrate any existing local uploads to the object storage using [`gitlab:uploads:migrate:all` Rake task](raketasks/uploads/migrate.md). -### OpenStack example +#### OpenStack example **In Omnibus installations:** _The uploads are stored by default in -`/var/opt/gitlab/gitlab-rails/public/uploads/-/system`._ +`/var/opt/gitlab/gitlab-rails/uploads`._ 1. Edit `/etc/gitlab/gitlab.rb` and add the following lines by replacing with the values you want: @@ -196,7 +168,7 @@ _The uploads are stored by default in **In installations from source:** _The uploads are stored by default in -`/home/git/gitlab/public/uploads/-/system`._ +`/home/git/gitlab/public/uploads`._ 1. Edit `/home/git/gitlab/config/gitlab.yml` and add or amend the following lines: diff --git a/doc/api/README.md b/doc/api/README.md index dced721b018..8fb3269d28b 100644 --- a/doc/api/README.md +++ b/doc/api/README.md @@ -23,9 +23,9 @@ For a list of the available resources and their endpoints, see ## SCIM **(SILVER ONLY)** -[GitLab.com Silver and higher](https://about.gitlab.com/pricing/) provides an -[SCIM API](scim.md) that both implements [the RFC7644 protocol](https://tools.ietf.org/html/rfc7644) -and provides the `/Users` endpoint. The base URL is: `/api/scim/v2/groups/:group_path/Users/`. +GitLab provides an [SCIM API](scim.md) that both implements +[the RFC7644 protocol](https://tools.ietf.org/html/rfc7644) and provides the +`/Users` endpoint. The base URL is `/api/scim/v2/groups/:group_path/Users/`. ## Road to GraphQL @@ -186,9 +186,9 @@ curl --header "Authorization: Bearer <your_access_token>" "https://gitlab.exampl ### Session cookie -When signing in to the main GitLab application, a `_gitlab_session` cookie is -set. The API uses this cookie for authentication if it's present. Using the -API to generate a new session cookie isn't supported. +Signing in to the main GitLab application sets a `_gitlab_session` cookie. The +API uses this cookie for authentication if it's present. Using the API to +generate a new session cookie isn't supported. The primary user of this authentication method is the web frontend of GitLab itself, which can, for example, use the API as the authenticated user to get a @@ -203,8 +203,7 @@ to authenticate with the API: - [Composer Repository](../user/packages/composer_repository/index.md) - [Conan Repository](../user/packages/conan_repository/index.md) - [Container Registry](../user/packages/container_registry/index.md) - (`$CI_REGISTRY_PASSWORD` is actually `$CI_JOB_TOKEN`, but this may change in - the future) + (`$CI_REGISTRY_PASSWORD` is `$CI_JOB_TOKEN`) - [Go Proxy](../user/packages/go_proxy/index.md) - [Maven Repository](../user/packages/maven_repository/index.md#authenticate-with-a-ci-job-token-in-maven) - [NPM Repository](../user/packages/npm_registry/index.md#authenticate-with-a-ci-job-token) @@ -221,12 +220,12 @@ The token is valid as long as the job is running. ### Impersonation tokens Impersonation tokens are a type of [personal access token](../user/profile/personal_access_tokens.md) -that can only be created by an administrator for a specific user. They are a great fit -if you want to build applications or scripts that authenticate with the API as a -specific user. +that can be created only by an administrator for a specific user. They can be +useful if you want to build applications or scripts that authenticate with the +API as a specific user. -They're an alternative to directly using the user's password or one of their -personal access tokens, and to using the [Sudo](#sudo) feature, as the user's +They're an alternative to directly using the user's password (or one of their +personal access tokens), and to using the [Sudo](#sudo) feature, as the user's (or administrator's in the case of Sudo) password or token may not be known, or may change over time. @@ -245,13 +244,13 @@ By default, impersonation is enabled. To disable impersonation: **For Omnibus installations** -1. Edit `/etc/gitlab/gitlab.rb`: +1. Edit the `/etc/gitlab/gitlab.rb` file: ```ruby gitlab_rails['impersonation_enabled'] = false ``` -1. Save the file and [reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) +1. Save the file, and then [reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) GitLab for the changes to take effect. To re-enable impersonation, remove this configuration, and then reconfigure @@ -259,14 +258,14 @@ GitLab. **For installations from source** -1. Edit `config/gitlab.yml`: +1. Edit the `config/gitlab.yml` file: ```yaml gitlab: impersonation_enabled: false ``` -1. Save the file and [restart](../administration/restart_gitlab.md#installations-from-source) +1. Save the file, and then [restart](../administration/restart_gitlab.md#installations-from-source) GitLab for the changes to take effect. To re-enable impersonation, remove this configuration, and then restart GitLab. @@ -353,41 +352,41 @@ The following table shows the possible return codes for API requests. | Return values | Description | |--------------------------|-------------| -| `200 OK` | The `GET`, `PUT` or `DELETE` request was successful, the resource(s) itself is returned as JSON. | -| `204 No Content` | The server has successfully fulfilled the request and that there is no additional content to send in the response payload body. | -| `201 Created` | The `POST` request was successful and the resource is returned as JSON. | -| `304 Not Modified` | Indicates that the resource has not been modified since the last request. | +| `200 OK` | The `GET`, `PUT` or `DELETE` request was successful, and the resource(s) itself is returned as JSON. | +| `204 No Content` | The server has successfully fulfilled the request, and there is no additional content to send in the response payload body. | +| `201 Created` | The `POST` request was successful, and the resource is returned as JSON. | +| `304 Not Modified` | The resource hasn't been modified since the last request. | | `400 Bad Request` | A required attribute of the API request is missing. For example, the title of an issue is not given. | -| `401 Unauthorized` | The user is not authenticated, a valid [user token](#authentication) is necessary. | -| `403 Forbidden` | The request is not allowed. For example, the user is not allowed to delete a project. | -| `404 Not Found` | A resource could not be accessed. For example, an ID for a resource could not be found. | -| `405 Method Not Allowed` | The request is not supported. | +| `401 Unauthorized` | The user isn't authenticated. A valid [user token](#authentication) is necessary. | +| `403 Forbidden` | The request isn't allowed. For example, the user isn't allowed to delete a project. | +| `404 Not Found` | A resource couldn't be accessed. For example, an ID for a resource couldn't be found. | +| `405 Method Not Allowed` | The request isn't supported. | | `409 Conflict` | A conflicting resource already exists. For example, creating a project with a name that already exists. | -| `412` | Indicates the request was denied. May happen if the `If-Unmodified-Since` header is provided when trying to delete a resource, which was modified in between. | -| `422 Unprocessable` | The entity could not be processed. | +| `412` | The request was denied. This can happen if the `If-Unmodified-Since` header is provided when trying to delete a resource, which was modified in between. | +| `422 Unprocessable` | The entity couldn't be processed. | | `429 Too Many Requests` | The user exceeded the [application rate limits](../administration/instance_limits.md#rate-limits). | -| `500 Server Error` | While handling the request, something went wrong server-side. | +| `500 Server Error` | While handling the request, something went wrong on the server. | ## Pagination GitLab supports the following pagination methods: -- Offset-based pagination. This is the default method and available on all endpoints. +- Offset-based pagination. This is the default method and is available on all endpoints. - Keyset-based pagination. Added to selected endpoints but being [progressively rolled out](https://gitlab.com/groups/gitlab-org/-/epics/2039). -For large collections, we recommend keyset pagination (when available) instead -of offset pagination for performance reasons. +For large collections, for performance reasons we recommend keyset pagination +(when available) instead of offset pagination. ### Offset-based pagination Sometimes, the returned result spans many pages. When listing resources, you can pass the following parameters: -| Parameter | Description | -|-----------|-------------| -| `page` | Page number (default: `1`). | -| `per_page`| Number of items to list per page (default: `20`, max: `100`). | +| Parameter | Description | +|------------|-------------| +| `page` | Page number (default: `1`). | +| `per_page` | Number of items to list per page (default: `20`, max: `100`). | In the following example, we list 50 [namespaces](namespaces.md) per page: @@ -485,10 +484,10 @@ header was [added in GitLab 13.1](https://gitlab.com/gitlab-org/gitlab/-/merge_r and should be used instead. The link to the next page contains an additional filter `id_after=42` that -excludes already-retrieved records. Note the type of filter depends on the +excludes already-retrieved records. The type of filter depends on the `order_by` option used, and we may have more than one additional filter. -When the end of the collection has been reached and there are no additional +When the end of the collection is reached and there are no additional records to retrieve, the `Link` header is absent and the resulting array is empty. diff --git a/doc/api/api_resources.md b/doc/api/api_resources.md index c6fd5b7c45c..029e434749f 100644 --- a/doc/api/api_resources.md +++ b/doc/api/api_resources.md @@ -158,6 +158,7 @@ The following API resources are available outside of project and group contexts | [Runners](runners.md) | `/runners` (also available for projects) | | [Search](search.md) | `/search` (also available for groups and projects) | | [Settings](settings.md) **(CORE ONLY)** | `/application/settings` | +| [Snippet repository storage moves](snippet_repository_storage_moves.md) **(CORE ONLY)** | `/snippet_repository_storage_moves` | | [Statistics](statistics.md) | `/application/statistics` | | [Sidekiq metrics](sidekiq_metrics.md) **(CORE ONLY)** | `/sidekiq` | | [Suggestions](suggestions.md) | `/suggestions` | diff --git a/doc/api/appearance.md b/doc/api/appearance.md index b33e41cf271..d03fc94cfcf 100644 --- a/doc/api/appearance.md +++ b/doc/api/appearance.md @@ -60,8 +60,8 @@ PUT /application/appearance | `favicon` | mixed | no | Instance favicon in `.ico` or `.png` format | `new_project_guidelines` | string | no | Markdown text shown on the new project page | `profile_image_guidelines` | string | no | Markdown text shown on the profile page below Public Avatar -| `header_message` | string | no | Message within the system header bar -| `footer_message` | string | no | Message within the system footer bar +| `header_message` | string | no | Message in the system header bar +| `footer_message` | string | no | Message in the system footer bar | `message_background_color` | string | no | Background color for the system header / footer bar | `message_font_color` | string | no | Font color for the system header / footer bar | `email_header_and_footer_enabled` | boolean | no | Add header and footer to all outgoing emails if enabled diff --git a/doc/api/audit_events.md b/doc/api/audit_events.md index 282c4ccfeea..5017c8defaf 100644 --- a/doc/api/audit_events.md +++ b/doc/api/audit_events.md @@ -1,6 +1,6 @@ --- -stage: none -group: unassigned +stage: Manage +group: Compliance info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/api/avatar.md b/doc/api/avatar.md index 31f254c7986..ccaa50eedd8 100644 --- a/doc/api/avatar.md +++ b/doc/api/avatar.md @@ -30,7 +30,7 @@ Parameters: | Attribute | Type | Required | Description | |:----------|:--------|:---------|:----------------------------------------------------------------------------------------------------------------------------------------| | `email` | string | yes | Public email address of the user. | -| `size` | integer | no | Single pixel dimension (since images are squares). Only used for avatar lookups at `Gravatar` or at the configured `Libravatar` server. | +| `size` | integer | no | Single pixel dimension (because images are squares). Only used for avatar lookups at `Gravatar` or at the configured `Libravatar` server. | Example request: diff --git a/doc/api/boards.md b/doc/api/boards.md index aff82daa1bf..e86f0d846ed 100644 --- a/doc/api/boards.md +++ b/doc/api/boards.md @@ -426,7 +426,7 @@ POST /projects/:id/boards/:board_id/lists NOTE: Label, assignee and milestone arguments are mutually exclusive, that is, only one of them are accepted in a request. -Check the [Issue Board docs](../user/project/issue_board.md) +Check the [Issue Board documentation](../user/project/issue_board.md) for more information regarding the required license for each list type. ```shell diff --git a/doc/api/container_registry.md b/doc/api/container_registry.md index 5f3dbcb1ab0..f29f8aaf6e9 100644 --- a/doc/api/container_registry.md +++ b/doc/api/container_registry.md @@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/55978) in GitLab 11.8. -This is the API docs of the [GitLab Container Registry](../user/packages/container_registry/index.md). +This is the API documentation of the [GitLab Container Registry](../user/packages/container_registry/index.md). ## List registry repositories @@ -313,6 +313,13 @@ You can run this at most once an hour for a given container repository. This action doesn't delete blobs. To delete them and recycle disk space, [run the garbage collection](https://docs.gitlab.com/omnibus/maintenance/README.html#removing-unused-layers-not-referenced-by-manifests). +WARNING: +The number of tags deleted by this API is limited on GitLab.com +because of the scale of the Container Registry there. +If your Container Registry has a large number of tags to delete, +only some of them will be deleted, and you might need to call this API multiple times. +To schedule tags for automatic deletion, use a [cleanup policy](../user/packages/container_registry/index.md#cleanup-policy) instead. + NOTE: In GitLab 12.4 and later, individual tags are deleted. For more details, see the [discussion](https://gitlab.com/gitlab-org/gitlab/-/issues/15737). diff --git a/doc/api/deploy_keys.md b/doc/api/deploy_keys.md index 293f7218527..91046717c1d 100644 --- a/doc/api/deploy_keys.md +++ b/doc/api/deploy_keys.md @@ -109,8 +109,8 @@ Example response: Creates a new deploy key for a project. -If the deploy key already exists in another project, it will be joined to current -project only if original one is accessible by the same user. +If the deploy key already exists in another project, it's joined to the current +project only if the original one is accessible by the same user. ```plaintext POST /projects/:id/deploy_keys @@ -171,7 +171,7 @@ Example response: ## Delete deploy key -Removes a deploy key from the project. If the deploy key is used only for this project, it will be deleted from the system. +Removes a deploy key from the project. If the deploy key is used only for this project, it's deleted from the system. ```plaintext DELETE /projects/:id/deploy_keys/:key_id diff --git a/doc/api/deployments.md b/doc/api/deployments.md index 4a937cd1818..b8865ecc614 100644 --- a/doc/api/deployments.md +++ b/doc/api/deployments.md @@ -379,7 +379,7 @@ This API retrieves the list of merge requests shipped with a given deployment: GET /projects/:id/deployments/:deployment_id/merge_requests ``` -It supports the same parameters as the [Merge Requests API](merge_requests.md#list-merge-requests) and will return a response using the same format: +It supports the same parameters as the [Merge Requests API](merge_requests.md#list-merge-requests) and returns a response using the same format: ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/deployments/42" diff --git a/doc/api/discussions.md b/doc/api/discussions.md index 51ca2bea3ae..a7a53987fe9 100644 --- a/doc/api/discussions.md +++ b/doc/api/discussions.md @@ -687,7 +687,8 @@ GET /projects/:id/merge_requests/:merge_request_iid/discussions "noteable_iid": null, "resolved": false, "resolvable": true, - "resolved_by": null + "resolved_by": null, + "resolved_at": null }, { "id": 1129, diff --git a/doc/api/epic_links.md b/doc/api/epic_links.md index 319d1a1ee9b..cabab18ed71 100644 --- a/doc/api/epic_links.md +++ b/doc/api/epic_links.md @@ -76,7 +76,7 @@ Example response: Creates an association between two epics, designating one as the parent epic and the other as the child epic. A parent epic can have multiple child epics. If the new child epic already belonged to another epic, it is unassigned from that previous parent. ```plaintext -POST /groups/:id/epics/:epic_iid/epics +POST /groups/:id/epics/:epic_iid/epics/:child_epic_id ``` | Attribute | Type | Required | Description | diff --git a/doc/api/epics.md b/doc/api/epics.md index dc582808578..d501d61bfb8 100644 --- a/doc/api/epics.md +++ b/doc/api/epics.md @@ -11,9 +11,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w Every API call to epic must be authenticated. -If a user is not a member of a group and the group is private, a `GET` request on that group will result to a `404` status code. +If a user is not a member of a private group, a `GET` request on that group results in a `404` status code. -If epics feature is not available a `403` status code will be returned. +If epics feature is not available a `403` status code is returned. ## Epic issues API @@ -23,9 +23,10 @@ The [epic issues API](epic_issues.md) allows you to interact with issues associa > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/6448) in GitLab 11.3. -Since start date and due date can be dynamically sourced from related issue milestones, when user has edit permission, -additional fields will be shown. These include two boolean fields `start_date_is_fixed` and `due_date_is_fixed`, -and four date fields `start_date_fixed`, `start_date_from_inherited_source`, `due_date_fixed` and `due_date_from_inherited_source`. +Because start date and due date can be dynamically sourced from related issue milestones, +additional fields are shown when user has edit permission. These include two boolean +fields `start_date_is_fixed` and `due_date_is_fixed`, and four date fields `start_date_fixed`, +`start_date_from_inherited_source`, `due_date_fixed` and `due_date_from_inherited_source`. - `end_date` has been deprecated in favor of `due_date`. - `start_date_from_milestones` has been deprecated in favor of `start_date_from_inherited_source` @@ -40,7 +41,7 @@ Read more on [pagination](README.md#pagination). WARNING: > `reference` attribute in response is deprecated in favour of `references`. -> Introduced [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354) +> Introduced in [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354) NOTE: > `references.relative` is relative to the group that the epic is being requested. When epic is fetched from its origin group @@ -62,7 +63,7 @@ GET /groups/:id/epics?state=opened | `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user | | `author_id` | integer | no | Return epics created by the given user `id` | | `labels` | string | no | Return epics matching a comma separated list of labels names. Label names from the epic group or a parent group can be used | -| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)| +| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Available in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) and later | | `order_by` | string | no | Return epics ordered by `created_at` or `updated_at` fields. Default is `created_at` | | `sort` | string | no | Return epics sorted in `asc` or `desc` order. Default is `desc` | | `search` | string | no | Search epics against their `title` and `description` | @@ -73,7 +74,7 @@ GET /groups/:id/epics?state=opened | `updated_before` | datetime | no | Return epics updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `include_ancestor_groups` | boolean | no | Include epics from the requested group's ancestors. Default is `false` | | `include_descendant_groups` | boolean | no | Include epics from the requested group's descendants. Default is `true` | -| `my_reaction_emoji` | string | no | Return epics reacted by the authenticated user by the given emoji. `None` returns epics not given a reaction. `Any` returns epics given at least one reaction. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31479)| +| `my_reaction_emoji` | string | no | Return epics reacted by the authenticated user by the given emoji. `None` returns epics not given a reaction. `Any` returns epics given at least one reaction. Available in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31479) and later | ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/epics" @@ -267,12 +268,12 @@ POST /groups/:id/epics | `labels` | string | no | The comma separated list of labels | | `description` | string | no | The description of the epic. Limited to 1,048,576 characters. | | `confidential` | boolean | no | Whether the epic should be confidential | -| `created_at` | string | no | When the epic was created. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` . Requires administrator or project/group owner privileges ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255309) in GitLab 13.5) | -| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (since 11.3) | -| `start_date_fixed` | string | no | The fixed start date of an epic (since 11.3) | -| `due_date_is_fixed` | boolean | no | Whether due date should be sourced from `due_date_fixed` or from milestones (since 11.3) | -| `due_date_fixed` | string | no | The fixed due date of an epic (since 11.3) | -| `parent_id` | integer/string | no | The ID of a parent epic (since 11.11) | +| `created_at` | string | no | When the epic was created. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` . Requires administrator or project/group owner privileges ([available](https://gitlab.com/gitlab-org/gitlab/-/issues/255309) in GitLab 13.5 and later) | +| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (in GitLab 11.3 and later) | +| `start_date_fixed` | string | no | The fixed start date of an epic (in GitLab 11.3 and later) | +| `due_date_is_fixed` | boolean | no | Whether due date should be sourced from `due_date_fixed` or from milestones (in GitLab 11.3 and later) | +| `due_date_fixed` | string | no | The fixed due date of an epic (in GitLab 11.3 and later) | +| `parent_id` | integer/string | no | The ID of a parent epic (in GitLab 11.11 and later) | ```shell curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/epics?title=Epic&description=Epic%20description" @@ -352,12 +353,12 @@ PUT /groups/:id/epics/:epic_iid | `labels` | string | no | Comma-separated label names for an issue. Set to an empty string to unassign all labels. | | `add_labels` | string | no | Comma-separated label names to add to an issue. | | `remove_labels` | string | no | Comma-separated label names to remove from an issue. | -| `updated_at` | string | no | When the epic was updated. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` . Requires administrator or project/group owner privileges ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/255309) in GitLab 13.5) | -| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (since 11.3) | -| `start_date_fixed` | string | no | The fixed start date of an epic (since 11.3) | -| `due_date_is_fixed` | boolean | no | Whether due date should be sourced from `due_date_fixed` or from milestones (since 11.3) | -| `due_date_fixed` | string | no | The fixed due date of an epic (since 11.3) | -| `state_event` | string | no | State event for an epic. Set `close` to close the epic and `reopen` to reopen it (since 11.4) | +| `updated_at` | string | no | When the epic was updated. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z` . Requires administrator or project/group owner privileges ([available](https://gitlab.com/gitlab-org/gitlab/-/issues/255309) in GitLab 13.5 and later) | +| `start_date_is_fixed` | boolean | no | Whether start date should be sourced from `start_date_fixed` or from milestones (in GitLab 11.3 and later) | +| `start_date_fixed` | string | no | The fixed start date of an epic (in GitLab 11.3 and later) | +| `due_date_is_fixed` | boolean | no | Whether due date should be sourced from `due_date_fixed` or from milestones (in GitLab 11.3 and later) | +| `due_date_fixed` | string | no | The fixed due date of an epic (in GitLab 11.3 and later) | +| `state_event` | string | no | State event for an epic. Set `close` to close the epic and `reopen` to reopen it (in GitLab 11.4 and later) | ```shell curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/1/epics/5?title=New%20Title" diff --git a/doc/api/features.md b/doc/api/features.md index 0582a4b9432..0ed0dec1b6d 100644 --- a/doc/api/features.md +++ b/doc/api/features.md @@ -111,8 +111,8 @@ Example response: ## Set or create a feature -Set a feature's gate value. If a feature with the given name doesn't exist yet -it will be created. The value can be a boolean, or an integer to indicate +Set a feature's gate value. If a feature with the given name doesn't exist yet, +it's created. The value can be a boolean, or an integer to indicate percentage of time. ```plaintext diff --git a/doc/api/graphql/img/users_query_example_v13_8.png b/doc/api/graphql/img/users_query_example_v13_8.png Binary files differnew file mode 100644 index 00000000000..b4c2b4e999a --- /dev/null +++ b/doc/api/graphql/img/users_query_example_v13_8.png diff --git a/doc/api/graphql/index.md b/doc/api/graphql/index.md index 681130e82c1..45a327d323b 100644 --- a/doc/api/graphql/index.md +++ b/doc/api/graphql/index.md @@ -82,6 +82,10 @@ The process is as follows: release post (at or prior to X.11 and X.5 releases). 1. Fields meeting criteria are removed in X.0 or X.6. +NOTE: +Fields behind a feature flag and disabled by default are exempt from the deprecation process, +and can be removed at any time without notice. + ### List of removed items View the [fields, enums, and other items we removed](removed_items.md) from the GraphQL API. diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql index 8218d792fe8..94792a49933 100644 --- a/doc/api/graphql/reference/gitlab_schema.graphql +++ b/doc/api/graphql/reference/gitlab_schema.graphql @@ -30,7 +30,7 @@ Autogenerated input type of AddAwardEmoji """ input AddAwardEmojiInput { """ - The global ID of the awardable resource + The global ID of the awardable resource. """ awardableId: AwardableID! @@ -50,7 +50,7 @@ Autogenerated return type of AddAwardEmoji """ type AddAwardEmojiPayload { """ - The award emoji after mutation + The award emoji after mutation. """ awardEmoji: AwardEmoji @@ -75,7 +75,7 @@ input AddProjectToSecurityDashboardInput { clientMutationId: String """ - ID of the project to be added to Instance Security Dashboard + ID of the project to be added to Instance Security Dashboard. """ id: ProjectID! } @@ -95,7 +95,7 @@ type AddProjectToSecurityDashboardPayload { errors: [String!]! """ - Project that was added to the Instance Security Dashboard + Project that was added to the Instance Security Dashboard. """ project: Project } @@ -125,7 +125,7 @@ input AdminSidekiqQueuesDeleteJobsInput { project: String """ - The name of the queue to delete jobs from + The name of the queue to delete jobs from. """ queueName: String! @@ -135,6 +135,11 @@ input AdminSidekiqQueuesDeleteJobsInput { relatedClass: String """ + Delete jobs matching remote_ip in the context metadata + """ + remoteIp: String + + """ Delete jobs matching root_namespace in the context metadata """ rootNamespace: String @@ -165,7 +170,7 @@ type AdminSidekiqQueuesDeleteJobsPayload { errors: [String!]! """ - Information about the status of the deletion request + Information about the status of the deletion request. """ result: DeleteJobsResponse } @@ -349,7 +354,7 @@ type AlertManagementAlert implements Noteable { """ todos( """ - The action to be filtered + The action to be filtered. """ action: [TodoActionEnum!] @@ -359,7 +364,7 @@ type AlertManagementAlert implements Noteable { after: String """ - The ID of an author + The ID of an author. """ authorId: [ID!] @@ -374,7 +379,7 @@ type AlertManagementAlert implements Noteable { first: Int """ - The ID of a group + The ID of a group. """ groupId: [ID!] @@ -384,17 +389,17 @@ type AlertManagementAlert implements Noteable { last: Int """ - The ID of a project + The ID of a project. """ projectId: [ID!] """ - The state of the todo + The state of the todo. """ state: [TodoStateEnum!] """ - The type of the todo + The type of the todo. """ type: [TodoTargetEnum!] ): TodoConnection @@ -595,7 +600,7 @@ Filters the alerts based on given domain """ enum AlertManagementDomainFilter { """ - Alerts for operations domain + Alerts for operations domain """ operations @@ -738,6 +743,106 @@ enum AlertManagementIntegrationType { } """ +Field that are available while modifying the custom mapping attributes for an HTTP integration +""" +input AlertManagementPayloadAlertFieldInput { + """ + A GitLab alert field name. + """ + fieldName: AlertManagementPayloadAlertFieldName! + + """ + Human-readable label of the payload path. + """ + label: String + + """ + Path to value inside payload JSON. + """ + path: [String!]! + + """ + Type of the parsed value. + """ + type: AlertManagementPayloadAlertFieldType! +} + +""" +Values for alert field names used in the custom mapping +""" +enum AlertManagementPayloadAlertFieldName { + """ + A high-level summary of the problem. + """ + DESCRIPTION + + """ + The resolved time of the incident. + """ + END_TIME + + """ + The unique identifier of the alert. This can be used to group occurrences of the same alert. + """ + FINGERPRINT + + """ + The name of the associated GitLab environment. + """ + GITLAB_ENVIRONMENT_NAME + + """ + One or more hosts, as to where this incident occurred. + """ + HOSTS + + """ + The name of the associated monitoring tool. + """ + MONITORING_TOOL + + """ + The affected service. + """ + SERVICE + + """ + The severity of the alert. + """ + SEVERITY + + """ + The time of the incident. + """ + START_TIME + + """ + The title of the incident. + """ + TITLE +} + +""" +Values for alert field types used in the custom mapping +""" +enum AlertManagementPayloadAlertFieldType { + """ + Array field type + """ + ARRAY + + """ + DateTime field type + """ + DATETIME + + """ + String field type + """ + STRING +} + +""" An endpoint and credentials used to accept Prometheus alerts for a project """ type AlertManagementPrometheusIntegration implements AlertManagementIntegration { @@ -852,7 +957,7 @@ input AlertSetAssigneesInput { clientMutationId: String """ - The IID of the alert to mutate + The IID of the alert to mutate. """ iid: String! @@ -862,7 +967,7 @@ input AlertSetAssigneesInput { operationMode: MutationOperationMode """ - The project the alert to mutate is in + The project the alert to mutate is in. """ projectPath: ID! } @@ -872,7 +977,7 @@ Autogenerated return type of AlertSetAssignees """ type AlertSetAssigneesPayload { """ - The alert after mutation + The alert after mutation. """ alert: AlertManagementAlert @@ -887,12 +992,12 @@ type AlertSetAssigneesPayload { errors: [String!]! """ - The issue created after mutation + The issue created after mutation. """ issue: Issue """ - The todo after mutation + The todo after mutation. """ todo: Todo } @@ -907,12 +1012,12 @@ input AlertTodoCreateInput { clientMutationId: String """ - The IID of the alert to mutate + The IID of the alert to mutate. """ iid: String! """ - The project the alert to mutate is in + The project the alert to mutate is in. """ projectPath: ID! } @@ -922,7 +1027,7 @@ Autogenerated return type of AlertTodoCreate """ type AlertTodoCreatePayload { """ - The alert after mutation + The alert after mutation. """ alert: AlertManagementAlert @@ -937,12 +1042,12 @@ type AlertTodoCreatePayload { errors: [String!]! """ - The issue created after mutation + The issue created after mutation. """ issue: Issue """ - The todo after mutation + The todo after mutation. """ todo: Todo } @@ -1007,7 +1112,7 @@ Autogenerated input type of AwardEmojiAdd """ input AwardEmojiAddInput { """ - The global ID of the awardable resource + The global ID of the awardable resource. """ awardableId: AwardableID! @@ -1027,7 +1132,7 @@ Autogenerated return type of AwardEmojiAdd """ type AwardEmojiAddPayload { """ - The award emoji after mutation + The award emoji after mutation. """ awardEmoji: AwardEmoji @@ -1047,7 +1152,7 @@ Autogenerated input type of AwardEmojiRemove """ input AwardEmojiRemoveInput { """ - The global ID of the awardable resource + The global ID of the awardable resource. """ awardableId: AwardableID! @@ -1067,7 +1172,7 @@ Autogenerated return type of AwardEmojiRemove """ type AwardEmojiRemovePayload { """ - The award emoji after mutation + The award emoji after mutation. """ awardEmoji: AwardEmoji @@ -1087,7 +1192,7 @@ Autogenerated input type of AwardEmojiToggle """ input AwardEmojiToggleInput { """ - The global ID of the awardable resource + The global ID of the awardable resource. """ awardableId: AwardableID! @@ -1107,7 +1212,7 @@ Autogenerated return type of AwardEmojiToggle """ type AwardEmojiTogglePayload { """ - The award emoji after mutation + The award emoji after mutation. """ awardEmoji: AwardEmoji @@ -1275,7 +1380,7 @@ type Board { first: Int """ - Filters applied when selecting issues on the board + Filters applied when selecting issues on the board. """ issueFilters: BoardIssueInput @@ -1350,12 +1455,12 @@ type Board { first: Int """ - Find a list by its global ID + Find a list by its global ID. """ id: ListID """ - Filters applied when getting issue metadata in the board list + Filters applied when getting issue metadata in the board list. """ issueFilters: BoardIssueInput @@ -1376,6 +1481,16 @@ type Board { name: String """ + Web path of the board. + """ + webPath: String! + + """ + Web URL of the board. + """ + webUrl: String! + + """ Weight of the board """ weight: Int @@ -1435,7 +1550,7 @@ type BoardEpic implements CurrentUserTodos & Noteable { after: String """ - Filter epics by author + Filter epics by author. """ authorUsername: String @@ -1445,6 +1560,11 @@ type BoardEpic implements CurrentUserTodos & Noteable { before: String """ + Filter epics by given confidentiality. + """ + confidential: Boolean + + """ List items overlapping a time frame defined by startDate..endDate (if one date is provided, both must be present) Deprecated in 13.5: Use timeframe.end. """ @@ -1456,27 +1576,27 @@ type BoardEpic implements CurrentUserTodos & Noteable { first: Int """ - IID of the epic, e.g., "1" + IID of the epic, e.g., "1". """ iid: ID """ - Filter epics by IID for autocomplete + Filter epics by IID for autocomplete. """ iidStartsWith: String """ - List of IIDs of epics, e.g., [1, 2] + List of IIDs of epics, e.g., [1, 2]. """ iids: [ID!] """ - Include epics from descendant groups + Include epics from descendant groups. """ includeDescendantGroups: Boolean = true """ - Filter epics by labels + Filter epics by labels. """ labelName: [String!] @@ -1486,17 +1606,17 @@ type BoardEpic implements CurrentUserTodos & Noteable { last: Int """ - Filter epics by milestone title, computed from epic's issues + Filter epics by milestone title, computed from epic's issues. """ milestoneTitle: String """ - Search query for epic title or description + Search query for epic title or description. """ search: String """ - List epics by sort order + List epics by sort order. """ sort: EpicSort @@ -1508,12 +1628,12 @@ type BoardEpic implements CurrentUserTodos & Noteable { startDate: Time """ - Filter epics by state + Filter epics by state. """ state: EpicState """ - List items overlapping the given timeframe + List items overlapping the given timeframe. """ timeframe: Timeframe ): EpicConnection @@ -2015,7 +2135,7 @@ type BoardList { before: String """ - Filters applied when selecting issues in the board list + Filters applied when selecting issues in the board list. """ filters: BoardIssueInput @@ -2036,6 +2156,11 @@ type BoardList { issuesCount: Int """ + Iteration of the list + """ + iteration: Iteration + + """ Label of the list """ label: Label @@ -2106,17 +2231,17 @@ Autogenerated input type of BoardListCreate """ input BoardListCreateInput { """ - Global ID of an existing user + Global ID of an existing user. """ assigneeId: UserID """ - Create the backlog list + Create the backlog list. """ backlog: Boolean """ - Global ID of the issue board to mutate + Global ID of the issue board to mutate. """ boardId: BoardID! @@ -2126,17 +2251,17 @@ input BoardListCreateInput { clientMutationId: String """ - Global ID of an existing iteration + Global ID of an existing iteration. """ iterationId: IterationID """ - Global ID of an existing label + Global ID of an existing label. """ labelId: LabelID """ - Global ID of an existing milestone + Global ID of an existing milestone. """ milestoneId: MilestoneID } @@ -2156,7 +2281,7 @@ type BoardListCreatePayload { errors: [String!]! """ - List of the issue board + List of the issue board. """ list: BoardList } @@ -2221,7 +2346,7 @@ type BoardListUpdateLimitMetricsPayload { errors: [String!]! """ - The updated list + The updated list. """ list: BoardList } @@ -2231,6 +2356,11 @@ Identifier of Boards::EpicBoard """ scalar BoardsEpicBoardID +""" +Identifier of Boards::EpicList +""" +scalar BoardsEpicListID + type Branch { """ Commit for the branch @@ -2273,6 +2403,83 @@ type BurnupChartDailyTotals { scopeWeight: Int! } +type CiBuildNeed { + """ + Name of the job we need to complete. + """ + name: String +} + +""" +The connection type for CiBuildNeed. +""" +type CiBuildNeedConnection { + """ + A list of edges. + """ + edges: [CiBuildNeedEdge] + + """ + A list of nodes. + """ + nodes: [CiBuildNeed] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type CiBuildNeedEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: CiBuildNeed +} + +""" +Autogenerated input type of CiCdSettingsUpdate +""" +input CiCdSettingsUpdateInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Full Path of the project the settings belong to. + """ + fullPath: ID! + + """ + Indicates if the latest artifact should be kept for this project. + """ + keepLatestArtifact: Boolean +} + +""" +Autogenerated return type of CiCdSettingsUpdate +""" +type CiCdSettingsUpdatePayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! +} + type CiConfig { """ Linting errors @@ -2287,7 +2494,27 @@ type CiConfig { """ Stages of the pipeline """ - stages: [CiConfigStage!] + stages( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): CiConfigStageConnection """ Status of linting, can be either valid or invalid @@ -2299,7 +2526,27 @@ type CiConfigGroup { """ Jobs in group """ - jobs: [CiConfigJob!] + jobs( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): CiConfigJobConnection """ Name of the job group @@ -2312,26 +2559,168 @@ type CiConfigGroup { size: Int } +""" +The connection type for CiConfigGroup. +""" +type CiConfigGroupConnection { + """ + A list of edges. + """ + edges: [CiConfigGroupEdge] + + """ + A list of nodes. + """ + nodes: [CiConfigGroup] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type CiConfigGroupEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: CiConfigGroup +} + type CiConfigJob { """ - Name of the job group + Override a set of commands that are executed after the job. + """ + afterScript: [String!] + + """ + Allow job to fail. + """ + allowFailure: Boolean + + """ + Override a set of commands that are executed before the job. + """ + beforeScript: [String!] + + """ + Name of an environment to which the job deploys. + """ + environment: String + + """ + Limit when jobs are not created. + """ + except: CiConfigJobRestriction + + """ + Name of the job group. """ groupName: String """ - Name of the job + Name of the job. """ name: String """ - Builds that must complete before the jobs run + Builds that must complete before the jobs run. + """ + needs( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): CiConfigNeedConnection + + """ + Jobs are created when these conditions do not apply. """ - needs: [CiConfigNeed!] + only: CiConfigJobRestriction """ - Name of the job stage + Shell script that is executed by a runner. + """ + script: [String!] + + """ + Name of the job stage. """ stage: String + + """ + List of tags that are used to select a runner. + """ + tags: [String!] + + """ + When to run the job. + """ + when: String +} + +""" +The connection type for CiConfigJob. +""" +type CiConfigJobConnection { + """ + A list of edges. + """ + edges: [CiConfigJobEdge] + + """ + A list of nodes. + """ + nodes: [CiConfigJob] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type CiConfigJobEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: CiConfigJob +} + +type CiConfigJobRestriction { + """ + The Git refs the job restriction applies to. + """ + refs: [String!] } type CiConfigNeed { @@ -2341,11 +2730,66 @@ type CiConfigNeed { name: String } +""" +The connection type for CiConfigNeed. +""" +type CiConfigNeedConnection { + """ + A list of edges. + """ + edges: [CiConfigNeedEdge] + + """ + A list of nodes. + """ + nodes: [CiConfigNeed] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type CiConfigNeedEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: CiConfigNeed +} + type CiConfigStage { """ Groups of jobs for the stage """ - groups: [CiConfigGroup!] + groups( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): CiConfigGroupConnection """ Name of the stage @@ -2354,6 +2798,41 @@ type CiConfigStage { } """ +The connection type for CiConfigStage. +""" +type CiConfigStageConnection { + """ + A list of edges. + """ + edges: [CiConfigStageEdge] + + """ + A list of nodes. + """ + nodes: [CiConfigStage] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type CiConfigStageEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: CiConfigStage +} + +""" Values for YAML processor result """ enum CiConfigStatus { @@ -2482,7 +2961,7 @@ type CiJob { name: String """ - Builds that must complete before the jobs run + References to builds that must complete before the jobs run """ needs( """ @@ -2504,7 +2983,7 @@ type CiJob { Returns the last _n_ elements from the list. """ last: Int - ): CiJobConnection + ): CiBuildNeedConnection """ Pipeline the job belongs to @@ -2763,7 +3242,7 @@ input ClusterAgentDeleteInput { clientMutationId: String """ - Global ID of the cluster agent that will be deleted + Global ID of the cluster agent that will be deleted. """ id: ClustersAgentID! } @@ -2850,7 +3329,7 @@ input ClusterAgentTokenCreateInput { clientMutationId: String """ - Global ID of the cluster agent that will be associated with the new token + Global ID of the cluster agent that will be associated with the new token. """ clusterAgentId: ClustersAgentID! } @@ -2870,12 +3349,12 @@ type ClusterAgentTokenCreatePayload { errors: [String!]! """ - Token secret value. Make sure you save it - you won't be able to access it again + Token secret value. Make sure you save it - you won't be able to access it again. """ secret: String """ - Token created after mutation + Token created after mutation. """ token: ClusterAgentToken } @@ -2890,7 +3369,7 @@ input ClusterAgentTokenDeleteInput { clientMutationId: String """ - Global ID of the cluster agent token that will be deleted + Global ID of the cluster agent token that will be deleted. """ id: ClustersAgentTokenID! } @@ -3086,17 +3565,17 @@ type Commit { last: Int """ - Filter pipelines by the ref they are run for + Filter pipelines by the ref they are run for. """ ref: String """ - Filter pipelines by the sha of the commit they are run for + Filter pipelines by the sha of the commit they are run for. """ sha: String """ - Filter pipelines by their status + Filter pipelines by their status. """ status: PipelineStatusEnum ): PipelineConnection @@ -3229,12 +3708,12 @@ Autogenerated input type of CommitCreate """ input CommitCreateInput { """ - Array of action hashes to commit as a batch + Array of action hashes to commit as a batch. """ actions: [CommitAction!]! """ - Name of the branch to commit into, it can be a new branch + Name of the branch to commit into, it can be a new branch. """ branch: String! @@ -3249,12 +3728,12 @@ input CommitCreateInput { message: String! """ - Project full path the branch is associated with + Project full path the branch is associated with. """ projectPath: ID! """ - If on a new branch, name of the original branch + If on a new branch, name of the original branch. """ startBranch: String } @@ -3269,7 +3748,7 @@ type CommitCreatePayload { clientMutationId: String """ - The commit after mutation + The commit after mutation. """ commit: Commit @@ -3366,6 +3845,23 @@ type ComplianceFrameworkEdge { node: ComplianceFramework } +input ComplianceFrameworkInput { + """ + New color representation of the compliance framework in hex format. e.g. #FCA121. + """ + color: String + + """ + New description for the compliance framework. + """ + description: String + + """ + New name for the compliance framework. + """ + name: String +} + """ Identifier of ComplianceManagement::Framework """ @@ -3381,12 +3877,12 @@ input ConfigureSastInput { clientMutationId: String """ - SAST CI configuration for the project + SAST CI configuration for the project. """ configuration: SastCiConfigurationInput! """ - Full path of the project + Full path of the project. """ projectPath: ID! } @@ -3406,12 +3902,12 @@ type ConfigureSastPayload { errors: [String!]! """ - Status of creating the commit for the supplied SAST CI configuration + Status of creating the commit for the supplied SAST CI configuration. """ status: String! """ - Redirect path to use when the response is successful + Redirect path to use when the response is successful. """ successPath: String } @@ -3877,12 +4373,12 @@ input CreateAlertIssueInput { clientMutationId: String """ - The IID of the alert to mutate + The IID of the alert to mutate. """ iid: String! """ - The project the alert to mutate is in + The project the alert to mutate is in. """ projectPath: ID! } @@ -3892,7 +4388,7 @@ Autogenerated return type of CreateAlertIssue """ type CreateAlertIssuePayload { """ - The alert after mutation + The alert after mutation. """ alert: AlertManagementAlert @@ -3907,12 +4403,12 @@ type CreateAlertIssuePayload { errors: [String!]! """ - The issue created after mutation + The issue created after mutation. """ issue: Issue """ - The todo after mutation + The todo after mutation. """ todo: Todo } @@ -3927,32 +4423,32 @@ input CreateAnnotationInput { clientMutationId: String """ - The global ID of the cluster to add an annotation to + The global ID of the cluster to add an annotation to. """ clusterId: ClustersClusterID """ - The path to a file defining the dashboard on which the annotation should be added + The path to a file defining the dashboard on which the annotation should be added. """ dashboardPath: String! """ - The description of the annotation + The description of the annotation. """ description: String! """ - Timestamp indicating ending moment to which the annotation relates + Timestamp indicating ending moment to which the annotation relates. """ endingAt: Time """ - The global ID of the environment to add an annotation to + The global ID of the environment to add an annotation to. """ environmentId: EnvironmentID """ - Timestamp indicating starting moment to which the annotation relates + Timestamp indicating starting moment to which the annotation relates. """ startingAt: Time! } @@ -3962,7 +4458,7 @@ Autogenerated return type of CreateAnnotation """ type CreateAnnotationPayload { """ - The created annotation + The created annotation. """ annotation: MetricsDashboardAnnotation @@ -3982,12 +4478,17 @@ Autogenerated input type of CreateBoard """ input CreateBoardInput { """ + The ID of user to be assigned to the board. + """ + assigneeId: UserID + + """ A unique identifier for the client performing the mutation. """ clientMutationId: String """ - The group full path the resource is associated with + The group full path the resource is associated with. """ groupPath: ID @@ -4002,14 +4503,39 @@ input CreateBoardInput { hideClosedList: Boolean """ + The ID of iteration to be assigned to the board. + """ + iterationId: IterationID + + """ + The IDs of labels to be added to the board. + """ + labelIds: [LabelID!] + + """ + Labels of the issue + """ + labels: [String!] + + """ + The ID of milestone to be assigned to the board. + """ + milestoneId: MilestoneID + + """ The board name. """ name: String """ - The project full path the resource is associated with + The project full path the resource is associated with. """ projectPath: ID + + """ + The weight value to be assigned to the board. + """ + weight: Int } """ @@ -4042,17 +4568,17 @@ input CreateBranchInput { clientMutationId: String """ - Name of the branch + Name of the branch. """ name: String! """ - Project full path the branch is associated with + Project full path the branch is associated with. """ projectPath: ID! """ - Branch name or commit SHA to create branch from + Branch name or commit SHA to create branch from. """ ref: String! } @@ -4062,7 +4588,7 @@ Autogenerated return type of CreateBranch """ type CreateBranchPayload { """ - Branch after mutation + Branch after mutation. """ branch: Branch @@ -4087,12 +4613,12 @@ input CreateClusterAgentInput { clientMutationId: String """ - Name of the cluster agent + Name of the cluster agent. """ name: String! """ - Full path of the associated project for this cluster agent + Full path of the associated project for this cluster agent. """ projectPath: ID! } @@ -4107,7 +4633,7 @@ type CreateClusterAgentPayload { clientMutationId: String """ - Cluster agent created after mutation + Cluster agent created after mutation. """ clusterAgent: ClusterAgent @@ -4127,24 +4653,14 @@ input CreateComplianceFrameworkInput { clientMutationId: String """ - Color to represent the compliance framework as a hexadecimal value. e.g. #ABC123. - """ - color: String! - - """ - Description of the compliance framework. - """ - description: String! - - """ - Name of the compliance framework. + Full path of the namespace to add the compliance framework to. """ - name: String! + namespacePath: ID! """ - Full path of the namespace to add the compliance framework to. + Parameters to update the compliance framework with. """ - namespacePath: ID! + params: ComplianceFrameworkInput! } """ @@ -4177,17 +4693,17 @@ input CreateCustomEmojiInput { clientMutationId: String """ - Namespace full path the emoji is associated with + Namespace full path the emoji is associated with. """ groupPath: ID! """ - Name of the emoji + Name of the emoji. """ name: String! """ - Location of the emoji file + Location of the emoji file. """ url: String! } @@ -4202,7 +4718,7 @@ type CreateCustomEmojiPayload { clientMutationId: String """ - The new custom emoji + The new custom emoji. """ customEmoji: CustomEmoji @@ -4222,12 +4738,12 @@ input CreateDevopsAdoptionSegmentInput { clientMutationId: String """ - The array of group IDs to set for the segment + The array of group IDs to set for the segment. """ groupIds: [GroupID!] """ - Name of the segment + Name of the segment. """ name: String! } @@ -4247,7 +4763,7 @@ type CreateDevopsAdoptionSegmentPayload { errors: [String!]! """ - The segment after mutation + The segment after mutation. """ segment: DevopsAdoptionSegment } @@ -4272,7 +4788,7 @@ input CreateDiffNoteInput { confidential: Boolean """ - The global ID of the resource to add a note to + The global ID of the resource to add a note to. """ noteableId: NoteableID! @@ -4297,7 +4813,7 @@ type CreateDiffNotePayload { errors: [String!]! """ - The note after mutation + The note after mutation. """ note: Note } @@ -4317,27 +4833,27 @@ input CreateEpicInput { clientMutationId: String """ - Indicates if the epic is confidential + Indicates if the epic is confidential. """ confidential: Boolean """ - The description of the epic + The description of the epic. """ description: String """ - The end date of the epic + The end date of the epic. """ dueDateFixed: String """ - Indicates end date should be sourced from due_date_fixed field not the issue milestones + Indicates end date should be sourced from due_date_fixed field not the issue milestones. """ dueDateIsFixed: Boolean """ - The group the epic to mutate is in + The group the epic to mutate is in. """ groupPath: ID! @@ -4347,17 +4863,17 @@ input CreateEpicInput { removeLabelIds: [ID!] """ - The start date of the epic + The start date of the epic. """ startDateFixed: String """ - Indicates start date should be sourced from start_date_fixed field not the issue milestones + Indicates start date should be sourced from start_date_fixed field not the issue milestones. """ startDateIsFixed: Boolean """ - The title of the epic + The title of the epic. """ title: String } @@ -4372,7 +4888,7 @@ type CreateEpicPayload { clientMutationId: String """ - The created epic + The created epic. """ epic: Epic @@ -4402,7 +4918,7 @@ input CreateImageDiffNoteInput { confidential: Boolean """ - The global ID of the resource to add a note to + The global ID of the resource to add a note to. """ noteableId: NoteableID! @@ -4427,7 +4943,7 @@ type CreateImageDiffNotePayload { errors: [String!]! """ - The note after mutation + The note after mutation. """ note: Note } @@ -4437,7 +4953,7 @@ Autogenerated input type of CreateIssue """ input CreateIssueInput { """ - The array of user IDs to assign to the issue + The array of user IDs to assign to the issue. """ assigneeIds: [UserID!] @@ -4452,7 +4968,7 @@ input CreateIssueInput { confidential: Boolean """ - Timestamp when the issue was created. Available only for admins and project owners + Timestamp when the issue was created. Available only for admins and project owners. """ createdAt: Time @@ -4462,7 +4978,7 @@ input CreateIssueInput { description: String """ - The ID of a discussion to resolve. Also pass `merge_request_to_resolve_discussions_of` + The ID of a discussion to resolve. Also pass `merge_request_to_resolve_discussions_of`. """ discussionToResolve: String @@ -4472,22 +4988,22 @@ input CreateIssueInput { dueDate: ISO8601Date """ - The ID of an epic to associate the issue with + The ID of an epic to associate the issue with. """ epicId: EpicID """ - The desired health status + The desired health status. """ healthStatus: HealthStatus """ - The IID (internal ID) of a project issue. Only admins and project owners can modify + The IID (internal ID) of a project issue. Only admins and project owners can modify. """ iid: Int """ - The IDs of labels to be added to the issue + The IDs of labels to be added to the issue. """ labelIds: [LabelID!] @@ -4502,17 +5018,17 @@ input CreateIssueInput { locked: Boolean """ - The IID of a merge request for which to resolve discussions + The IID of a merge request for which to resolve discussions. """ mergeRequestToResolveDiscussionsOf: MergeRequestID """ - The ID of the milestone to assign to the issue. On update milestone will be removed if set to null + The ID of the milestone to assign to the issue. On update milestone will be removed if set to null. """ milestoneId: MilestoneID """ - Project full path the issue is associated with + Project full path the issue is associated with. """ projectPath: ID! @@ -4522,7 +5038,7 @@ input CreateIssueInput { title: String! """ - The weight of the issue + The weight of the issue. """ weight: Int } @@ -4542,7 +5058,7 @@ type CreateIssuePayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -4557,32 +5073,32 @@ input CreateIterationInput { clientMutationId: String """ - The description of the iteration + The description of the iteration. """ description: String """ - The end date of the iteration + The end date of the iteration. """ dueDate: String """ - The target group for the iteration + The target group for the iteration. """ groupPath: ID """ - The target project for the iteration + The target project for the iteration. """ projectPath: ID """ - The start date of the iteration + The start date of the iteration. """ startDate: String """ - The title of the iteration + The title of the iteration. """ title: String } @@ -4602,7 +5118,7 @@ type CreateIterationPayload { errors: [String!]! """ - The created iteration + The created iteration. """ iteration: Iteration } @@ -4627,12 +5143,12 @@ input CreateNoteInput { confidential: Boolean """ - The global ID of the discussion this note is in reply to + The global ID of the discussion this note is in reply to. """ discussionId: DiscussionID """ - The global ID of the resource to add a note to + The global ID of the resource to add a note to. """ noteableId: NoteableID! } @@ -4652,7 +5168,7 @@ type CreateNotePayload { errors: [String!]! """ - The note after mutation + The note after mutation. """ note: Note } @@ -4667,17 +5183,17 @@ input CreateRequirementInput { clientMutationId: String """ - Description of the requirement + Description of the requirement. """ description: String """ - Full project path the requirement is associated with + Full project path the requirement is associated with. """ projectPath: ID! """ - Title of the requirement + Title of the requirement. """ title: String } @@ -4697,7 +5213,7 @@ type CreateRequirementPayload { errors: [String!]! """ - Requirement after mutation + Requirement after mutation. """ requirement: Requirement } @@ -4707,7 +5223,7 @@ Autogenerated input type of CreateSnippet """ input CreateSnippetInput { """ - Actions to perform over the snippet repository and blobs + Actions to perform over the snippet repository and blobs. """ blobActions: [SnippetBlobActionInputType!] @@ -4717,27 +5233,27 @@ input CreateSnippetInput { clientMutationId: String """ - Description of the snippet + Description of the snippet. """ description: String """ - The project full path the snippet is associated with + The project full path the snippet is associated with. """ projectPath: ID """ - Title of the snippet + Title of the snippet. """ title: String! """ - The paths to files uploaded in the snippet description + The paths to files uploaded in the snippet description. """ uploadedFiles: [String!] """ - The visibility level of the snippet + The visibility level of the snippet. """ visibilityLevel: VisibilityLevelsEnum! } @@ -4757,12 +5273,12 @@ type CreateSnippetPayload { errors: [String!]! """ - The snippet after mutation + The snippet after mutation. """ snippet: Snippet """ - Indicates whether the operation returns a record detected as spam + Indicates whether the operation returns a record detected as spam. """ spam: Boolean } @@ -4777,7 +5293,7 @@ input CreateTestCaseInput { clientMutationId: String """ - The test case description + The test case description. """ description: String @@ -4787,12 +5303,12 @@ input CreateTestCaseInput { labelIds: [ID!] """ - The project full path to create the test case + The project full path to create the test case. """ projectPath: ID! """ - The test case title + The test case title. """ title: String! } @@ -4812,7 +5328,7 @@ type CreateTestCasePayload { errors: [String!]! """ - The test case created + The test case created. """ testCase: Issue } @@ -5672,6 +6188,96 @@ enum DastSiteValidationStrategyEnum { } """ +Color of the data visualization palette +""" +enum DataVisualizationColorEnum { + """ + Aqua color + """ + AQUA + + """ + Blue color + """ + BLUE + + """ + Green color + """ + GREEN + + """ + Magenta color + """ + MAGENTA + + """ + Orange color + """ + ORANGE +} + +""" +Weight of the data visualization palette +""" +enum DataVisualizationWeightEnum { + """ + 100 weight + """ + WEIGHT_100 + + """ + 200 weight + """ + WEIGHT_200 + + """ + 300 weight + """ + WEIGHT_300 + + """ + 400 weight + """ + WEIGHT_400 + + """ + 50 weight + """ + WEIGHT_50 + + """ + 500 weight + """ + WEIGHT_500 + + """ + 600 weight + """ + WEIGHT_600 + + """ + 700 weight + """ + WEIGHT_700 + + """ + 800 weight + """ + WEIGHT_800 + + """ + 900 weight + """ + WEIGHT_900 + + """ + 950 weight + """ + WEIGHT_950 +} + +""" Date represented in ISO 8601 """ scalar Date @@ -5686,7 +6292,7 @@ input DeleteAnnotationInput { clientMutationId: String """ - Global ID of the annotation to delete + Global ID of the annotation to delete. """ id: MetricsDashboardAnnotationID! } @@ -5716,7 +6322,7 @@ input DeleteDevopsAdoptionSegmentInput { clientMutationId: String """ - ID of the segment + ID of the segment. """ id: AnalyticsDevopsAdoptionSegmentID! } @@ -5905,12 +6511,12 @@ type Design implements CurrentUserTodos & DesignFields & Noteable { before: String """ - The Global ID of the most recent acceptable version + The Global ID of the most recent acceptable version. """ earlierOrEqualToId: DesignManagementVersionID """ - The SHA256 of the most recent acceptable version + The SHA256 of the most recent acceptable version. """ earlierOrEqualToSha: String @@ -6040,12 +6646,12 @@ type DesignCollection { """ design( """ - Find a design by its filename + Find a design by its filename. """ filename: String """ - Find a design by its ID + Find a design by its ID. """ id: DesignManagementDesignID ): Design @@ -6055,7 +6661,7 @@ type DesignCollection { """ designAtVersion( """ - The Global ID of the design at this version + The Global ID of the design at this version. """ id: DesignManagementDesignAtVersionID! ): DesignAtVersion @@ -6081,7 +6687,7 @@ type DesignCollection { before: String """ - Filters designs by their filename + Filters designs by their filename. """ filenames: [String!] @@ -6091,7 +6697,7 @@ type DesignCollection { first: Int """ - Filters designs by their ID + Filters designs by their ID. """ ids: [DesignManagementDesignID!] @@ -6116,12 +6722,12 @@ type DesignCollection { """ version( """ - The Global ID of the version + The Global ID of the version. """ id: DesignManagementVersionID """ - The SHA256 of a specific version + The SHA256 of a specific version. """ sha: String ): DesignVersion @@ -6141,12 +6747,12 @@ type DesignCollection { before: String """ - The Global ID of the most recent acceptable version + The Global ID of the most recent acceptable version. """ earlierOrEqualToId: DesignManagementVersionID """ - The SHA256 of the most recent acceptable version + The SHA256 of the most recent acceptable version. """ earlierOrEqualToSha: String @@ -6275,7 +6881,7 @@ type DesignManagement { """ designAtVersion( """ - The Global ID of the design at this version + The Global ID of the design at this version. """ id: DesignManagementDesignAtVersionID! ): DesignAtVersion @@ -6285,7 +6891,7 @@ type DesignManagement { """ version( """ - The Global ID of the version + The Global ID of the version. """ id: DesignManagementVersionID! ): DesignVersion @@ -6301,17 +6907,17 @@ input DesignManagementDeleteInput { clientMutationId: String """ - The filenames of the designs to delete + The filenames of the designs to delete. """ filenames: [String!]! """ - The IID of the issue to modify designs for + The IID of the issue to modify designs for. """ iid: ID! """ - The project where the issue is to upload designs for + The project where the issue is to upload designs for. """ projectPath: ID! } @@ -6331,7 +6937,7 @@ type DesignManagementDeletePayload { errors: [String!]! """ - The new version in which the designs are deleted + The new version in which the designs are deleted. """ version: DesignVersion } @@ -6356,17 +6962,17 @@ input DesignManagementMoveInput { clientMutationId: String """ - ID of the design to move + ID of the design to move. """ id: DesignManagementDesignID! """ - ID of the immediately following design + ID of the immediately following design. """ next: DesignManagementDesignID """ - ID of the immediately preceding design + ID of the immediately preceding design. """ previous: DesignManagementDesignID } @@ -6381,7 +6987,7 @@ type DesignManagementMovePayload { clientMutationId: String """ - The current state of the collection + The current state of the collection. """ designCollection: DesignCollection @@ -6401,17 +7007,17 @@ input DesignManagementUploadInput { clientMutationId: String """ - The files to upload + The files to upload. """ files: [Upload!]! """ - The IID of the issue to modify designs for + The IID of the issue to modify designs for. """ iid: ID! """ - The project where the issue is to upload designs for + The project where the issue is to upload designs for. """ projectPath: ID! } @@ -6426,7 +7032,7 @@ type DesignManagementUploadPayload { clientMutationId: String """ - The designs that were uploaded by the mutation + The designs that were uploaded by the mutation. """ designs: [Design!]! @@ -6455,17 +7061,17 @@ type DesignVersion { """ designAtVersion( """ - The ID of a specific design + The ID of a specific design. """ designId: DesignManagementDesignID """ - The filename of a specific design + The filename of a specific design. """ filename: String """ - The ID of the DesignAtVersion + The ID of the DesignAtVersion. """ id: DesignManagementDesignAtVersionID ): DesignAtVersion! @@ -6510,7 +7116,7 @@ type DesignVersion { before: String """ - Filters designs by their filename + Filters designs by their filename. """ filenames: [String!] @@ -6520,7 +7126,7 @@ type DesignVersion { first: Int """ - Filters designs by their ID + Filters designs by their ID. """ ids: [DesignManagementDesignID!] @@ -6611,7 +7217,7 @@ input DestroyBoardInput { clientMutationId: String """ - The global ID of the board to destroy + The global ID of the board to destroy. """ id: BoardID! } @@ -6656,7 +7262,7 @@ Autogenerated return type of DestroyBoard """ type DestroyBoardPayload { """ - The board after mutation + The board after mutation. """ board: Board @@ -6681,7 +7287,7 @@ input DestroyComplianceFrameworkInput { clientMutationId: String """ - The global ID of the compliance framework to destroy + The global ID of the compliance framework to destroy. """ id: ComplianceManagementFrameworkID! } @@ -6766,7 +7372,7 @@ type DestroyContainerRepositoryTagsPayload { clientMutationId: String """ - Deleted container repository tags + Deleted container repository tags. """ deletedTagNames: [String!]! @@ -6786,7 +7392,7 @@ input DestroyNoteInput { clientMutationId: String """ - The global ID of the note to destroy + The global ID of the note to destroy. """ id: NoteID! } @@ -6806,7 +7412,7 @@ type DestroyNotePayload { errors: [String!]! """ - The note after mutation + The note after mutation. """ note: Note } @@ -6821,7 +7427,7 @@ input DestroySnippetInput { clientMutationId: String """ - The global ID of the snippet to destroy + The global ID of the snippet to destroy. """ id: SnippetID! } @@ -6841,7 +7447,7 @@ type DestroySnippetPayload { errors: [String!]! """ - The snippet after mutation + The snippet after mutation. """ snippet: Snippet } @@ -7340,12 +7946,12 @@ input DiscussionToggleResolveInput { clientMutationId: String """ - The global ID of the discussion + The global ID of the discussion. """ id: DiscussionID! """ - Will resolve the discussion when true, and unresolve the discussion when false + Will resolve the discussion when true, and unresolve the discussion when false. """ resolve: Boolean! } @@ -7360,7 +7966,7 @@ type DiscussionToggleResolvePayload { clientMutationId: String """ - The discussion after mutation + The discussion after mutation. """ discussion: Discussion @@ -7380,12 +7986,17 @@ input DismissVulnerabilityInput { clientMutationId: String """ - Reason why vulnerability should be dismissed + Comment why vulnerability should be dismissed. """ comment: String """ - ID of the vulnerability to be dismissed + Reason why vulnerability should be dismissed. + """ + dismissalReason: VulnerabilityDismissalReason + + """ + ID of the vulnerability to be dismissed. """ id: VulnerabilityID! } @@ -7405,7 +8016,7 @@ type DismissVulnerabilityPayload { errors: [String!]! """ - The vulnerability after dismissal + The vulnerability after dismissal. """ vulnerability: Vulnerability } @@ -7470,7 +8081,7 @@ type Environment { """ metricsDashboard( """ - Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml' + Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'. """ path: String! ): MetricsDashboard @@ -7541,12 +8152,12 @@ input EnvironmentsCanaryIngressUpdateInput { clientMutationId: String """ - The global ID of the environment to update + The global ID of the environment to update. """ id: EnvironmentID! """ - The weight of the Canary Ingress + The weight of the Canary Ingress. """ weight: Int! } @@ -7585,7 +8196,7 @@ type Epic implements CurrentUserTodos & Noteable { after: String """ - Filter epics by author + Filter epics by author. """ authorUsername: String @@ -7595,6 +8206,11 @@ type Epic implements CurrentUserTodos & Noteable { before: String """ + Filter epics by given confidentiality. + """ + confidential: Boolean + + """ List items overlapping a time frame defined by startDate..endDate (if one date is provided, both must be present) Deprecated in 13.5: Use timeframe.end. """ @@ -7606,27 +8222,27 @@ type Epic implements CurrentUserTodos & Noteable { first: Int """ - IID of the epic, e.g., "1" + IID of the epic, e.g., "1". """ iid: ID """ - Filter epics by IID for autocomplete + Filter epics by IID for autocomplete. """ iidStartsWith: String """ - List of IIDs of epics, e.g., [1, 2] + List of IIDs of epics, e.g., [1, 2]. """ iids: [ID!] """ - Include epics from descendant groups + Include epics from descendant groups. """ includeDescendantGroups: Boolean = true """ - Filter epics by labels + Filter epics by labels. """ labelName: [String!] @@ -7636,17 +8252,17 @@ type Epic implements CurrentUserTodos & Noteable { last: Int """ - Filter epics by milestone title, computed from epic's issues + Filter epics by milestone title, computed from epic's issues. """ milestoneTitle: String """ - Search query for epic title or description + Search query for epic title or description. """ search: String """ - List epics by sort order + List epics by sort order. """ sort: EpicSort @@ -7658,12 +8274,12 @@ type Epic implements CurrentUserTodos & Noteable { startDate: Time """ - Filter epics by state + Filter epics by state. """ state: EpicState """ - List items overlapping the given timeframe + List items overlapping the given timeframe. """ timeframe: Timeframe ): EpicConnection @@ -8019,22 +8635,22 @@ input EpicAddIssueInput { clientMutationId: String """ - The group the epic to mutate belongs to + The group the epic to mutate belongs to. """ groupPath: ID! """ - The IID of the epic to mutate + The IID of the epic to mutate. """ iid: ID! """ - The IID of the issue to be added + The IID of the issue to be added. """ issueIid: String! """ - The full path of the project the issue belongs to + The full path of the project the issue belongs to. """ projectPath: ID! } @@ -8049,12 +8665,12 @@ type EpicAddIssuePayload { clientMutationId: String """ - The epic after mutation + The epic after mutation. """ epic: Epic """ - The epic-issue relation + The epic-issue relation. """ epicIssue: EpicIssue @@ -8069,12 +8685,42 @@ Represents an epic board """ type EpicBoard { """ - Global ID of the board + Global ID of the board. """ id: BoardsEpicBoardID! """ - Name of the board + Epic board lists. + """ + lists( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Find an epic board list by ID. + """ + id: BoardsEpicListID + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): EpicListConnection + + """ + Name of the board. """ name: String } @@ -8274,6 +8920,11 @@ type EpicIssue implements CurrentUserTodos & Noteable { confidential: Boolean! """ + User specific email address for the issue + """ + createNoteEmail: String + + """ Timestamp of when the issue was created """ createdAt: Time! @@ -8670,6 +9321,96 @@ type EpicIssueEdge { } """ +Represents an epic board list +""" +type EpicList { + """ + List epics. + """ + epics( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): EpicConnection + + """ + Global ID of the board list. + """ + id: BoardsEpicListID! + + """ + Label of the list. + """ + label: Label + + """ + Type of the list. + """ + listType: String! + + """ + Position of the list within the board. + """ + position: Int + + """ + Title of the list. + """ + title: String! +} + +""" +The connection type for EpicList. +""" +type EpicListConnection { + """ + A list of edges. + """ + edges: [EpicListEdge] + + """ + A list of nodes. + """ + nodes: [EpicList] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type EpicListEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: EpicList +} + +""" Check permissions for the current user on an epic """ type EpicPermissions { @@ -8724,17 +9465,17 @@ input EpicSetSubscriptionInput { clientMutationId: String """ - The group the epic to mutate belongs to + The group the epic to mutate belongs to. """ groupPath: ID! """ - The IID of the epic to mutate + The IID of the epic to mutate. """ iid: ID! """ - The desired state of the subscription + The desired state of the subscription. """ subscribedState: Boolean! } @@ -8749,7 +9490,7 @@ type EpicSetSubscriptionPayload { clientMutationId: String """ - The epic after mutation + The epic after mutation. """ epic: Epic @@ -8838,7 +9579,7 @@ Autogenerated input type of EpicTreeReorder """ input EpicTreeReorderInput { """ - The ID of the base epic of the tree + The ID of the base epic of the tree. """ baseEpicId: EpicID! @@ -8848,7 +9589,7 @@ input EpicTreeReorderInput { clientMutationId: String """ - Parameters for updating the tree positions + Parameters for updating the tree positions. """ moved: EpicTreeNodeFieldsInputType! } @@ -8889,6 +9630,56 @@ enum EpicWildcardId { } """ +Autogenerated input type of ExportRequirements +""" +input ExportRequirementsInput { + """ + Filter requirements by author username. + """ + authorUsername: [String!] + + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Full project path the requirements are associated with. + """ + projectPath: ID! + + """ + Search query for requirement title. + """ + search: String + + """ + List requirements by sort order. + """ + sort: Sort + + """ + Filter requirements by state. + """ + state: RequirementState +} + +""" +Autogenerated return type of ExportRequirements +""" +type ExportRequirementsPayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! +} + +""" Represents an external issue """ type ExternalIssue { @@ -8974,7 +9765,7 @@ type GeoNode { first: Int """ - Filters registries by their ID + Filters registries by their ID. """ ids: [ID!] @@ -9014,7 +9805,7 @@ type GeoNode { first: Int """ - Filters registries by their ID + Filters registries by their ID. """ ids: [ID!] @@ -9089,7 +9880,7 @@ type GeoNode { first: Int """ - Filters registries by their ID + Filters registries by their ID. """ ids: [ID!] @@ -9124,7 +9915,7 @@ type GeoNode { first: Int """ - Filters registries by their ID + Filters registries by their ID. """ ids: [ID!] @@ -9203,7 +9994,7 @@ type Group { """ board( """ - The board's ID + The board's ID. """ id: BoardID! ): Board @@ -9228,7 +10019,7 @@ type Group { first: Int """ - Find a board by its ID + Find a board by its ID. """ id: BoardID @@ -9263,13 +10054,13 @@ type Group { last: Int """ - First day for which to fetch code coverage activity (maximum time window is set to 90 days) + First day for which to fetch code coverage activity (maximum time window is set to 90 days). """ startDate: Date! ): CodeCoverageActivityConnection """ - Compliance frameworks available to projects in this namespace Available only + Compliance frameworks available to projects in this namespace. Available only when feature flag `ff_custom_compliance_frameworks` is enabled. """ complianceFrameworks( @@ -9289,6 +10080,11 @@ type Group { first: Int """ + Global ID of a specific compliance framework to return. + """ + id: ComplianceManagementFrameworkID + + """ Returns the last _n_ elements from the list. """ last: Int @@ -9319,7 +10115,7 @@ type Group { last: Int """ - Filter the container repositories by their name + Filter the container repositories by their name. """ name: String ): ContainerRepositoryConnection @@ -9379,53 +10175,58 @@ type Group { """ epic( """ - Filter epics by author + Filter epics by author. """ authorUsername: String """ + Filter epics by given confidentiality. + """ + confidential: Boolean + + """ List items overlapping a time frame defined by startDate..endDate (if one date is provided, both must be present) Deprecated in 13.5: Use timeframe.end. """ endDate: Time """ - IID of the epic, e.g., "1" + IID of the epic, e.g., "1". """ iid: ID """ - Filter epics by IID for autocomplete + Filter epics by IID for autocomplete. """ iidStartsWith: String """ - List of IIDs of epics, e.g., [1, 2] + List of IIDs of epics, e.g., [1, 2]. """ iids: [ID!] """ - Include epics from descendant groups + Include epics from descendant groups. """ includeDescendantGroups: Boolean = true """ - Filter epics by labels + Filter epics by labels. """ labelName: [String!] """ - Filter epics by milestone title, computed from epic's issues + Filter epics by milestone title, computed from epic's issues. """ milestoneTitle: String """ - Search query for epic title or description + Search query for epic title or description. """ search: String """ - List epics by sort order + List epics by sort order. """ sort: EpicSort @@ -9437,12 +10238,12 @@ type Group { startDate: Time """ - Filter epics by state + Filter epics by state. """ state: EpicState """ - List items overlapping the given timeframe + List items overlapping the given timeframe. """ timeframe: Timeframe ): Epic @@ -9452,7 +10253,7 @@ type Group { """ epicBoard( """ - Find an epic board by ID + Find an epic board by ID. """ id: BoardsEpicBoardID! ): EpicBoard @@ -9492,7 +10293,7 @@ type Group { after: String """ - Filter epics by author + Filter epics by author. """ authorUsername: String @@ -9502,6 +10303,11 @@ type Group { before: String """ + Filter epics by given confidentiality. + """ + confidential: Boolean + + """ List items overlapping a time frame defined by startDate..endDate (if one date is provided, both must be present) Deprecated in 13.5: Use timeframe.end. """ @@ -9513,27 +10319,27 @@ type Group { first: Int """ - IID of the epic, e.g., "1" + IID of the epic, e.g., "1". """ iid: ID """ - Filter epics by IID for autocomplete + Filter epics by IID for autocomplete. """ iidStartsWith: String """ - List of IIDs of epics, e.g., [1, 2] + List of IIDs of epics, e.g., [1, 2]. """ iids: [ID!] """ - Include epics from descendant groups + Include epics from descendant groups. """ includeDescendantGroups: Boolean = true """ - Filter epics by labels + Filter epics by labels. """ labelName: [String!] @@ -9543,17 +10349,17 @@ type Group { last: Int """ - Filter epics by milestone title, computed from epic's issues + Filter epics by milestone title, computed from epic's issues. """ milestoneTitle: String """ - Search query for epic title or description + Search query for epic title or description. """ search: String """ - List epics by sort order + List epics by sort order. """ sort: EpicSort @@ -9565,12 +10371,12 @@ type Group { startDate: Time """ - Filter epics by state + Filter epics by state. """ state: EpicState """ - List items overlapping the given timeframe + List items overlapping the given timeframe. """ timeframe: Timeframe ): EpicConnection @@ -9615,12 +10421,12 @@ type Group { last: Int """ - Filter members by the given member relations + Filter members by the given member relations. """ relations: [GroupMemberRelation!] = [DIRECT, INHERITED] """ - Search query + Search query. """ search: String ): GroupMemberConnection @@ -9650,22 +10456,22 @@ type Group { after: String """ - ID of a user assigned to the issues, "none" and "any" values are supported + ID of a user assigned to the issues, "none" and "any" values are supported. """ assigneeId: String """ - Username of a user assigned to the issue + Username of a user assigned to the issue. """ assigneeUsername: String """ - Usernames of users assigned to the issue + Usernames of users assigned to the issue. """ assigneeUsernames: [String!] """ - Username of the author of the issue + Username of the author of the issue. """ authorUsername: String @@ -9675,27 +10481,27 @@ type Group { before: String """ - Issues closed after this date + Issues closed after this date. """ closedAfter: Time """ - Issues closed before this date + Issues closed before this date. """ closedBefore: Time """ - Issues created after this date + Issues created after this date. """ createdAfter: Time """ - Issues created before this date + Issues created before this date. """ createdBefore: Time """ - ID of an epic associated with the issues, "none" and "any" values are supported + ID of an epic associated with the issues, "none" and "any" values are supported. """ epicId: String @@ -9705,12 +10511,12 @@ type Group { first: Int """ - IID of the issue. For example, "1" + IID of the issue. For example, "1". """ iid: String """ - List of IIDs of issues. For example, [1, 2] + List of IIDs of issues. For example, [1, 2]. """ iids: [String!] @@ -9720,12 +10526,12 @@ type Group { includeSubgroups: Boolean = false """ - Iterations applied to the issue + Iterations applied to the issue. """ iterationId: [ID] """ - Labels applied to this issue + Labels applied to this issue. """ labelName: [String] @@ -9735,37 +10541,37 @@ type Group { last: Int """ - Milestone applied to this issue + Milestone applied to this issue. """ milestoneTitle: [String] """ - Search query for issue title or description + Search query for issue title or description. """ search: String """ - Sort issues by this criteria + Sort issues by this criteria. """ sort: IssueSort = created_desc """ - Current state of this issue + Current state of this issue. """ state: IssuableState """ - Filter issues by the given issue types + Filter issues by the given issue types. """ types: [IssueType!] """ - Issues updated after this date + Issues updated after this date. """ updatedAfter: Time """ - Issues updated before this date + Issues updated before this date. """ updatedBefore: Time ): IssueConnection @@ -9828,7 +10634,7 @@ type Group { state: IterationState """ - List items overlapping the given timeframe + List items overlapping the given timeframe. """ timeframe: Timeframe @@ -9898,12 +10704,12 @@ type Group { after: String """ - Username of the assignee + Username of the assignee. """ assigneeUsername: String """ - Username of the author + Username of the author. """ authorUsername: String @@ -9918,7 +10724,7 @@ type Group { first: Int """ - Array of IIDs of merge requests, for example `[1, 2]` + Array of IIDs of merge requests, for example `[1, 2]`. """ iids: [String!] @@ -9938,22 +10744,22 @@ type Group { last: Int """ - Merge requests merged after this date + Merge requests merged after this date. """ mergedAfter: Time """ - Merge requests merged before this date + Merge requests merged before this date. """ mergedBefore: Time """ - Title of the milestone + Title of the milestone. """ milestoneTitle: String """ - Sort merge requests by this criteria + Sort merge requests by this criteria. """ sort: MergeRequestSort = created_desc @@ -9988,7 +10794,7 @@ type Group { before: String """ - A date that the milestone contains + A date that the milestone contains. """ containingDate: Time @@ -10004,12 +10810,12 @@ type Group { first: Int """ - Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1" + Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1". """ ids: [ID!] """ - Also return milestones in all subgroups and subprojects + Also return milestones in all subgroups and subprojects. """ includeDescendants: Boolean @@ -10019,7 +10825,7 @@ type Group { last: Int """ - A search string for the title + A search string for the title. """ searchTitle: String @@ -10031,17 +10837,17 @@ type Group { startDate: Time """ - Filter milestones by state + Filter milestones by state. """ state: MilestoneStateEnum """ - List items overlapping the given timeframe + List items overlapping the given timeframe. """ timeframe: Timeframe """ - The title of the milestone + The title of the milestone. """ title: String ): MilestoneConnection @@ -10052,6 +10858,11 @@ type Group { name: String! """ + The package settings for the namespace + """ + packageSettings: PackageSettings + + """ Parent group """ parent: Group @@ -10086,12 +10897,12 @@ type Group { first: Int """ - Returns only the projects which have vulnerabilities + Returns only the projects which have vulnerabilities. """ hasVulnerabilities: Boolean = false """ - Include also subgroup projects + Include also subgroup projects. """ includeSubgroups: Boolean = false @@ -10101,12 +10912,12 @@ type Group { last: Int """ - Search project with most similar names or paths + Search project with most similar names or paths. """ search: String = null """ - Sort projects by this criteria + Sort projects by this criteria. """ sort: NamespaceProjectSort = null ): ProjectConnection! @@ -10171,12 +10982,12 @@ type Group { before: String """ - List time logs within a date range where the logged date is equal to or before endDate + List time logs within a date range where the logged date is equal to or before endDate. """ endDate: Time """ - List time-logs within a time range where the logged time is equal to or before endTime + List time-logs within a time range where the logged time is equal to or before endTime. """ endTime: Time @@ -10191,12 +11002,12 @@ type Group { last: Int """ - List time logs within a date range where the logged date is equal to or after startDate + List time logs within a date range where the logged date is equal to or after startDate. """ startDate: Time """ - List time-logs within a time range where the logged time is equal to or after startTime + List time-logs within a time range where the logged time is equal to or after startTime. """ startTime: Time ): TimelogConnection! @@ -10246,12 +11057,12 @@ type Group { first: Int """ - Returns only the vulnerabilities which have linked issues + Returns only the vulnerabilities which have linked issues. """ hasIssues: Boolean """ - Returns only the vulnerabilities which have been resolved on default branch + Returns only the vulnerabilities which have been resolved on default branch. """ hasResolution: Boolean @@ -10261,32 +11072,32 @@ type Group { last: Int """ - Filter vulnerabilities by project + Filter vulnerabilities by project. """ projectId: [ID!] """ - Filter vulnerabilities by report type + Filter vulnerabilities by report type. """ reportType: [VulnerabilityReportType!] """ - Filter vulnerabilities by scanner + Filter vulnerabilities by VulnerabilityScanner.externalId. """ scanner: [String!] """ - Filter vulnerabilities by severity + Filter vulnerabilities by severity. """ severity: [VulnerabilitySeverity!] """ - List vulnerabilities by sort order + List vulnerabilities by sort order. """ sort: VulnerabilitySort = severity_desc """ - Filter vulnerabilities by state + Filter vulnerabilities by state. """ state: [VulnerabilityState!] ): VulnerabilityConnection @@ -10306,7 +11117,7 @@ type Group { before: String """ - Last day for which to fetch vulnerability history + Last day for which to fetch vulnerability history. """ endDate: ISO8601Date! @@ -10321,7 +11132,7 @@ type Group { last: Int """ - First day for which to fetch vulnerability history + First day for which to fetch vulnerability history. """ startDate: ISO8601Date! ): VulnerabilitiesCountByDayConnection @@ -10342,7 +11153,7 @@ type Group { before: String """ - Last day for which to fetch vulnerability history + Last day for which to fetch vulnerability history. """ endDate: ISO8601Date! @@ -10357,7 +11168,7 @@ type Group { last: Int """ - First day for which to fetch vulnerability history + First day for which to fetch vulnerability history. """ startDate: ISO8601Date! ): VulnerabilitiesCountByDayAndSeverityConnection @deprecated(reason: "Use `vulnerabilitiesCountByDay`. Deprecated in 13.3.") @@ -10367,7 +11178,7 @@ type Group { """ vulnerabilityGrades( """ - Include grades belonging to subgroups + Include grades belonging to subgroups. """ includeSubgroups: Boolean = false ): [VulnerableProjectsByGrade!]! @@ -10402,27 +11213,27 @@ type Group { """ vulnerabilitySeveritiesCount( """ - Filter vulnerabilities by project + Filter vulnerabilities by project. """ projectId: [ID!] """ - Filter vulnerabilities by report type + Filter vulnerabilities by report type. """ reportType: [VulnerabilityReportType!] """ - Filter vulnerabilities by scanner + Filter vulnerabilities by scanner. """ scanner: [String!] """ - Filter vulnerabilities by severity + Filter vulnerabilities by severity. """ severity: [VulnerabilitySeverity!] """ - Filter vulnerabilities by state + Filter vulnerabilities by state. """ state: [VulnerabilityState!] ): VulnerabilitySeveritiesCount @@ -10591,7 +11402,7 @@ Autogenerated input type of HttpIntegrationCreate """ input HttpIntegrationCreateInput { """ - Whether the integration is receiving alerts + Whether the integration is receiving alerts. """ active: Boolean! @@ -10601,12 +11412,22 @@ input HttpIntegrationCreateInput { clientMutationId: String """ - The name of the integration + The name of the integration. """ name: String! """ - The project to create the integration in + The custom mapping of GitLab alert attributes to fields from the payload_example. + """ + payloadAttributeMappings: [AlertManagementPayloadAlertFieldInput!] + + """ + The example of an alert payload. + """ + payloadExample: JsonString + + """ + The project to create the integration in. """ projectPath: ID! } @@ -10626,7 +11447,7 @@ type HttpIntegrationCreatePayload { errors: [String!]! """ - The HTTP integration + The HTTP integration. """ integration: AlertManagementHttpIntegration } @@ -10641,7 +11462,7 @@ input HttpIntegrationDestroyInput { clientMutationId: String """ - The ID of the integration to remove + The ID of the integration to remove. """ id: AlertManagementHttpIntegrationID! } @@ -10661,7 +11482,7 @@ type HttpIntegrationDestroyPayload { errors: [String!]! """ - The HTTP integration + The HTTP integration. """ integration: AlertManagementHttpIntegration } @@ -10676,7 +11497,7 @@ input HttpIntegrationResetTokenInput { clientMutationId: String """ - The ID of the integration to mutate + The ID of the integration to mutate. """ id: AlertManagementHttpIntegrationID! } @@ -10696,7 +11517,7 @@ type HttpIntegrationResetTokenPayload { errors: [String!]! """ - The HTTP integration + The HTTP integration. """ integration: AlertManagementHttpIntegration } @@ -10706,7 +11527,7 @@ Autogenerated input type of HttpIntegrationUpdate """ input HttpIntegrationUpdateInput { """ - Whether the integration is receiving alerts + Whether the integration is receiving alerts. """ active: Boolean @@ -10716,12 +11537,12 @@ input HttpIntegrationUpdateInput { clientMutationId: String """ - The ID of the integration to mutate + The ID of the integration to mutate. """ id: AlertManagementHttpIntegrationID! """ - The name of the integration + The name of the integration. """ name: String } @@ -10741,7 +11562,7 @@ type HttpIntegrationUpdatePayload { errors: [String!]! """ - The HTTP integration + The HTTP integration. """ integration: AlertManagementHttpIntegration } @@ -10752,6 +11573,106 @@ An ISO 8601-encoded date scalar ISO8601Date """ +Identifier of IncidentManagement::OncallParticipant +""" +scalar IncidentManagementOncallParticipantID + +""" +Describes an incident management on-call rotation +""" +type IncidentManagementOncallRotation { + """ + ID of the on-call rotation. + """ + id: IncidentManagementOncallRotationID! + + """ + Length of the on-call schedule, in the units specified by lengthUnit. + """ + length: Int + + """ + Unit of the on-call rotation length. + """ + lengthUnit: OncallRotationUnitEnum + + """ + Name of the on-call rotation. + """ + name: String! + + """ + Participants of the on-call rotation. + """ + participants( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): OncallParticipantTypeConnection + + """ + Start date of the on-call rotation. + """ + startsAt: Time +} + +""" +The connection type for IncidentManagementOncallRotation. +""" +type IncidentManagementOncallRotationConnection { + """ + A list of edges. + """ + edges: [IncidentManagementOncallRotationEdge] + + """ + A list of nodes. + """ + nodes: [IncidentManagementOncallRotation] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type IncidentManagementOncallRotationEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: IncidentManagementOncallRotation +} + +""" +Identifier of IncidentManagement::OncallRotation +""" +scalar IncidentManagementOncallRotationID + +""" Describes an incident management on-call schedule """ type IncidentManagementOncallSchedule { @@ -10771,6 +11692,31 @@ type IncidentManagementOncallSchedule { name: String! """ + On-call rotations for the on-call schedule + """ + rotations( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): IncidentManagementOncallRotationConnection! + + """ Time zone of the on-call schedule """ timezone: String! @@ -10872,27 +11818,27 @@ type InstanceSecurityDashboard { """ vulnerabilitySeveritiesCount( """ - Filter vulnerabilities by project + Filter vulnerabilities by project. """ projectId: [ID!] """ - Filter vulnerabilities by report type + Filter vulnerabilities by report type. """ reportType: [VulnerabilityReportType!] """ - Filter vulnerabilities by scanner + Filter vulnerabilities by scanner. """ scanner: [String!] """ - Filter vulnerabilities by severity + Filter vulnerabilities by severity. """ severity: [VulnerabilitySeverity!] """ - Filter vulnerabilities by state + Filter vulnerabilities by state. """ state: [VulnerabilityState!] ): VulnerabilitySeveritiesCount @@ -11050,6 +11996,11 @@ type Issue implements CurrentUserTodos & Noteable { confidential: Boolean! """ + User specific email address for the issue + """ + createNoteEmail: String + + """ Timestamp of when the issue was created """ createdAt: Time! @@ -11450,17 +12401,17 @@ input IssueMoveInput { clientMutationId: String """ - The IID of the issue to mutate + The IID of the issue to mutate. """ iid: String! """ - The project the issue to mutate is in + The project the issue to mutate is in. """ projectPath: ID! """ - The project to move the issue to + The project to move the issue to. """ targetProjectPath: ID! } @@ -11470,7 +12421,7 @@ Autogenerated input type of IssueMoveList """ input IssueMoveListInput { """ - Global ID of the board that the issue is in + Global ID of the board that the issue is in. """ boardId: ID! @@ -11480,37 +12431,37 @@ input IssueMoveListInput { clientMutationId: String """ - The ID of the parent epic. NULL when removing the association + The ID of the parent epic. NULL when removing the association. """ epicId: EpicID """ - ID of the board list that the issue will be moved from + ID of the board list that the issue will be moved from. """ fromListId: ID """ - IID of the issue to mutate + IID of the issue to mutate. """ iid: String! """ - ID of issue that should be placed after the current issue + ID of issue that should be placed after the current issue. """ moveAfterId: ID """ - ID of issue that should be placed before the current issue + ID of issue that should be placed before the current issue. """ moveBeforeId: ID """ - Project the issue to mutate is in + Project the issue to mutate is in. """ projectPath: ID! """ - ID of the board list that the issue will be moved to + ID of the board list that the issue will be moved to. """ toListId: ID } @@ -11530,7 +12481,7 @@ type IssueMoveListPayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -11550,7 +12501,7 @@ type IssueMovePayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -11615,7 +12566,7 @@ input IssueSetAssigneesInput { clientMutationId: String """ - The IID of the issue to mutate + The IID of the issue to mutate. """ iid: String! @@ -11625,7 +12576,7 @@ input IssueSetAssigneesInput { operationMode: MutationOperationMode """ - The project the issue to mutate is in + The project the issue to mutate is in. """ projectPath: ID! } @@ -11645,7 +12596,7 @@ type IssueSetAssigneesPayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -11665,12 +12616,12 @@ input IssueSetConfidentialInput { confidential: Boolean! """ - The IID of the issue to mutate + The IID of the issue to mutate. """ iid: String! """ - The project the issue to mutate is in + The project the issue to mutate is in. """ projectPath: ID! } @@ -11690,7 +12641,7 @@ type IssueSetConfidentialPayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -11705,17 +12656,17 @@ input IssueSetDueDateInput { clientMutationId: String """ - The desired due date for the issue + The desired due date for the issue. """ dueDate: Time! """ - The IID of the issue to mutate + The IID of the issue to mutate. """ iid: String! """ - The project the issue to mutate is in + The project the issue to mutate is in. """ projectPath: ID! } @@ -11735,7 +12686,7 @@ type IssueSetDueDatePayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -11755,12 +12706,12 @@ input IssueSetEpicInput { epicId: EpicID """ - The IID of the issue to mutate + The IID of the issue to mutate. """ iid: String! """ - The project the issue to mutate is in + The project the issue to mutate is in. """ projectPath: ID! } @@ -11780,7 +12731,7 @@ type IssueSetEpicPayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -11795,7 +12746,7 @@ input IssueSetIterationInput { clientMutationId: String """ - The IID of the issue to mutate + The IID of the issue to mutate. """ iid: String! @@ -11805,7 +12756,7 @@ input IssueSetIterationInput { iterationId: IterationID """ - The project the issue to mutate is in + The project the issue to mutate is in. """ projectPath: ID! } @@ -11825,7 +12776,7 @@ type IssueSetIterationPayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -11840,17 +12791,17 @@ input IssueSetLockedInput { clientMutationId: String """ - The IID of the issue to mutate + The IID of the issue to mutate. """ iid: String! """ - Whether or not to lock discussion on the issue + Whether or not to lock discussion on the issue. """ locked: Boolean! """ - The project the issue to mutate is in + The project the issue to mutate is in. """ projectPath: ID! } @@ -11870,7 +12821,7 @@ type IssueSetLockedPayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -11885,12 +12836,12 @@ input IssueSetSeverityInput { clientMutationId: String """ - The IID of the issue to mutate + The IID of the issue to mutate. """ iid: String! """ - The project the issue to mutate is in + The project the issue to mutate is in. """ projectPath: ID! @@ -11915,7 +12866,7 @@ type IssueSetSeverityPayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -11930,17 +12881,17 @@ input IssueSetSubscriptionInput { clientMutationId: String """ - The IID of the issue to mutate + The IID of the issue to mutate. """ iid: String! """ - The project the issue to mutate is in + The project the issue to mutate is in. """ projectPath: ID! """ - The desired state of the subscription + The desired state of the subscription. """ subscribedState: Boolean! } @@ -11960,7 +12911,7 @@ type IssueSetSubscriptionPayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -11975,17 +12926,17 @@ input IssueSetWeightInput { clientMutationId: String """ - The IID of the issue to mutate + The IID of the issue to mutate. """ iid: String! """ - The project the issue to mutate is in + The project the issue to mutate is in. """ projectPath: ID! """ - The desired weight for the issue + The desired weight for the issue. """ weight: Int! } @@ -12005,7 +12956,7 @@ type IssueSetWeightPayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -12443,22 +13394,22 @@ input JiraImportStartInput { clientMutationId: String """ - Project key of the importer Jira project + Project key of the importer Jira project. """ jiraProjectKey: String! """ - Project name of the importer Jira project + Project name of the importer Jira project. """ jiraProjectName: String """ - The project to import the Jira project into + The project to import the Jira project into. """ projectPath: ID! """ - The mapping of Jira to GitLab users + The mapping of Jira to GitLab users. """ usersMapping: [JiraUsersMappingInputType!] } @@ -12478,7 +13429,7 @@ type JiraImportStartPayload { errors: [String!]! """ - The Jira import data after mutation + The Jira import data after mutation. """ jiraImport: JiraImport } @@ -12493,12 +13444,12 @@ input JiraImportUsersInput { clientMutationId: String """ - The project to import the Jira users into + The project to import the Jira users into. """ projectPath: ID! """ - The index of the record the import should started at, default 0 (50 records returned) + The index of the record the import should started at, default 0 (50 records returned). """ startAt: Int } @@ -12606,7 +13557,7 @@ type JiraService implements Service { last: Int """ - Project name or key + Project name or key. """ name: String ): JiraProjectConnection @@ -12691,6 +13642,11 @@ enum JobArtifactFileType { TRACE } +""" +JSON object as raw string +""" +scalar JsonString + type Label { """ Background color of the label @@ -12760,27 +13716,27 @@ input LabelCreateInput { """ The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the CSS color names in - https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords + https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords. """ color: String = "#428BCA" """ - Description of the label + Description of the label. """ description: String """ - The group full path the resource is associated with + The group full path the resource is associated with. """ groupPath: ID """ - The project full path the resource is associated with + The project full path the resource is associated with. """ projectPath: ID """ - Title of the label + Title of the label. """ title: String! } @@ -12800,7 +13756,7 @@ type LabelCreatePayload { errors: [String!]! """ - The label after mutation + The label after mutation. """ label: Label } @@ -12849,7 +13805,7 @@ input MarkAsSpamSnippetInput { clientMutationId: String """ - The global ID of the snippet to update + The global ID of the snippet to update. """ id: SnippetID! } @@ -12869,7 +13825,7 @@ type MarkAsSpamSnippetPayload { errors: [String!]! """ - The snippet after mutation + The snippet after mutation. """ snippet: Snippet } @@ -13083,6 +14039,11 @@ type MergeRequest implements CurrentUserTodos & Noteable { autoMergeEnabled: Boolean! """ + Selected auto merge strategy + """ + autoMergeStrategy: String + + """ Array of available auto merge strategies """ availableAutoMergeStrategies: [String!] @@ -13168,6 +14129,11 @@ type MergeRequest implements CurrentUserTodos & Noteable { defaultMergeCommitMessageWithDescription: String """ + Default squash commit message of the merge request + """ + defaultSquashCommitMessage: String + + """ Description of the merge request (Markdown rendered as HTML for caching) """ description: String @@ -13317,6 +14283,11 @@ type MergeRequest implements CurrentUserTodos & Noteable { mergeTrainsCount: Int """ + User who merged this merge request + """ + mergeUser: User + + """ Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS) """ mergeWhenPipelineSucceeds: Boolean @@ -13367,7 +14338,7 @@ type MergeRequest implements CurrentUserTodos & Noteable { ): NoteConnection! """ - Participants in the merge request + Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes. """ participants( """ @@ -13417,17 +14388,17 @@ type MergeRequest implements CurrentUserTodos & Noteable { last: Int """ - Filter pipelines by the ref they are run for + Filter pipelines by the ref they are run for. """ ref: String """ - Filter pipelines by the sha of the commit they are run for + Filter pipelines by the sha of the commit they are run for. """ sha: String """ - Filter pipelines by their status + Filter pipelines by their status. """ status: PipelineStatusEnum ): PipelineConnection @@ -13463,6 +14434,31 @@ type MergeRequest implements CurrentUserTodos & Noteable { ): String! """ + Users from whom a review has been requested. + """ + reviewers( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): UserConnection + + """ Indicates if the merge request is created by @GitLab-Security-Bot. """ securityAutoFix: Boolean @@ -13505,6 +14501,11 @@ type MergeRequest implements CurrentUserTodos & Noteable { """ Indicates if squash on merge is enabled """ + squash: Boolean! + + """ + Indicates if squash on merge is enabled + """ squashOnMerge: Boolean! """ @@ -13648,7 +14649,7 @@ input MergeRequestCreateInput { labels: [String!] """ - Project full path the merge request is associated with + Project full path the merge request is associated with. """ projectPath: ID! @@ -13683,7 +14684,7 @@ type MergeRequestCreatePayload { errors: [String!]! """ - The merge request after mutation + The merge request after mutation. """ mergeRequest: MergeRequest } @@ -13853,7 +14854,7 @@ input MergeRequestSetAssigneesInput { clientMutationId: String """ - The IID of the merge request to mutate + The IID of the merge request to mutate. """ iid: String! @@ -13863,7 +14864,7 @@ input MergeRequestSetAssigneesInput { operationMode: MutationOperationMode """ - The project the merge request to mutate is in + The project the merge request to mutate is in. """ projectPath: ID! } @@ -13883,7 +14884,7 @@ type MergeRequestSetAssigneesPayload { errors: [String!]! """ - The merge request after mutation + The merge request after mutation. """ mergeRequest: MergeRequest } @@ -13898,7 +14899,7 @@ input MergeRequestSetLabelsInput { clientMutationId: String """ - The IID of the merge request to mutate + The IID of the merge request to mutate. """ iid: String! @@ -13913,7 +14914,7 @@ input MergeRequestSetLabelsInput { operationMode: MutationOperationMode """ - The project the merge request to mutate is in + The project the merge request to mutate is in. """ projectPath: ID! } @@ -13933,7 +14934,7 @@ type MergeRequestSetLabelsPayload { errors: [String!]! """ - The merge request after mutation + The merge request after mutation. """ mergeRequest: MergeRequest } @@ -13948,7 +14949,7 @@ input MergeRequestSetLockedInput { clientMutationId: String """ - The IID of the merge request to mutate + The IID of the merge request to mutate. """ iid: String! @@ -13958,7 +14959,7 @@ input MergeRequestSetLockedInput { locked: Boolean! """ - The project the merge request to mutate is in + The project the merge request to mutate is in. """ projectPath: ID! } @@ -13978,7 +14979,7 @@ type MergeRequestSetLockedPayload { errors: [String!]! """ - The merge request after mutation + The merge request after mutation. """ mergeRequest: MergeRequest } @@ -13993,7 +14994,7 @@ input MergeRequestSetMilestoneInput { clientMutationId: String """ - The IID of the merge request to mutate + The IID of the merge request to mutate. """ iid: String! @@ -14003,7 +15004,7 @@ input MergeRequestSetMilestoneInput { milestoneId: MilestoneID """ - The project the merge request to mutate is in + The project the merge request to mutate is in. """ projectPath: ID! } @@ -14023,7 +15024,7 @@ type MergeRequestSetMilestonePayload { errors: [String!]! """ - The merge request after mutation + The merge request after mutation. """ mergeRequest: MergeRequest } @@ -14038,17 +15039,17 @@ input MergeRequestSetSubscriptionInput { clientMutationId: String """ - The IID of the merge request to mutate + The IID of the merge request to mutate. """ iid: String! """ - The project the merge request to mutate is in + The project the merge request to mutate is in. """ projectPath: ID! """ - The desired state of the subscription + The desired state of the subscription. """ subscribedState: Boolean! } @@ -14068,7 +15069,7 @@ type MergeRequestSetSubscriptionPayload { errors: [String!]! """ - The merge request after mutation + The merge request after mutation. """ mergeRequest: MergeRequest } @@ -14083,12 +15084,12 @@ input MergeRequestSetWipInput { clientMutationId: String """ - The IID of the merge request to mutate + The IID of the merge request to mutate. """ iid: String! """ - The project the merge request to mutate is in + The project the merge request to mutate is in. """ projectPath: ID! @@ -14113,7 +15114,7 @@ type MergeRequestSetWipPayload { errors: [String!]! """ - The merge request after mutation + The merge request after mutation. """ mergeRequest: MergeRequest } @@ -14229,12 +15230,12 @@ input MergeRequestUpdateInput { description: String """ - The IID of the merge request to mutate + The IID of the merge request to mutate. """ iid: String! """ - The project the merge request to mutate is in + The project the merge request to mutate is in. """ projectPath: ID! @@ -14264,7 +15265,7 @@ type MergeRequestUpdatePayload { errors: [String!]! """ - The merge request after mutation + The merge request after mutation. """ mergeRequest: MergeRequest } @@ -14332,7 +15333,7 @@ type MetricsDashboard { first: Int """ - Timestamp marking date and time from which annotations need to be fetched + Timestamp marking date and time from which annotations need to be fetched. """ from: Time! @@ -14342,7 +15343,7 @@ type MetricsDashboard { last: Int """ - Timestamp marking date and time to which annotations need to be fetched + Timestamp marking date and time to which annotations need to be fetched. """ to: Time ): MetricsDashboardAnnotationConnection @@ -14586,6 +15587,7 @@ type Mutation { awardEmojiToggle(input: AwardEmojiToggleInput!): AwardEmojiTogglePayload boardListCreate(input: BoardListCreateInput!): BoardListCreatePayload boardListUpdateLimitMetrics(input: BoardListUpdateLimitMetricsInput!): BoardListUpdateLimitMetricsPayload + ciCdSettingsUpdate(input: CiCdSettingsUpdateInput!): CiCdSettingsUpdatePayload clusterAgentDelete(input: ClusterAgentDeleteInput!): ClusterAgentDeletePayload clusterAgentTokenCreate(input: ClusterAgentTokenCreateInput!): ClusterAgentTokenCreatePayload clusterAgentTokenDelete(input: ClusterAgentTokenDeleteInput!): ClusterAgentTokenDeletePayload @@ -14643,6 +15645,7 @@ type Mutation { epicAddIssue(input: EpicAddIssueInput!): EpicAddIssuePayload epicSetSubscription(input: EpicSetSubscriptionInput!): EpicSetSubscriptionPayload epicTreeReorder(input: EpicTreeReorderInput!): EpicTreeReorderPayload + exportRequirements(input: ExportRequirementsInput!): ExportRequirementsPayload httpIntegrationCreate(input: HttpIntegrationCreateInput!): HttpIntegrationCreatePayload httpIntegrationDestroy(input: HttpIntegrationDestroyInput!): HttpIntegrationDestroyPayload httpIntegrationResetToken(input: HttpIntegrationResetTokenInput!): HttpIntegrationResetTokenPayload @@ -14675,6 +15678,7 @@ type Mutation { """ mergeRequestUpdate(input: MergeRequestUpdateInput!): MergeRequestUpdatePayload namespaceIncreaseStorageTemporarily(input: NamespaceIncreaseStorageTemporarilyInput!): NamespaceIncreaseStorageTemporarilyPayload + oncallRotationCreate(input: OncallRotationCreateInput!): OncallRotationCreatePayload oncallScheduleCreate(input: OncallScheduleCreateInput!): OncallScheduleCreatePayload oncallScheduleDestroy(input: OncallScheduleDestroyInput!): OncallScheduleDestroyPayload oncallScheduleUpdate(input: OncallScheduleUpdateInput!): OncallScheduleUpdatePayload @@ -14723,6 +15727,7 @@ type Mutation { updateImageDiffNote(input: UpdateImageDiffNoteInput!): UpdateImageDiffNotePayload updateIssue(input: UpdateIssueInput!): UpdateIssuePayload updateIteration(input: UpdateIterationInput!): UpdateIterationPayload + updateNamespacePackageSettings(input: UpdateNamespacePackageSettingsInput!): UpdateNamespacePackageSettingsPayload """ Updates a Note. If the body of the Note contains only quick actions, the Note @@ -14771,7 +15776,7 @@ type Namespace { additionalPurchasedStorageSize: Float """ - Compliance frameworks available to projects in this namespace Available only + Compliance frameworks available to projects in this namespace. Available only when feature flag `ff_custom_compliance_frameworks` is enabled. """ complianceFrameworks( @@ -14791,6 +15796,11 @@ type Namespace { first: Int """ + Global ID of a specific compliance framework to return. + """ + id: ComplianceManagementFrameworkID + + """ Returns the last _n_ elements from the list. """ last: Int @@ -14842,6 +15852,11 @@ type Namespace { name: String! """ + The package settings for the namespace + """ + packageSettings: PackageSettings + + """ Path of the namespace """ path: String! @@ -14866,12 +15881,12 @@ type Namespace { first: Int """ - Returns only the projects which have vulnerabilities + Returns only the projects which have vulnerabilities. """ hasVulnerabilities: Boolean = false """ - Include also subgroup projects + Include also subgroup projects. """ includeSubgroups: Boolean = false @@ -14881,12 +15896,12 @@ type Namespace { last: Int """ - Search project with most similar names or paths + Search project with most similar names or paths. """ search: String = null """ - Sort projects by this criteria + Sort projects by this criteria. """ sort: NamespaceProjectSort = null ): ProjectConnection! @@ -14982,7 +15997,7 @@ input NamespaceIncreaseStorageTemporarilyInput { clientMutationId: String """ - The global ID of the namespace to mutate + The global ID of the namespace to mutate. """ id: NamespaceID! } @@ -15002,7 +16017,7 @@ type NamespaceIncreaseStorageTemporarilyPayload { errors: [String!]! """ - The namespace after mutation + The namespace after mutation. """ namespace: Namespace } @@ -15151,6 +16166,11 @@ type Note implements ResolvableInterface { updatedAt: Time! """ + URL to view this Note in the Web UI + """ + url: String + + """ Permissions for the current user on the resource """ userPermissions: NotePermissions! @@ -15286,6 +16306,176 @@ Identifier of Noteable scalar NoteableID """ +The rotation participant and color palette +""" +type OncallParticipantType { + """ + The color palette to assign to the on-call user. For example "blue". + """ + colorPalette: String + + """ + The color weight to assign to for the on-call user, for example "500". Max 4 chars. For easy identification of the user. + """ + colorWeight: String + + """ + ID of the on-call participant. + """ + id: IncidentManagementOncallParticipantID! + + """ + The user who is participating. + """ + user: User! +} + +""" +The connection type for OncallParticipantType. +""" +type OncallParticipantTypeConnection { + """ + A list of edges. + """ + edges: [OncallParticipantTypeEdge] + + """ + A list of nodes. + """ + nodes: [OncallParticipantType] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type OncallParticipantTypeEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: OncallParticipantType +} + +""" +Autogenerated input type of OncallRotationCreate +""" +input OncallRotationCreateInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + The name of the on-call rotation. + """ + name: String! + + """ + The usernames of users participating in the on-call rotation. + """ + participants: [OncallUserInputType!]! + + """ + The project to create the on-call schedule in. + """ + projectPath: ID! + + """ + The rotation length of the on-call rotation. + """ + rotationLength: OncallRotationLengthInputType! + + """ + The IID of the on-call schedule to create the on-call rotation in. + """ + scheduleIid: String! + + """ + The start date and time of the on-call rotation, in the timezone of the on-call schedule. + """ + startsAt: OncallRotationDateInputType! +} + +""" +Autogenerated return type of OncallRotationCreate +""" +type OncallRotationCreatePayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + The on-call rotation. + """ + oncallRotation: IncidentManagementOncallRotation +} + +""" +Date input type for on-call rotation +""" +input OncallRotationDateInputType { + """ + The date component of the date in YYYY-MM-DD format. + """ + date: String! + + """ + The time component of the date in 24hr HH:MM format. + """ + time: String! +} + +""" +The rotation length of the on-call rotation +""" +input OncallRotationLengthInputType { + """ + The rotation length of the on-call rotation. + """ + length: Int! + + """ + The unit of the rotation length of the on-call rotation. + """ + unit: OncallRotationUnitEnum! +} + +""" +Rotation length unit of an on-call rotation +""" +enum OncallRotationUnitEnum { + """ + Days + """ + DAYS + + """ + Hours + """ + HOURS + + """ + Weeks + """ + WEEKS +} + +""" Autogenerated input type of OncallScheduleCreate """ input OncallScheduleCreateInput { @@ -15295,22 +16485,22 @@ input OncallScheduleCreateInput { clientMutationId: String """ - The description of the on-call schedule + The description of the on-call schedule. """ description: String """ - The name of the on-call schedule + The name of the on-call schedule. """ name: String! """ - The project to create the on-call schedule in + The project to create the on-call schedule in. """ projectPath: ID! """ - The timezone of the on-call schedule + The timezone of the on-call schedule. """ timezone: String! } @@ -15330,7 +16520,7 @@ type OncallScheduleCreatePayload { errors: [String!]! """ - The on-call schedule + The on-call schedule. """ oncallSchedule: IncidentManagementOncallSchedule } @@ -15345,12 +16535,12 @@ input OncallScheduleDestroyInput { clientMutationId: String """ - The on-call schedule internal ID to remove + The on-call schedule internal ID to remove. """ iid: String! """ - The project to remove the on-call schedule from + The project to remove the on-call schedule from. """ projectPath: ID! } @@ -15370,7 +16560,7 @@ type OncallScheduleDestroyPayload { errors: [String!]! """ - The on-call schedule + The on-call schedule. """ oncallSchedule: IncidentManagementOncallSchedule } @@ -15385,27 +16575,27 @@ input OncallScheduleUpdateInput { clientMutationId: String """ - The description of the on-call schedule + The description of the on-call schedule. """ description: String """ - The on-call schedule internal ID to update + The on-call schedule internal ID to update. """ iid: String! """ - The name of the on-call schedule + The name of the on-call schedule. """ name: String """ - The project to update the on-call schedule in + The project to update the on-call schedule in. """ projectPath: ID! """ - The timezone of the on-call schedule + The timezone of the on-call schedule. """ timezone: String } @@ -15425,44 +16615,304 @@ type OncallScheduleUpdatePayload { errors: [String!]! """ - The on-call schedule + The on-call schedule. """ oncallSchedule: IncidentManagementOncallSchedule } """ -Represents a package +The rotation user and color palette +""" +input OncallUserInputType { + """ + A value of DataVisualizationColorEnum. The color from the palette to assign to the on-call user. + """ + colorPalette: DataVisualizationColorEnum + + """ + A value of DataVisualizationWeightEnum. The color weight to assign to for the on-call user. + """ + colorWeight: DataVisualizationWeightEnum + + """ + The username of the user to participate in the on-call rotation, such as `user_one`. + """ + username: String! +} + +""" +Represents a package in the Package Registry """ type Package { """ - The created date + The created date. + """ + createdAt: Time! + + """ + The ID of the package. + """ + id: ID! + + """ + The name of the package. + """ + name: String! + + """ + The type of the package. + """ + packageType: PackageTypeEnum! + + """ + Pipelines that built the package. + """ + pipelines( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): PipelineConnection + + """ + Project where the package is stored. + """ + project: Project! + + """ + The package tags. + """ + tags( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): PackageTagConnection + + """ + The updated date. + """ + updatedAt: Time! + + """ + The version of the package. + """ + version: String + + """ + The other versions of the package. + """ + versions( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): PackageConnection +} + +""" +Details of a Composer package +""" +type PackageComposerDetails { + """ + The Composer metadatum. + """ + composerMetadatum: PackageComposerMetadatumType! + + """ + The created date. """ createdAt: Time! """ - The ID of the package + The ID of the package. """ id: ID! """ - The name of the package + The name of the package. """ name: String! """ - The type of the package + The type of the package. """ packageType: PackageTypeEnum! """ - The update date + Pipelines that built the package. + """ + pipelines( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): PipelineConnection + + """ + Project where the package is stored. + """ + project: Project! + + """ + The package tags. + """ + tags( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): PackageTagConnection + + """ + The updated date. """ updatedAt: Time! """ - The version of the package + The version of the package. """ version: String + + """ + The other versions of the package. + """ + versions( + """ + Returns the elements in the list that come after the specified cursor. + """ + after: String + + """ + Returns the elements in the list that come before the specified cursor. + """ + before: String + + """ + Returns the first _n_ elements from the list. + """ + first: Int + + """ + Returns the last _n_ elements from the list. + """ + last: Int + ): PackageConnection +} + +""" +Represents a composer JSON file +""" +type PackageComposerJsonType { + """ + The license set in the Composer JSON file. + """ + license: String + + """ + The name set in the Composer JSON file. + """ + name: String + + """ + The type set in the Composer JSON file. + """ + type: String + + """ + The version set in the Composer JSON file. + """ + version: String +} + +""" +Composer metadatum +""" +type PackageComposerMetadatumType { + """ + Data of the Composer JSON file. + """ + composerJson: PackageComposerJsonType! + + """ + Target SHA of the package. + """ + targetSha: String! } """ @@ -15580,6 +17030,82 @@ type PackageFileRegistryEdge { node: PackageFileRegistry } +""" +Namespace-level Package Registry settings +""" +type PackageSettings { + """ + When maven_duplicates_allowed is false, you can publish duplicate packages + with names that match this regex. Otherwise, this setting has no effect. + """ + mavenDuplicateExceptionRegex: UntrustedRegexp + + """ + Indicates whether duplicate Maven packages are allowed for this namespace. + """ + mavenDuplicatesAllowed: Boolean! +} + +""" +Represents a package tag +""" +type PackageTag { + """ + The created date. + """ + createdAt: Time! + + """ + The ID of the tag. + """ + id: ID! + + """ + The name of the tag. + """ + name: String! + + """ + The updated date. + """ + updatedAt: Time! +} + +""" +The connection type for PackageTag. +""" +type PackageTagConnection { + """ + A list of edges. + """ + edges: [PackageTagEdge] + + """ + A list of nodes. + """ + nodes: [PackageTag] + + """ + Information to aid in pagination. + """ + pageInfo: PageInfo! +} + +""" +An edge in a connection. +""" +type PackageTagEdge { + """ + A cursor for use in pagination. + """ + cursor: String! + + """ + The item at the end of the edge. + """ + node: PackageTag +} + enum PackageTypeEnum { """ Packages from the Composer package manager @@ -15628,6 +17154,11 @@ enum PackageTypeEnum { } """ +Identifier of Packages::Package +""" +scalar PackagesPackageID + +""" Information about pagination in a connection. """ type PageInfo { @@ -15765,7 +17296,7 @@ type Pipeline { last: Int """ - Filter jobs by the type of security report they produce + Filter jobs by the type of security report they produce. """ securityReportTypes: [SecurityReportTypeEnum!] ): CiJobConnection @@ -15924,7 +17455,7 @@ input PipelineCancelInput { clientMutationId: String """ - The ID of the pipeline to mutate + The ID of the pipeline to mutate. """ id: CiPipelineID! } @@ -15990,7 +17521,7 @@ input PipelineDestroyInput { clientMutationId: String """ - The ID of the pipeline to mutate + The ID of the pipeline to mutate. """ id: CiPipelineID! } @@ -16052,7 +17583,7 @@ input PipelineRetryInput { clientMutationId: String """ - The ID of the pipeline to mutate + The ID of the pipeline to mutate. """ id: CiPipelineID! } @@ -16072,7 +17603,7 @@ type PipelineRetryPayload { errors: [String!]! """ - The pipeline after mutation + The pipeline after mutation. """ pipeline: Pipeline } @@ -16102,17 +17633,17 @@ type Project { """ alertManagementAlert( """ - Username of a user assigned to the issue + Username of a user assigned to the issue. """ assigneeUsername: String """ - Filter query for given domain + Filter query for given domain. """ domain: AlertManagementDomainFilter! = operations """ - IID of the alert. For example, "1" + IID of the alert. For example, "1". """ iid: String @@ -16122,12 +17653,12 @@ type Project { search: String """ - Sort alerts by this criteria + Sort alerts by this criteria. """ sort: AlertManagementAlertSort """ - Alerts with the specified statues. For example, [TRIGGERED] + Alerts with the specified statues. For example, [TRIGGERED]. """ statuses: [AlertManagementStatus!] ): AlertManagementAlert @@ -16137,7 +17668,7 @@ type Project { """ alertManagementAlertStatusCounts( """ - Username of a user assigned to the issue + Username of a user assigned to the issue. """ assigneeUsername: String @@ -16157,7 +17688,7 @@ type Project { after: String """ - Username of a user assigned to the issue + Username of a user assigned to the issue. """ assigneeUsername: String @@ -16167,7 +17698,7 @@ type Project { before: String """ - Filter query for given domain + Filter query for given domain. """ domain: AlertManagementDomainFilter! = operations @@ -16177,7 +17708,7 @@ type Project { first: Int """ - IID of the alert. For example, "1" + IID of the alert. For example, "1". """ iid: String @@ -16192,12 +17723,12 @@ type Project { search: String """ - Sort alerts by this criteria + Sort alerts by this criteria. """ sort: AlertManagementAlertSort """ - Alerts with the specified statues. For example, [TRIGGERED] + Alerts with the specified statues. For example, [TRIGGERED]. """ statuses: [AlertManagementStatus!] ): AlertManagementAlertConnection @@ -16253,7 +17784,7 @@ type Project { """ board( """ - The board's ID + The board's ID. """ id: BoardID! ): Board @@ -16278,7 +17809,7 @@ type Project { first: Int """ - Find a board by its ID + Find a board by its ID. """ id: BoardID @@ -16298,7 +17829,7 @@ type Project { """ clusterAgent( """ - Name of the cluster agent + Name of the cluster agent. """ name: String! ): ClusterAgent @@ -16393,7 +17924,7 @@ type Project { last: Int """ - Filter the container repositories by their name + Filter the container repositories by their name. """ name: String ): ContainerRepositoryConnection @@ -16438,7 +17969,7 @@ type Project { """ dastSiteProfile( """ - ID of the site profile + ID of the site profile. """ id: DastSiteProfileID! ): DastSiteProfile @@ -16469,22 +18000,6 @@ type Project { ): DastSiteProfileConnection """ - DAST Site Validation associated with the project. Will always return `null` if - `security_on_demand_scans_site_validation` is disabled - """ - dastSiteValidation( - """ - Normalized URL of the target to be scanned - """ - normalizedTargetUrls: [String!] - - """ - URL of the target to be scanned - """ - targetUrl: String! - ): DastSiteValidation - - """ DAST Site Validations associated with the project. Will always return no nodes if `security_on_demand_scans_site_validation` is disabled """ @@ -16510,7 +18025,7 @@ type Project { last: Int """ - Normalized URL of the target to be scanned + Normalized URL of the target to be scanned. """ normalizedTargetUrls: [String!] ): DastSiteValidationConnection @@ -16530,17 +18045,17 @@ type Project { """ environment( """ - Name of the environment + Name of the environment. """ name: String """ - Search query for environment name + Search query for environment name. """ search: String """ - States of environments that should be included in result + States of environments that should be included in result. """ states: [String!] ): Environment @@ -16570,17 +18085,17 @@ type Project { last: Int """ - Name of the environment + Name of the environment. """ name: String """ - Search query for environment name + Search query for environment name. """ search: String """ - States of environments that should be included in result + States of environments that should be included in result. """ states: [String!] ): EnvironmentConnection @@ -16650,102 +18165,102 @@ type Project { """ issue( """ - ID of a user assigned to the issues, "none" and "any" values are supported + ID of a user assigned to the issues, "none" and "any" values are supported. """ assigneeId: String """ - Username of a user assigned to the issue + Username of a user assigned to the issue. """ assigneeUsername: String """ - Usernames of users assigned to the issue + Usernames of users assigned to the issue. """ assigneeUsernames: [String!] """ - Username of the author of the issue + Username of the author of the issue. """ authorUsername: String """ - Issues closed after this date + Issues closed after this date. """ closedAfter: Time """ - Issues closed before this date + Issues closed before this date. """ closedBefore: Time """ - Issues created after this date + Issues created after this date. """ createdAfter: Time """ - Issues created before this date + Issues created before this date. """ createdBefore: Time """ - ID of an epic associated with the issues, "none" and "any" values are supported + ID of an epic associated with the issues, "none" and "any" values are supported. """ epicId: String """ - IID of the issue. For example, "1" + IID of the issue. For example, "1". """ iid: String """ - List of IIDs of issues. For example, [1, 2] + List of IIDs of issues. For example, [1, 2]. """ iids: [String!] """ - Iterations applied to the issue + Iterations applied to the issue. """ iterationId: [ID] """ - Labels applied to this issue + Labels applied to this issue. """ labelName: [String] """ - Milestone applied to this issue + Milestone applied to this issue. """ milestoneTitle: [String] """ - Search query for issue title or description + Search query for issue title or description. """ search: String """ - Sort issues by this criteria + Sort issues by this criteria. """ sort: IssueSort = created_desc """ - Current state of this issue + Current state of this issue. """ state: IssuableState """ - Filter issues by the given issue types + Filter issues by the given issue types. """ types: [IssueType!] """ - Issues updated after this date + Issues updated after this date. """ updatedAfter: Time """ - Issues updated before this date + Issues updated before this date. """ updatedBefore: Time ): Issue @@ -16755,82 +18270,82 @@ type Project { """ issueStatusCounts( """ - ID of a user assigned to the issues, "none" and "any" values are supported + ID of a user assigned to the issues, "none" and "any" values are supported. """ assigneeId: String """ - Username of a user assigned to the issue + Username of a user assigned to the issue. """ assigneeUsername: String """ - Usernames of users assigned to the issue + Usernames of users assigned to the issue. """ assigneeUsernames: [String!] """ - Username of the author of the issue + Username of the author of the issue. """ authorUsername: String """ - Issues closed after this date + Issues closed after this date. """ closedAfter: Time """ - Issues closed before this date + Issues closed before this date. """ closedBefore: Time """ - Issues created after this date + Issues created after this date. """ createdAfter: Time """ - Issues created before this date + Issues created before this date. """ createdBefore: Time """ - IID of the issue. For example, "1" + IID of the issue. For example, "1". """ iid: String """ - List of IIDs of issues. For example, [1, 2] + List of IIDs of issues. For example, [1, 2]. """ iids: [String!] """ - Labels applied to this issue + Labels applied to this issue. """ labelName: [String] """ - Milestone applied to this issue + Milestone applied to this issue. """ milestoneTitle: [String] """ - Search query for issue title or description + Search query for issue title or description. """ search: String """ - Filter issues by the given issue types + Filter issues by the given issue types. """ types: [IssueType!] """ - Issues updated after this date + Issues updated after this date. """ updatedAfter: Time """ - Issues updated before this date + Issues updated before this date. """ updatedBefore: Time ): IssueStatusCountsType @@ -16845,22 +18360,22 @@ type Project { after: String """ - ID of a user assigned to the issues, "none" and "any" values are supported + ID of a user assigned to the issues, "none" and "any" values are supported. """ assigneeId: String """ - Username of a user assigned to the issue + Username of a user assigned to the issue. """ assigneeUsername: String """ - Usernames of users assigned to the issue + Usernames of users assigned to the issue. """ assigneeUsernames: [String!] """ - Username of the author of the issue + Username of the author of the issue. """ authorUsername: String @@ -16870,27 +18385,27 @@ type Project { before: String """ - Issues closed after this date + Issues closed after this date. """ closedAfter: Time """ - Issues closed before this date + Issues closed before this date. """ closedBefore: Time """ - Issues created after this date + Issues created after this date. """ createdAfter: Time """ - Issues created before this date + Issues created before this date. """ createdBefore: Time """ - ID of an epic associated with the issues, "none" and "any" values are supported + ID of an epic associated with the issues, "none" and "any" values are supported. """ epicId: String @@ -16900,22 +18415,22 @@ type Project { first: Int """ - IID of the issue. For example, "1" + IID of the issue. For example, "1". """ iid: String """ - List of IIDs of issues. For example, [1, 2] + List of IIDs of issues. For example, [1, 2]. """ iids: [String!] """ - Iterations applied to the issue + Iterations applied to the issue. """ iterationId: [ID] """ - Labels applied to this issue + Labels applied to this issue. """ labelName: [String] @@ -16925,37 +18440,37 @@ type Project { last: Int """ - Milestone applied to this issue + Milestone applied to this issue. """ milestoneTitle: [String] """ - Search query for issue title or description + Search query for issue title or description. """ search: String """ - Sort issues by this criteria + Sort issues by this criteria. """ sort: IssueSort = created_desc """ - Current state of this issue + Current state of this issue. """ state: IssuableState """ - Filter issues by the given issue types + Filter issues by the given issue types. """ types: [IssueType!] """ - Issues updated after this date + Issues updated after this date. """ updatedAfter: Time """ - Issues updated before this date + Issues updated before this date. """ updatedBefore: Time ): IssueConnection @@ -17023,7 +18538,7 @@ type Project { state: IterationState """ - List items overlapping the given timeframe + List items overlapping the given timeframe. """ timeframe: Timeframe @@ -17123,7 +18638,7 @@ type Project { """ mergeRequest( """ - IID of the merge request, for example `1` + IID of the merge request, for example `1`. """ iid: String! ): MergeRequest @@ -17138,12 +18653,12 @@ type Project { after: String """ - Username of the assignee + Username of the assignee. """ assigneeUsername: String """ - Username of the author + Username of the author. """ authorUsername: String @@ -17158,7 +18673,7 @@ type Project { first: Int """ - Array of IIDs of merge requests, for example `[1, 2]` + Array of IIDs of merge requests, for example `[1, 2]`. """ iids: [String!] @@ -17173,27 +18688,27 @@ type Project { last: Int """ - Merge requests merged after this date + Merge requests merged after this date. """ mergedAfter: Time """ - Merge requests merged before this date + Merge requests merged before this date. """ mergedBefore: Time """ - Title of the milestone + Title of the milestone. """ milestoneTitle: String """ - Username of the reviewer + Username of the reviewer. """ reviewerUsername: String """ - Sort merge requests by this criteria + Sort merge requests by this criteria. """ sort: MergeRequestSort = created_desc @@ -17240,7 +18755,7 @@ type Project { before: String """ - A date that the milestone contains + A date that the milestone contains. """ containingDate: Time @@ -17256,12 +18771,12 @@ type Project { first: Int """ - Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1" + Array of global milestone IDs, e.g., "gid://gitlab/Milestone/1". """ ids: [ID!] """ - Also return milestones in the project's parent group and its ancestors + Also return milestones in the project's parent group and its ancestors. """ includeAncestors: Boolean @@ -17271,7 +18786,7 @@ type Project { last: Int """ - A search string for the title + A search string for the title. """ searchTitle: String @@ -17283,17 +18798,17 @@ type Project { startDate: Time """ - Filter milestones by state + Filter milestones by state. """ state: MilestoneStateEnum """ - List items overlapping the given timeframe + List items overlapping the given timeframe. """ timeframe: Timeframe """ - The title of the milestone + The title of the milestone. """ title: String ): MilestoneConnection @@ -17363,7 +18878,7 @@ type Project { """ pipeline( """ - IID of the Pipeline, e.g., "1" + IID of the Pipeline, e.g., "1". """ iid: ID! ): Pipeline @@ -17398,17 +18913,17 @@ type Project { last: Int """ - Filter pipelines by the ref they are run for + Filter pipelines by the ref they are run for. """ ref: String """ - Filter pipelines by the sha of the commit they are run for + Filter pipelines by the sha of the commit they are run for. """ sha: String """ - Filter pipelines by their status + Filter pipelines by their status. """ status: PipelineStatusEnum ): PipelineConnection @@ -17444,12 +18959,12 @@ type Project { last: Int """ - Filter members by the given member relations + Filter members by the given member relations. """ relations: [ProjectMemberRelation!] = [DIRECT, INHERITED] """ - Search query + Search query. """ search: String ): MemberInterfaceConnection @@ -17464,7 +18979,7 @@ type Project { """ release( """ - The name of the tag associated to the release + The name of the tag associated to the release. """ tagName: String! ): Release @@ -17494,7 +19009,7 @@ type Project { last: Int """ - Sort releases by this criteria + Sort releases by this criteria. """ sort: ReleaseSort = RELEASED_AT_DESC ): ReleaseConnection @@ -17524,32 +19039,32 @@ type Project { """ requirement( """ - Filter requirements by author username + Filter requirements by author username. """ authorUsername: [String!] """ - IID of the requirement, e.g., "1" + IID of the requirement, e.g., "1". """ iid: ID """ - List of IIDs of requirements, e.g., [1, 2] + List of IIDs of requirements, e.g., [1, 2]. """ iids: [ID!] """ - Search query for requirement title + Search query for requirement title. """ search: String """ - List requirements by sort order + List requirements by sort order. """ sort: Sort """ - Filter requirements by state + Filter requirements by state. """ state: RequirementState ): Requirement @@ -17569,7 +19084,7 @@ type Project { after: String """ - Filter requirements by author username + Filter requirements by author username. """ authorUsername: [String!] @@ -17584,12 +19099,12 @@ type Project { first: Int """ - IID of the requirement, e.g., "1" + IID of the requirement, e.g., "1". """ iid: ID """ - List of IIDs of requirements, e.g., [1, 2] + List of IIDs of requirements, e.g., [1, 2]. """ iids: [ID!] @@ -17599,17 +19114,17 @@ type Project { last: Int """ - Search query for requirement title + Search query for requirement title. """ search: String """ - List requirements by sort order + List requirements by sort order. """ sort: Sort """ - Filter requirements by state + Filter requirements by state. """ state: RequirementState ): RequirementConnection @@ -17634,7 +19149,7 @@ type Project { """ sentryDetailedError( """ - ID of the Sentry issue + ID of the Sentry issue. """ id: GitlabErrorTrackingDetailedErrorID! ): SentryDetailedError @@ -17659,7 +19174,7 @@ type Project { """ services( """ - Indicates if the service is active + Indicates if the service is active. """ active: Boolean @@ -17684,7 +19199,7 @@ type Project { last: Int """ - Class name of the service + Class name of the service. """ type: ServiceType ): ServiceConnection @@ -17714,7 +19229,7 @@ type Project { first: Int """ - Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1" + Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1". """ ids: [SnippetID!] @@ -17724,7 +19239,7 @@ type Project { last: Int """ - The visibility of the snippet + The visibility of the snippet. """ visibility: VisibilityScopesEnum ): SnippetConnection @@ -17790,11 +19305,6 @@ type Project { ): TerraformStateConnection """ - Total pipeline duration for all of the pipelines in a project - """ - totalPipelineDuration: Int - - """ Permissions for the current user on the resource """ userPermissions: ProjectPermissions! @@ -17824,12 +19334,12 @@ type Project { first: Int """ - Returns only the vulnerabilities which have linked issues + Returns only the vulnerabilities which have linked issues. """ hasIssues: Boolean """ - Returns only the vulnerabilities which have been resolved on default branch + Returns only the vulnerabilities which have been resolved on default branch. """ hasResolution: Boolean @@ -17839,32 +19349,32 @@ type Project { last: Int """ - Filter vulnerabilities by project + Filter vulnerabilities by project. """ projectId: [ID!] """ - Filter vulnerabilities by report type + Filter vulnerabilities by report type. """ reportType: [VulnerabilityReportType!] """ - Filter vulnerabilities by scanner + Filter vulnerabilities by VulnerabilityScanner.externalId. """ scanner: [String!] """ - Filter vulnerabilities by severity + Filter vulnerabilities by severity. """ severity: [VulnerabilitySeverity!] """ - List vulnerabilities by sort order + List vulnerabilities by sort order. """ sort: VulnerabilitySort = severity_desc """ - Filter vulnerabilities by state + Filter vulnerabilities by state. """ state: [VulnerabilityState!] ): VulnerabilityConnection @@ -17884,7 +19394,7 @@ type Project { before: String """ - Last day for which to fetch vulnerability history + Last day for which to fetch vulnerability history. """ endDate: ISO8601Date! @@ -17899,7 +19409,7 @@ type Project { last: Int """ - First day for which to fetch vulnerability history + First day for which to fetch vulnerability history. """ startDate: ISO8601Date! ): VulnerabilitiesCountByDayConnection @@ -17934,27 +19444,27 @@ type Project { """ vulnerabilitySeveritiesCount( """ - Filter vulnerabilities by project + Filter vulnerabilities by project. """ projectId: [ID!] """ - Filter vulnerabilities by report type + Filter vulnerabilities by report type. """ reportType: [VulnerabilityReportType!] """ - Filter vulnerabilities by scanner + Filter vulnerabilities by scanner. """ scanner: [String!] """ - Filter vulnerabilities by severity + Filter vulnerabilities by severity. """ severity: [VulnerabilitySeverity!] """ - Filter vulnerabilities by state + Filter vulnerabilities by state. """ state: [VulnerabilityState!] ): VulnerabilitySeveritiesCount @@ -17972,6 +19482,11 @@ type Project { type ProjectCiCdSetting { """ + Whether to keep the latest builds artifacts. + """ + keepLatestArtifact: Boolean + + """ Whether merge pipelines are enabled. """ mergePipelinesEnabled: Boolean @@ -18416,12 +19931,12 @@ Autogenerated input type of PrometheusIntegrationCreate """ input PrometheusIntegrationCreateInput { """ - Whether the integration is receiving alerts + Whether the integration is receiving alerts. """ active: Boolean! """ - Endpoint at which prometheus can be queried + Endpoint at which prometheus can be queried. """ apiUrl: String! @@ -18431,7 +19946,7 @@ input PrometheusIntegrationCreateInput { clientMutationId: String """ - The project to create the integration in + The project to create the integration in. """ projectPath: ID! } @@ -18451,7 +19966,7 @@ type PrometheusIntegrationCreatePayload { errors: [String!]! """ - The newly created integration + The newly created integration. """ integration: AlertManagementPrometheusIntegration } @@ -18466,7 +19981,7 @@ input PrometheusIntegrationResetTokenInput { clientMutationId: String """ - The ID of the integration to mutate + The ID of the integration to mutate. """ id: PrometheusServiceID! } @@ -18486,7 +20001,7 @@ type PrometheusIntegrationResetTokenPayload { errors: [String!]! """ - The newly created integration + The newly created integration. """ integration: AlertManagementPrometheusIntegration } @@ -18496,12 +20011,12 @@ Autogenerated input type of PrometheusIntegrationUpdate """ input PrometheusIntegrationUpdateInput { """ - Whether the integration is receiving alerts + Whether the integration is receiving alerts. """ active: Boolean """ - Endpoint at which prometheus can be queried + Endpoint at which prometheus can be queried. """ apiUrl: String @@ -18511,7 +20026,7 @@ input PrometheusIntegrationUpdateInput { clientMutationId: String """ - The ID of the integration to mutate + The ID of the integration to mutate. """ id: PrometheusServiceID! } @@ -18531,7 +20046,7 @@ type PrometheusIntegrationUpdatePayload { errors: [String!]! """ - The newly created integration + The newly created integration. """ integration: AlertManagementPrometheusIntegration } @@ -18551,17 +20066,17 @@ input PromoteToEpicInput { clientMutationId: String """ - The group the promoted epic will belong to + The group the promoted epic will belong to. """ groupPath: ID """ - The IID of the issue to mutate + The IID of the issue to mutate. """ iid: String! """ - The project the issue to mutate is in + The project the issue to mutate is in. """ projectPath: ID! } @@ -18576,7 +20091,7 @@ type PromoteToEpicPayload { clientMutationId: String """ - The epic after issue promotion + The epic after issue promotion. """ epic: Epic @@ -18586,7 +20101,7 @@ type PromoteToEpicPayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -18597,9 +20112,19 @@ type Query { """ ciConfig( """ - Contents of .gitlab-ci.yml + Contents of '.gitlab-ci.yml'. """ content: String! + + """ + Run pipeline creation simulation, or only do static check. + """ + dryRun: Boolean + + """ + The project of the CI config. + """ + projectPath: ID! ): CiConfig """ @@ -18652,7 +20177,7 @@ type Query { """ echo( """ - Text to echo back + Text to echo back. """ text: String! ): String! @@ -18672,7 +20197,7 @@ type Query { """ group( """ - The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss" + The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss". """ fullPath: ID! ): Group @@ -18702,7 +20227,7 @@ type Query { first: Int """ - The type of measurement/statistics to retrieve + The type of measurement/statistics to retrieve. """ identifier: MeasurementIdentifier! @@ -18712,12 +20237,12 @@ type Query { last: Int """ - Measurement recorded after this date + Measurement recorded after this date. """ recordedAfter: Time """ - Measurement recorded before this date + Measurement recorded before this date. """ recordedBefore: Time ): InstanceStatisticsMeasurementConnection @@ -18762,17 +20287,27 @@ type Query { """ namespace( """ - The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss" + The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss". """ fullPath: ID! ): Namespace """ + Find a composer package + """ + packageComposerDetails( + """ + The global ID of the package. + """ + id: PackagesPackageID! + ): PackageComposerDetails + + """ Find a project """ project( """ - The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss" + The full path of the project, group or namespace, e.g., "gitlab-org/gitlab-foss". """ fullPath: ID! ): Project @@ -18797,7 +20332,7 @@ type Query { first: Int """ - Filter projects by IDs + Filter projects by IDs. """ ids: [ID!] @@ -18807,22 +20342,22 @@ type Query { last: Int """ - Limit projects that the current user is a member of + Limit projects that the current user is a member of. """ membership: Boolean """ - Search query for project name, path, or description + Search query for project name, path, or description. """ search: String """ - Include namespace in project search + Include namespace in project search. """ searchNamespaces: Boolean """ - Sort order of results + Sort order of results. """ sort: String ): ProjectConnection @@ -18857,22 +20392,22 @@ type Query { """ runnerSetup( """ - Architecture to generate the instructions for + Architecture to generate the instructions for. """ architecture: String! """ - Group to register the runner for + Group to register the runner for. """ groupId: GroupID """ - Platform to generate the instructions for + Platform to generate the instructions for. """ platform: String! """ - Project to register the runner for + Project to register the runner for. """ projectId: ProjectID ): RunnerSetup @@ -18887,7 +20422,7 @@ type Query { after: String """ - The ID of an author + The ID of an author. """ authorId: UserID @@ -18897,7 +20432,7 @@ type Query { before: String """ - Explore personal snippets + Explore personal snippets. """ explore: Boolean @@ -18907,7 +20442,7 @@ type Query { first: Int """ - Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1" + Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1". """ ids: [SnippetID!] @@ -18917,17 +20452,17 @@ type Query { last: Int """ - The ID of a project + The ID of a project. """ projectId: ProjectID """ - The type of snippet + The type of snippet. """ type: TypeEnum """ - The visibility of the snippet + The visibility of the snippet. """ visibility: VisibilityScopesEnum ): SnippetConnection @@ -18937,12 +20472,12 @@ type Query { """ user( """ - ID of the User + ID of the User. """ id: UserID """ - Username of the User + Username of the User. """ username: String ): User @@ -18952,6 +20487,11 @@ type Query { """ users( """ + Return only admin users. + """ + admins: Boolean = false + + """ Returns the elements in the list that come after the specified cursor. """ after: String @@ -18967,7 +20507,7 @@ type Query { first: Int """ - List of user Global IDs + List of user Global IDs. """ ids: [ID!] @@ -18982,12 +20522,12 @@ type Query { search: String """ - Sort users by this criteria + Sort users by this criteria. """ sort: Sort = created_desc """ - List of usernames + List of usernames. """ usernames: [String!] ): UserConnection @@ -19012,12 +20552,12 @@ type Query { first: Int """ - Returns only the vulnerabilities which have linked issues + Returns only the vulnerabilities which have linked issues. """ hasIssues: Boolean """ - Returns only the vulnerabilities which have been resolved on default branch + Returns only the vulnerabilities which have been resolved on default branch. """ hasResolution: Boolean @@ -19027,32 +20567,32 @@ type Query { last: Int """ - Filter vulnerabilities by project + Filter vulnerabilities by project. """ projectId: [ID!] """ - Filter vulnerabilities by report type + Filter vulnerabilities by report type. """ reportType: [VulnerabilityReportType!] """ - Filter vulnerabilities by scanner + Filter vulnerabilities by VulnerabilityScanner.externalId. """ scanner: [String!] """ - Filter vulnerabilities by severity + Filter vulnerabilities by severity. """ severity: [VulnerabilitySeverity!] """ - List vulnerabilities by sort order + List vulnerabilities by sort order. """ sort: VulnerabilitySort = severity_desc """ - Filter vulnerabilities by state + Filter vulnerabilities by state. """ state: [VulnerabilityState!] ): VulnerabilityConnection @@ -19072,7 +20612,7 @@ type Query { before: String """ - Last day for which to fetch vulnerability history + Last day for which to fetch vulnerability history. """ endDate: ISO8601Date! @@ -19087,7 +20627,7 @@ type Query { last: Int """ - First day for which to fetch vulnerability history + First day for which to fetch vulnerability history. """ startDate: ISO8601Date! ): VulnerabilitiesCountByDayConnection @@ -19109,7 +20649,7 @@ type Query { before: String """ - Last day for which to fetch vulnerability history + Last day for which to fetch vulnerability history. """ endDate: ISO8601Date! @@ -19124,7 +20664,7 @@ type Query { last: Int """ - First day for which to fetch vulnerability history + First day for which to fetch vulnerability history. """ startDate: ISO8601Date! ): VulnerabilitiesCountByDayAndSeverityConnection @deprecated(reason: "Use `vulnerabilitiesCountByDay`. Deprecated in 13.3.") @@ -19500,7 +21040,7 @@ Autogenerated input type of ReleaseCreate """ input ReleaseCreateInput { """ - Assets associated to the release + Assets associated to the release. """ assets: ReleaseAssetsInput @@ -19510,7 +21050,7 @@ input ReleaseCreateInput { clientMutationId: String """ - Description (also known as "release notes") of the release + Description (also known as "release notes") of the release. """ description: String @@ -19520,17 +21060,17 @@ input ReleaseCreateInput { milestones: [String!] """ - Name of the release + Name of the release. """ name: String """ - Full path of the project the release is associated with + Full path of the project the release is associated with. """ projectPath: ID! """ - The commit SHA or branch name to use if creating a new tag + The commit SHA or branch name to use if creating a new tag. """ ref: String @@ -19540,7 +21080,7 @@ input ReleaseCreateInput { releasedAt: Time """ - Name of the tag to associate with the release + Name of the tag to associate with the release. """ tagName: String! } @@ -19560,7 +21100,7 @@ type ReleaseCreatePayload { errors: [String!]! """ - The release after mutation + The release after mutation. """ release: Release } @@ -19575,7 +21115,7 @@ input ReleaseDeleteInput { clientMutationId: String """ - Full path of the project the release is associated with + Full path of the project the release is associated with. """ projectPath: ID! @@ -19802,7 +21342,7 @@ input ReleaseUpdateInput { clientMutationId: String """ - Description (release notes) of the release + Description (release notes) of the release. """ description: String @@ -19812,22 +21352,22 @@ input ReleaseUpdateInput { milestones: [String!] """ - Name of the release + Name of the release. """ name: String """ - Full path of the project the release is associated with + Full path of the project the release is associated with. """ projectPath: ID! """ - The release date + The release date. """ releasedAt: Time """ - Name of the tag associated with the release + Name of the tag associated with the release. """ tagName: String! } @@ -19857,7 +21397,7 @@ Autogenerated input type of RemoveAwardEmoji """ input RemoveAwardEmojiInput { """ - The global ID of the awardable resource + The global ID of the awardable resource. """ awardableId: AwardableID! @@ -19877,7 +21417,7 @@ Autogenerated return type of RemoveAwardEmoji """ type RemoveAwardEmojiPayload { """ - The award emoji after mutation + The award emoji after mutation. """ awardEmoji: AwardEmoji @@ -19902,7 +21442,7 @@ input RemoveProjectFromSecurityDashboardInput { clientMutationId: String """ - ID of the project to remove from the Instance Security Dashboard + ID of the project to remove from the Instance Security Dashboard. """ id: ProjectID! } @@ -19932,7 +21472,7 @@ input RepositionImageDiffNoteInput { clientMutationId: String """ - The global ID of the DiffNote to update + The global ID of the DiffNote to update. """ id: DiffNoteID! @@ -19957,7 +21497,7 @@ type RepositionImageDiffNotePayload { errors: [String!]! """ - The note after mutation + The note after mutation. """ note: Note } @@ -19983,17 +21523,17 @@ type Repository { """ tree( """ - The path to get the tree for. Default value is the root of the repository + The path to get the tree for. Default value is the root of the repository. """ path: String = "" """ - Used to get a recursive tree. Default is false + Used to get a recursive tree. Default is false. """ recursive: Boolean = false """ - The commit ref to get the tree for. Default value is HEAD + The commit ref to get the tree for. Default value is HEAD. """ ref: String = "head" ): Tree @@ -20078,7 +21618,7 @@ type Requirement { last: Int """ - List test reports by sort order + List test reports by sort order. """ sort: Sort ): TestReportConnection @@ -20224,7 +21764,7 @@ input RevertVulnerabilityToDetectedInput { clientMutationId: String """ - ID of the vulnerability to be reverted + ID of the vulnerability to be reverted. """ id: VulnerabilityID! } @@ -20244,7 +21784,7 @@ type RevertVulnerabilityToDetectedPayload { errors: [String!]! """ - The vulnerability after revert + The vulnerability after revert. """ vulnerability: Vulnerability } @@ -21310,7 +22850,7 @@ type SentryErrorCollection { """ detailedError( """ - ID of the Sentry issue + ID of the Sentry issue. """ id: GitlabErrorTrackingDetailedErrorID! ): SentryDetailedError @@ -21320,7 +22860,7 @@ type SentryErrorCollection { """ errorStackTrace( """ - ID of the Sentry issue + ID of the Sentry issue. """ id: GitlabErrorTrackingDetailedErrorID! ): SentryErrorStackTrace @@ -21350,12 +22890,12 @@ type SentryErrorCollection { last: Int """ - Search query for the Sentry error details + Search query for the Sentry error details. """ searchTerm: String """ - Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default + Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default. """ sort: String ): SentryErrorConnection @@ -21566,7 +23106,6 @@ type ServiceEdge { } enum ServiceType { - ALERTS_SERVICE ASANA_SERVICE ASSEMBLA_SERVICE BAMBOO_SERVICE @@ -21644,7 +23183,7 @@ type Snippet implements Noteable { last: Int """ - Paths of the blobs + Paths of the blobs. """ paths: [String!] ): SnippetBlobConnection @@ -22333,7 +23872,7 @@ input TerraformStateDeleteInput { clientMutationId: String """ - Global ID of the Terraform state + Global ID of the Terraform state. """ id: TerraformStateID! } @@ -22383,7 +23922,7 @@ input TerraformStateLockInput { clientMutationId: String """ - Global ID of the Terraform state + Global ID of the Terraform state. """ id: TerraformStateID! } @@ -22413,7 +23952,7 @@ input TerraformStateUnlockInput { clientMutationId: String """ - Global ID of the Terraform state + Global ID of the Terraform state. """ id: TerraformStateID! } @@ -22847,7 +24386,7 @@ input TodoCreateInput { clientMutationId: String """ - The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported + The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported. """ targetId: TodoableID! } @@ -22867,7 +24406,7 @@ type TodoCreatePayload { errors: [String!]! """ - The to-do created + The to-do created. """ todo: Todo } @@ -22902,7 +24441,7 @@ input TodoMarkDoneInput { clientMutationId: String """ - The global ID of the todo to mark as done + The global ID of the todo to mark as done. """ id: TodoID! } @@ -22922,7 +24461,7 @@ type TodoMarkDonePayload { errors: [String!]! """ - The requested todo + The requested todo. """ todo: Todo! } @@ -22937,7 +24476,7 @@ input TodoRestoreInput { clientMutationId: String """ - The global ID of the todo to restore + The global ID of the todo to restore. """ id: TodoID! } @@ -22952,7 +24491,7 @@ input TodoRestoreManyInput { clientMutationId: String """ - The global IDs of the todos to restore (a maximum of 50 is supported at once) + The global IDs of the todos to restore (a maximum of 50 is supported at once). """ ids: [TodoID!]! } @@ -22972,12 +24511,12 @@ type TodoRestoreManyPayload { errors: [String!]! """ - Updated todos + Updated todos. """ todos: [Todo!]! """ - The IDs of the updated todo items Deprecated in 13.2: Use todos. + The IDs of the updated todo items. Deprecated in 13.2: Use todos. """ updatedIds: [TodoID!]! @deprecated(reason: "Use todos. Deprecated in 13.2.") } @@ -22997,7 +24536,7 @@ type TodoRestorePayload { errors: [String!]! """ - The requested todo + The requested todo. """ todo: Todo! } @@ -23069,12 +24608,12 @@ type TodosMarkAllDonePayload { errors: [String!]! """ - Updated todos + Updated todos. """ todos: [Todo!]! """ - Ids of the updated todos Deprecated in 13.2: Use todos. + Ids of the updated todos. Deprecated in 13.2: Use todos. """ updatedIds: [TodoID!]! @deprecated(reason: "Use todos. Deprecated in 13.2.") } @@ -23084,7 +24623,7 @@ Autogenerated input type of ToggleAwardEmoji """ input ToggleAwardEmojiInput { """ - The global ID of the awardable resource + The global ID of the awardable resource. """ awardableId: AwardableID! @@ -23104,7 +24643,7 @@ Autogenerated return type of ToggleAwardEmoji """ type ToggleAwardEmojiPayload { """ - The award emoji after mutation + The award emoji after mutation. """ awardEmoji: AwardEmoji @@ -23306,17 +24845,17 @@ input UpdateAlertStatusInput { clientMutationId: String """ - The IID of the alert to mutate + The IID of the alert to mutate. """ iid: String! """ - The project the alert to mutate is in + The project the alert to mutate is in. """ projectPath: ID! """ - The status to set the alert + The status to set the alert. """ status: AlertManagementStatus! } @@ -23326,7 +24865,7 @@ Autogenerated return type of UpdateAlertStatus """ type UpdateAlertStatusPayload { """ - The alert after mutation + The alert after mutation. """ alert: AlertManagementAlert @@ -23341,12 +24880,12 @@ type UpdateAlertStatusPayload { errors: [String!]! """ - The issue created after mutation + The issue created after mutation. """ issue: Issue """ - The todo after mutation + The todo after mutation. """ todo: Todo } @@ -23356,7 +24895,7 @@ Autogenerated input type of UpdateBoardEpicUserPreferences """ input UpdateBoardEpicUserPreferencesInput { """ - The board global ID + The board global ID. """ boardId: BoardID! @@ -23366,12 +24905,12 @@ input UpdateBoardEpicUserPreferencesInput { clientMutationId: String """ - Whether the epic should be collapsed in the board + Whether the epic should be collapsed in the board. """ collapsed: Boolean! """ - ID of an epic to set preferences for + ID of an epic to set preferences for. """ epicId: EpicID! } @@ -23386,7 +24925,7 @@ type UpdateBoardEpicUserPreferencesPayload { clientMutationId: String """ - User preferences for the epic in the board after mutation + User preferences for the epic in the board after mutation. """ epicUserPreferences: BoardEpicUserPreferences @@ -23401,6 +24940,11 @@ Autogenerated input type of UpdateBoard """ input UpdateBoardInput { """ + The ID of user to be assigned to the board. + """ + assigneeId: UserID + + """ A unique identifier for the client performing the mutation. """ clientMutationId: String @@ -23421,9 +24965,34 @@ input UpdateBoardInput { id: BoardID! """ + The ID of iteration to be assigned to the board. + """ + iterationId: IterationID + + """ + The IDs of labels to be added to the board. + """ + labelIds: [LabelID!] + + """ + Labels of the issue + """ + labels: [String!] + + """ + The ID of milestone to be assigned to the board. + """ + milestoneId: MilestoneID + + """ The board name. """ name: String + + """ + The weight value to be assigned to the board. + """ + weight: Int } """ @@ -23436,7 +25005,7 @@ input UpdateBoardListInput { clientMutationId: String """ - Indicates if list is collapsed for this user + Indicates if list is collapsed for this user. """ collapsed: Boolean @@ -23446,7 +25015,7 @@ input UpdateBoardListInput { listId: ListID! """ - Position of list within the board + Position of list within the board. """ position: Int } @@ -23466,7 +25035,7 @@ type UpdateBoardListPayload { errors: [String!]! """ - Mutated list + Mutated list. """ list: BoardList } @@ -23501,24 +25070,14 @@ input UpdateComplianceFrameworkInput { clientMutationId: String """ - New color representation of the compliance framework in hex format. e.g. #FCA121 - """ - color: String - - """ - New description for the compliance framework - """ - description: String - - """ - The global ID of the compliance framework to update + The global ID of the compliance framework to update. """ id: ComplianceManagementFrameworkID! """ - New name for the compliance framework + Parameters to update the compliance framework with. """ - name: String + params: ComplianceFrameworkInput! } """ @@ -23531,7 +25090,7 @@ type UpdateComplianceFrameworkPayload { clientMutationId: String """ - The compliance framework after mutation + The compliance framework after mutation. """ complianceFramework: ComplianceFramework @@ -23581,7 +25140,7 @@ input UpdateContainerExpirationPolicyInput { olderThan: ContainerExpirationPolicyOlderThanEnum """ - The project path where the container expiration policy is located + The project path where the container expiration policy is located. """ projectPath: ID! } @@ -23596,7 +25155,7 @@ type UpdateContainerExpirationPolicyPayload { clientMutationId: String """ - The container expiration policy after mutation + The container expiration policy after mutation. """ containerExpirationPolicy: ContainerExpirationPolicy @@ -23616,17 +25175,17 @@ input UpdateDevopsAdoptionSegmentInput { clientMutationId: String """ - The array of group IDs to set for the segment + The array of group IDs to set for the segment. """ groupIds: [GroupID!] """ - ID of the segment + ID of the segment. """ id: AnalyticsDevopsAdoptionSegmentID! """ - Name of the segment + Name of the segment. """ name: String! } @@ -23646,7 +25205,7 @@ type UpdateDevopsAdoptionSegmentPayload { errors: [String!]! """ - The segment after mutation + The segment after mutation. """ segment: DevopsAdoptionSegment } @@ -23688,32 +25247,32 @@ input UpdateEpicInput { clientMutationId: String """ - Indicates if the epic is confidential + Indicates if the epic is confidential. """ confidential: Boolean """ - The description of the epic + The description of the epic. """ description: String """ - The end date of the epic + The end date of the epic. """ dueDateFixed: String """ - Indicates end date should be sourced from due_date_fixed field not the issue milestones + Indicates end date should be sourced from due_date_fixed field not the issue milestones. """ dueDateIsFixed: Boolean """ - The group the epic to mutate is in + The group the epic to mutate is in. """ groupPath: ID! """ - The IID of the epic to mutate + The IID of the epic to mutate. """ iid: ID! @@ -23723,22 +25282,22 @@ input UpdateEpicInput { removeLabelIds: [ID!] """ - The start date of the epic + The start date of the epic. """ startDateFixed: String """ - Indicates start date should be sourced from start_date_fixed field not the issue milestones + Indicates start date should be sourced from start_date_fixed field not the issue milestones. """ startDateIsFixed: Boolean """ - State event for the epic + State event for the epic. """ stateEvent: EpicStateEvent """ - The title of the epic + The title of the epic. """ title: String } @@ -23753,7 +25312,7 @@ type UpdateEpicPayload { clientMutationId: String """ - The epic after mutation + The epic after mutation. """ epic: Epic @@ -23778,7 +25337,7 @@ input UpdateImageDiffNoteInput { clientMutationId: String """ - The global ID of the note to update + The global ID of the note to update. """ id: NoteID! @@ -23803,7 +25362,7 @@ type UpdateImageDiffNotePayload { errors: [String!]! """ - The note after mutation + The note after mutation. """ note: Note } @@ -23813,7 +25372,7 @@ Autogenerated input type of UpdateIssue """ input UpdateIssueInput { """ - The IDs of labels to be added to the issue + The IDs of labels to be added to the issue. """ addLabelIds: [ID!] @@ -23838,17 +25397,17 @@ input UpdateIssueInput { dueDate: ISO8601Date """ - The ID of the parent epic. NULL when removing the association + The ID of the parent epic. NULL when removing the association. """ epicId: EpicID """ - The desired health status + The desired health status. """ healthStatus: HealthStatus """ - The IID of the issue to mutate + The IID of the issue to mutate. """ iid: String! @@ -23858,22 +25417,22 @@ input UpdateIssueInput { locked: Boolean """ - The ID of the milestone to assign to the issue. On update milestone will be removed if set to null + The ID of the milestone to assign to the issue. On update milestone will be removed if set to null. """ milestoneId: ID """ - The project the issue to mutate is in + The project the issue to mutate is in. """ projectPath: ID! """ - The IDs of labels to be removed from the issue + The IDs of labels to be removed from the issue. """ removeLabelIds: [ID!] """ - Close or reopen an issue + Close or reopen an issue. """ stateEvent: IssueStateEvent @@ -23883,7 +25442,7 @@ input UpdateIssueInput { title: String """ - The weight of the issue + The weight of the issue. """ weight: Int } @@ -23903,7 +25462,7 @@ type UpdateIssuePayload { errors: [String!]! """ - The issue after mutation + The issue after mutation. """ issue: Issue } @@ -23969,6 +25528,52 @@ type UpdateIterationPayload { } """ +Autogenerated input type of UpdateNamespacePackageSettings +""" +input UpdateNamespacePackageSettingsInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + When maven_duplicates_allowed is false, you can publish duplicate packages + with names that match this regex. Otherwise, this setting has no effect. + """ + mavenDuplicateExceptionRegex: UntrustedRegexp + + """ + Indicates whether duplicate Maven packages are allowed for this namespace. + """ + mavenDuplicatesAllowed: Boolean + + """ + The namespace path where the namespace package setting is located. + """ + namespacePath: ID! +} + +""" +Autogenerated return type of UpdateNamespacePackageSettings +""" +type UpdateNamespacePackageSettingsPayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + The namespace package setting after mutation. + """ + packageSettings: PackageSettings +} + +""" Autogenerated input type of UpdateNote """ input UpdateNoteInput { @@ -23988,7 +25593,7 @@ input UpdateNoteInput { confidential: Boolean """ - The global ID of the note to update + The global ID of the note to update. """ id: NoteID! } @@ -24008,7 +25613,7 @@ type UpdateNotePayload { errors: [String!]! """ - The note after mutation + The note after mutation. """ note: Note } @@ -24023,32 +25628,32 @@ input UpdateRequirementInput { clientMutationId: String """ - Description of the requirement + Description of the requirement. """ description: String """ - The IID of the requirement to update + The IID of the requirement to update. """ iid: String! """ - Creates a test report for the requirement with the given state + Creates a test report for the requirement with the given state. """ lastTestReportState: TestReportState """ - Full project path the requirement is associated with + Full project path the requirement is associated with. """ projectPath: ID! """ - State of the requirement + State of the requirement. """ state: RequirementState """ - Title of the requirement + Title of the requirement. """ title: String } @@ -24068,7 +25673,7 @@ type UpdateRequirementPayload { errors: [String!]! """ - Requirement after mutation + Requirement after mutation. """ requirement: Requirement } @@ -24078,7 +25683,7 @@ Autogenerated input type of UpdateSnippet """ input UpdateSnippetInput { """ - Actions to perform over the snippet repository and blobs + Actions to perform over the snippet repository and blobs. """ blobActions: [SnippetBlobActionInputType!] @@ -24088,22 +25693,22 @@ input UpdateSnippetInput { clientMutationId: String """ - Description of the snippet + Description of the snippet. """ description: String """ - The global ID of the snippet to update + The global ID of the snippet to update. """ id: SnippetID! """ - Title of the snippet + Title of the snippet. """ title: String """ - The visibility level of the snippet + The visibility level of the snippet. """ visibilityLevel: VisibilityLevelsEnum } @@ -24123,12 +25728,12 @@ type UpdateSnippetPayload { errors: [String!]! """ - The snippet after mutation + The snippet after mutation. """ snippet: Snippet """ - Indicates whether the operation returns a record detected as spam + Indicates whether the operation returns a record detected as spam. """ spam: Boolean } @@ -24146,7 +25751,7 @@ type User { after: String """ - Username of the author + Username of the author. """ authorUsername: String @@ -24161,7 +25766,7 @@ type User { first: Int """ - Array of IIDs of merge requests, for example `[1, 2]` + Array of IIDs of merge requests, for example `[1, 2]`. """ iids: [String!] @@ -24176,17 +25781,17 @@ type User { last: Int """ - Merge requests merged after this date + Merge requests merged after this date. """ mergedAfter: Time """ - Merge requests merged before this date + Merge requests merged before this date. """ mergedBefore: Time """ - Title of the milestone + Title of the milestone. """ milestoneTitle: String @@ -24201,12 +25806,12 @@ type User { projectPath: String """ - Username of the reviewer + Username of the reviewer. """ reviewerUsername: String """ - Sort merge requests by this criteria + Sort merge requests by this criteria. """ sort: MergeRequestSort = created_desc @@ -24236,7 +25841,7 @@ type User { after: String """ - Username of the assignee + Username of the assignee. """ assigneeUsername: String @@ -24251,7 +25856,7 @@ type User { first: Int """ - Array of IIDs of merge requests, for example `[1, 2]` + Array of IIDs of merge requests, for example `[1, 2]`. """ iids: [String!] @@ -24266,17 +25871,17 @@ type User { last: Int """ - Merge requests merged after this date + Merge requests merged after this date. """ mergedAfter: Time """ - Merge requests merged before this date + Merge requests merged before this date. """ mergedBefore: Time """ - Title of the milestone + Title of the milestone. """ milestoneTitle: String @@ -24291,12 +25896,12 @@ type User { projectPath: String """ - Username of the reviewer + Username of the reviewer. """ reviewerUsername: String """ - Sort merge requests by this criteria + Sort merge requests by this criteria. """ sort: MergeRequestSort = created_desc @@ -24411,12 +26016,12 @@ type User { after: String """ - Username of the assignee + Username of the assignee. """ assigneeUsername: String """ - Username of the author + Username of the author. """ authorUsername: String @@ -24431,7 +26036,7 @@ type User { first: Int """ - Array of IIDs of merge requests, for example `[1, 2]` + Array of IIDs of merge requests, for example `[1, 2]`. """ iids: [String!] @@ -24446,17 +26051,17 @@ type User { last: Int """ - Merge requests merged after this date + Merge requests merged after this date. """ mergedAfter: Time """ - Merge requests merged before this date + Merge requests merged before this date. """ mergedBefore: Time """ - Title of the milestone + Title of the milestone. """ milestoneTitle: String @@ -24471,7 +26076,7 @@ type User { projectPath: String """ - Sort merge requests by this criteria + Sort merge requests by this criteria. """ sort: MergeRequestSort = created_desc @@ -24511,7 +26116,7 @@ type User { first: Int """ - Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1" + Array of global snippet ids, e.g., "gid://gitlab/ProjectSnippet/1". """ ids: [SnippetID!] @@ -24521,12 +26126,12 @@ type User { last: Int """ - The type of snippet + The type of snippet. """ type: TypeEnum """ - The visibility of the snippet + The visibility of the snippet. """ visibility: VisibilityScopesEnum ): SnippetConnection @@ -24556,7 +26161,7 @@ type User { last: Int """ - Search query + Search query. """ search: String ): ProjectConnection @@ -24576,7 +26181,7 @@ type User { """ todos( """ - The action to be filtered + The action to be filtered. """ action: [TodoActionEnum!] @@ -24586,7 +26191,7 @@ type User { after: String """ - The ID of an author + The ID of an author. """ authorId: [ID!] @@ -24601,7 +26206,7 @@ type User { first: Int """ - The ID of a group + The ID of a group. """ groupId: [ID!] @@ -24611,17 +26216,17 @@ type User { last: Int """ - The ID of a project + The ID of a project. """ projectId: [ID!] """ - The state of the todo + The state of the todo. """ state: [TodoStateEnum!] """ - The type of the todo + The type of the todo. """ type: [TodoTargetEnum!] ): TodoConnection! @@ -24898,6 +26503,11 @@ type Vulnerability implements Noteable { confirmedAt: Time """ + The user that confirmed the vulnerability. + """ + confirmedBy: User + + """ Description of the vulnerability """ description: String @@ -24938,6 +26548,11 @@ type Vulnerability implements Noteable { dismissedAt: Time """ + The user that dismissed the vulnerability. + """ + dismissedBy: User + + """ List of external issue links related to the vulnerability """ externalIssueLinks( @@ -25002,7 +26617,7 @@ type Vulnerability implements Noteable { last: Int """ - Filter issue links by link type + Filter issue links by link type. """ linkType: VulnerabilityIssueLinkType ): VulnerabilityIssueLinkConnection! @@ -25065,6 +26680,11 @@ type Vulnerability implements Noteable { resolvedAt: Time """ + The user that resolved the vulnerability. + """ + resolvedBy: User + + """ Indicates whether the vulnerability is fixed on the default branch or not """ resolvedOnDefaultBranch: Boolean! @@ -25115,7 +26735,7 @@ input VulnerabilityConfirmInput { clientMutationId: String """ - ID of the vulnerability to be confirmed + ID of the vulnerability to be confirmed. """ id: VulnerabilityID! } @@ -25135,7 +26755,7 @@ type VulnerabilityConfirmPayload { errors: [String!]! """ - The vulnerability after state change + The vulnerability after state change. """ vulnerability: Vulnerability } @@ -25170,12 +26790,17 @@ input VulnerabilityDismissInput { clientMutationId: String """ - Reason why vulnerability should be dismissed + Comment why vulnerability should be dismissed. """ comment: String """ - ID of the vulnerability to be dismissed + Reason why vulnerability should be dismissed. + """ + dismissalReason: VulnerabilityDismissalReason + + """ + ID of the vulnerability to be dismissed. """ id: VulnerabilityID! } @@ -25195,12 +26820,42 @@ type VulnerabilityDismissPayload { errors: [String!]! """ - The vulnerability after dismissal + The vulnerability after dismissal. """ vulnerability: Vulnerability } """ +The dismissal reason of the Vulnerability +""" +enum VulnerabilityDismissalReason { + """ + The likelihood of the Vulnerability occurring and its impact are deemed acceptable + """ + ACCEPTABLE_RISK + + """ + The Vulnerability was incorrectly identified as being present + """ + FALSE_POSITIVE + + """ + There is a mitigating control that eliminates the Vulnerability or makes its risk acceptable + """ + MITIGATING_CONTROL + + """ + Other reasons for dismissal + """ + NOT_APPLICABLE + + """ + The Vulnerability is used in tests and does not pose an actual risk + """ + USED_IN_TESTS +} + +""" An edge in a connection. """ type VulnerabilityEdge { @@ -25697,7 +27352,7 @@ input VulnerabilityResolveInput { clientMutationId: String """ - ID of the vulnerability to be resolved + ID of the vulnerability to be resolved. """ id: VulnerabilityID! } @@ -25717,7 +27372,7 @@ type VulnerabilityResolvePayload { errors: [String!]! """ - The vulnerability after state change + The vulnerability after state change. """ vulnerability: Vulnerability } @@ -25732,7 +27387,7 @@ input VulnerabilityRevertToDetectedInput { clientMutationId: String """ - ID of the vulnerability to be reverted + ID of the vulnerability to be reverted. """ id: VulnerabilityID! } @@ -25752,7 +27407,7 @@ type VulnerabilityRevertToDetectedPayload { errors: [String!]! """ - The vulnerability after revert + The vulnerability after revert. """ vulnerability: Vulnerability } diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json index 3494e0c8300..138530abb17 100644 --- a/doc/api/graphql/reference/gitlab_schema.json +++ b/doc/api/graphql/reference/gitlab_schema.json @@ -105,7 +105,7 @@ "inputFields": [ { "name": "awardableId", - "description": "The global ID of the awardable resource", + "description": "The global ID of the awardable resource.", "type": { "kind": "NON_NULL", "name": null, @@ -153,7 +153,7 @@ "fields": [ { "name": "awardEmoji", - "description": "The award emoji after mutation", + "description": "The award emoji after mutation.", "args": [ ], @@ -221,7 +221,7 @@ "inputFields": [ { "name": "id", - "description": "ID of the project to be added to Instance Security Dashboard", + "description": "ID of the project to be added to Instance Security Dashboard.", "type": { "kind": "NON_NULL", "name": null, @@ -295,7 +295,7 @@ }, { "name": "project", - "description": "Project that was added to the Instance Security Dashboard", + "description": "Project that was added to the Instance Security Dashboard.", "args": [ ], @@ -372,6 +372,16 @@ "defaultValue": null }, { + "name": "remoteIp", + "description": "Delete jobs matching remote_ip in the context metadata", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { "name": "relatedClass", "description": "Delete jobs matching related_class in the context metadata", "type": { @@ -393,7 +403,7 @@ }, { "name": "queueName", - "description": "The name of the queue to delete jobs from", + "description": "The name of the queue to delete jobs from.", "type": { "kind": "NON_NULL", "name": null, @@ -467,7 +477,7 @@ }, { "name": "result", - "description": "Information about the status of the deletion request", + "description": "Information about the status of the deletion request.", "args": [ ], @@ -947,7 +957,7 @@ "args": [ { "name": "action", - "description": "The action to be filtered", + "description": "The action to be filtered.", "type": { "kind": "LIST", "name": null, @@ -965,7 +975,7 @@ }, { "name": "authorId", - "description": "The ID of an author", + "description": "The ID of an author.", "type": { "kind": "LIST", "name": null, @@ -983,7 +993,7 @@ }, { "name": "projectId", - "description": "The ID of a project", + "description": "The ID of a project.", "type": { "kind": "LIST", "name": null, @@ -1001,7 +1011,7 @@ }, { "name": "groupId", - "description": "The ID of a group", + "description": "The ID of a group.", "type": { "kind": "LIST", "name": null, @@ -1019,7 +1029,7 @@ }, { "name": "state", - "description": "The state of the todo", + "description": "The state of the todo.", "type": { "kind": "LIST", "name": null, @@ -1037,7 +1047,7 @@ }, { "name": "type", - "description": "The type of the todo", + "description": "The type of the todo.", "type": { "kind": "LIST", "name": null, @@ -1490,7 +1500,7 @@ "enumValues": [ { "name": "operations", - "description": "Alerts for operations domain ", + "description": "Alerts for operations domain", "isDeprecated": false, "deprecationReason": null }, @@ -1900,6 +1910,177 @@ "possibleTypes": null }, { + "kind": "INPUT_OBJECT", + "name": "AlertManagementPayloadAlertFieldInput", + "description": "Field that are available while modifying the custom mapping attributes for an HTTP integration", + "fields": null, + "inputFields": [ + { + "name": "fieldName", + "description": "A GitLab alert field name.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "AlertManagementPayloadAlertFieldName", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "path", + "description": "Path to value inside payload JSON.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "defaultValue": null + }, + { + "name": "label", + "description": "Human-readable label of the payload path.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "type", + "description": "Type of the parsed value.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "AlertManagementPayloadAlertFieldType", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "AlertManagementPayloadAlertFieldName", + "description": "Values for alert field names used in the custom mapping", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "TITLE", + "description": "The title of the incident.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "DESCRIPTION", + "description": "A high-level summary of the problem.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "START_TIME", + "description": "The time of the incident.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "END_TIME", + "description": "The resolved time of the incident.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SERVICE", + "description": "The affected service.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "MONITORING_TOOL", + "description": "The name of the associated monitoring tool.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "HOSTS", + "description": "One or more hosts, as to where this incident occurred.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "SEVERITY", + "description": "The severity of the alert.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "FINGERPRINT", + "description": "The unique identifier of the alert. This can be used to group occurrences of the same alert.", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "GITLAB_ENVIRONMENT_NAME", + "description": "The name of the associated GitLab environment.", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "AlertManagementPayloadAlertFieldType", + "description": "Values for alert field types used in the custom mapping", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "ARRAY", + "description": "Array field type", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "DATETIME", + "description": "DateTime field type", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "STRING", + "description": "String field type", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { "kind": "OBJECT", "name": "AlertManagementPrometheusIntegration", "description": "An endpoint and credentials used to accept Prometheus alerts for a project", @@ -2112,7 +2293,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the alert to mutate is in", + "description": "The project the alert to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -2126,7 +2307,7 @@ }, { "name": "iid", - "description": "The IID of the alert to mutate", + "description": "The IID of the alert to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -2192,7 +2373,7 @@ "fields": [ { "name": "alert", - "description": "The alert after mutation", + "description": "The alert after mutation.", "args": [ ], @@ -2246,7 +2427,7 @@ }, { "name": "issue", - "description": "The issue created after mutation", + "description": "The issue created after mutation.", "args": [ ], @@ -2260,7 +2441,7 @@ }, { "name": "todo", - "description": "The todo after mutation", + "description": "The todo after mutation.", "args": [ ], @@ -2288,7 +2469,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the alert to mutate is in", + "description": "The project the alert to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -2302,7 +2483,7 @@ }, { "name": "iid", - "description": "The IID of the alert to mutate", + "description": "The IID of the alert to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -2336,7 +2517,7 @@ "fields": [ { "name": "alert", - "description": "The alert after mutation", + "description": "The alert after mutation.", "args": [ ], @@ -2390,7 +2571,7 @@ }, { "name": "issue", - "description": "The issue created after mutation", + "description": "The issue created after mutation.", "args": [ ], @@ -2404,7 +2585,7 @@ }, { "name": "todo", - "description": "The todo after mutation", + "description": "The todo after mutation.", "args": [ ], @@ -2586,7 +2767,7 @@ "inputFields": [ { "name": "awardableId", - "description": "The global ID of the awardable resource", + "description": "The global ID of the awardable resource.", "type": { "kind": "NON_NULL", "name": null, @@ -2634,7 +2815,7 @@ "fields": [ { "name": "awardEmoji", - "description": "The award emoji after mutation", + "description": "The award emoji after mutation.", "args": [ ], @@ -2702,7 +2883,7 @@ "inputFields": [ { "name": "awardableId", - "description": "The global ID of the awardable resource", + "description": "The global ID of the awardable resource.", "type": { "kind": "NON_NULL", "name": null, @@ -2750,7 +2931,7 @@ "fields": [ { "name": "awardEmoji", - "description": "The award emoji after mutation", + "description": "The award emoji after mutation.", "args": [ ], @@ -2818,7 +2999,7 @@ "inputFields": [ { "name": "awardableId", - "description": "The global ID of the awardable resource", + "description": "The global ID of the awardable resource.", "type": { "kind": "NON_NULL", "name": null, @@ -2866,7 +3047,7 @@ "fields": [ { "name": "awardEmoji", - "description": "The award emoji after mutation", + "description": "The award emoji after mutation.", "args": [ ], @@ -3356,7 +3537,7 @@ "args": [ { "name": "issueFilters", - "description": "Filters applied when selecting issues on the board", + "description": "Filters applied when selecting issues on the board.", "type": { "kind": "INPUT_OBJECT", "name": "BoardIssueInput", @@ -3532,7 +3713,7 @@ "args": [ { "name": "id", - "description": "Find a list by its global ID", + "description": "Find a list by its global ID.", "type": { "kind": "SCALAR", "name": "ListID", @@ -3542,7 +3723,7 @@ }, { "name": "issueFilters", - "description": "Filters applied when getting issue metadata in the board list", + "description": "Filters applied when getting issue metadata in the board list.", "type": { "kind": "INPUT_OBJECT", "name": "BoardIssueInput", @@ -3628,6 +3809,42 @@ "deprecationReason": null }, { + "name": "webPath", + "description": "Web path of the board.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "webUrl", + "description": "Web URL of the board.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "weight", "description": "Weight of the board", "args": [ @@ -3810,7 +4027,7 @@ }, { "name": "timeframe", - "description": "List items overlapping the given timeframe", + "description": "List items overlapping the given timeframe.", "type": { "kind": "INPUT_OBJECT", "name": "Timeframe", @@ -3820,7 +4037,7 @@ }, { "name": "iid", - "description": "IID of the epic, e.g., \"1\"", + "description": "IID of the epic, e.g., \"1\".", "type": { "kind": "SCALAR", "name": "ID", @@ -3830,7 +4047,7 @@ }, { "name": "iids", - "description": "List of IIDs of epics, e.g., [1, 2]", + "description": "List of IIDs of epics, e.g., [1, 2].", "type": { "kind": "LIST", "name": null, @@ -3848,7 +4065,7 @@ }, { "name": "state", - "description": "Filter epics by state", + "description": "Filter epics by state.", "type": { "kind": "ENUM", "name": "EpicState", @@ -3858,7 +4075,7 @@ }, { "name": "search", - "description": "Search query for epic title or description", + "description": "Search query for epic title or description.", "type": { "kind": "SCALAR", "name": "String", @@ -3868,7 +4085,7 @@ }, { "name": "sort", - "description": "List epics by sort order", + "description": "List epics by sort order.", "type": { "kind": "ENUM", "name": "EpicSort", @@ -3878,7 +4095,7 @@ }, { "name": "authorUsername", - "description": "Filter epics by author", + "description": "Filter epics by author.", "type": { "kind": "SCALAR", "name": "String", @@ -3888,7 +4105,7 @@ }, { "name": "labelName", - "description": "Filter epics by labels", + "description": "Filter epics by labels.", "type": { "kind": "LIST", "name": null, @@ -3906,7 +4123,7 @@ }, { "name": "milestoneTitle", - "description": "Filter epics by milestone title, computed from epic's issues", + "description": "Filter epics by milestone title, computed from epic's issues.", "type": { "kind": "SCALAR", "name": "String", @@ -3916,7 +4133,7 @@ }, { "name": "iidStartsWith", - "description": "Filter epics by IID for autocomplete", + "description": "Filter epics by IID for autocomplete.", "type": { "kind": "SCALAR", "name": "String", @@ -3926,7 +4143,7 @@ }, { "name": "includeDescendantGroups", - "description": "Include epics from descendant groups", + "description": "Include epics from descendant groups.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -3935,6 +4152,16 @@ "defaultValue": "true" }, { + "name": "confidential", + "description": "Filter epics by given confidentiality.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", "type": { @@ -5290,7 +5517,7 @@ "args": [ { "name": "filters", - "description": "Filters applied when selecting issues in the board list", + "description": "Filters applied when selecting issues in the board list.", "type": { "kind": "INPUT_OBJECT", "name": "BoardIssueInput", @@ -5362,6 +5589,20 @@ "deprecationReason": null }, { + "name": "iteration", + "description": "Iteration of the list", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Iteration", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "label", "description": "Label of the list", "args": [ @@ -5578,7 +5819,7 @@ "inputFields": [ { "name": "boardId", - "description": "Global ID of the issue board to mutate", + "description": "Global ID of the issue board to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -5592,7 +5833,7 @@ }, { "name": "backlog", - "description": "Create the backlog list", + "description": "Create the backlog list.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -5602,7 +5843,7 @@ }, { "name": "labelId", - "description": "Global ID of an existing label", + "description": "Global ID of an existing label.", "type": { "kind": "SCALAR", "name": "LabelID", @@ -5612,7 +5853,7 @@ }, { "name": "milestoneId", - "description": "Global ID of an existing milestone", + "description": "Global ID of an existing milestone.", "type": { "kind": "SCALAR", "name": "MilestoneID", @@ -5622,7 +5863,7 @@ }, { "name": "iterationId", - "description": "Global ID of an existing iteration", + "description": "Global ID of an existing iteration.", "type": { "kind": "SCALAR", "name": "IterationID", @@ -5632,7 +5873,7 @@ }, { "name": "assigneeId", - "description": "Global ID of an existing user", + "description": "Global ID of an existing user.", "type": { "kind": "SCALAR", "name": "UserID", @@ -5702,7 +5943,7 @@ }, { "name": "list", - "description": "List of the issue board", + "description": "List of the issue board.", "args": [ ], @@ -5879,7 +6120,7 @@ }, { "name": "list", - "description": "The updated list", + "description": "The updated list.", "args": [ ], @@ -5911,6 +6152,16 @@ }, { "kind": "SCALAR", + "name": "BoardsEpicListID", + "description": "Identifier of Boards::EpicList", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", "name": "Boolean", "description": "Represents `true` or `false` values.", "fields": null, @@ -6069,6 +6320,243 @@ }, { "kind": "OBJECT", + "name": "CiBuildNeed", + "description": null, + "fields": [ + { + "name": "name", + "description": "Name of the job we need to complete.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiBuildNeedConnection", + "description": "The connection type for CiBuildNeed.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CiBuildNeedEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CiBuildNeed", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiBuildNeedEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "CiBuildNeed", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "CiCdSettingsUpdateInput", + "description": "Autogenerated input type of CiCdSettingsUpdate", + "fields": null, + "inputFields": [ + { + "name": "fullPath", + "description": "Full Path of the project the settings belong to.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "keepLatestArtifact", + "description": "Indicates if the latest artifact should be kept for this project.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiCdSettingsUpdatePayload", + "description": "Autogenerated return type of CiCdSettingsUpdate", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", "name": "CiConfig", "description": null, "fields": [ @@ -6112,20 +6600,51 @@ "name": "stages", "description": "Stages of the pipeline", "args": [ - - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "CiConfigStage", + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", "ofType": null - } + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null } + ], + "type": { + "kind": "OBJECT", + "name": "CiConfigStageConnection", + "ofType": null }, "isDeprecated": false, "deprecationReason": null @@ -6161,20 +6680,51 @@ "name": "jobs", "description": "Jobs in group", "args": [ - - ], - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "CiConfigJob", + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", "ofType": null - } + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null } + ], + "type": { + "kind": "OBJECT", + "name": "CiConfigJobConnection", + "ofType": null }, "isDeprecated": false, "deprecationReason": null @@ -6217,12 +6767,210 @@ }, { "kind": "OBJECT", + "name": "CiConfigGroupConnection", + "description": "The connection type for CiConfigGroup.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CiConfigGroupEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CiConfigGroup", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiConfigGroupEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "CiConfigGroup", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", "name": "CiConfigJob", "description": null, "fields": [ { + "name": "afterScript", + "description": "Override a set of commands that are executed after the job.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "allowFailure", + "description": "Allow job to fail.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "beforeScript", + "description": "Override a set of commands that are executed before the job.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "environment", + "description": "Name of an environment to which the job deploys.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "except", + "description": "Limit when jobs are not created.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "CiConfigJobRestriction", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "groupName", - "description": "Name of the job group", + "description": "Name of the job group.", "args": [ ], @@ -6236,7 +6984,7 @@ }, { "name": "name", - "description": "Name of the job", + "description": "Name of the job.", "args": [ ], @@ -6250,7 +6998,74 @@ }, { "name": "needs", - "description": "Builds that must complete before the jobs run", + "description": "Builds that must complete before the jobs run.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "CiConfigNeedConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "only", + "description": "Jobs are created when these conditions do not apply.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "CiConfigJobRestriction", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "script", + "description": "Shell script that is executed by a runner.", "args": [ ], @@ -6261,8 +7076,8 @@ "kind": "NON_NULL", "name": null, "ofType": { - "kind": "OBJECT", - "name": "CiConfigNeed", + "kind": "SCALAR", + "name": "String", "ofType": null } } @@ -6272,7 +7087,43 @@ }, { "name": "stage", - "description": "Name of the job stage", + "description": "Name of the job stage.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tags", + "description": "List of tags that are used to select a runner.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "when", + "description": "When to run the job.", "args": [ ], @@ -6294,6 +7145,153 @@ }, { "kind": "OBJECT", + "name": "CiConfigJobConnection", + "description": "The connection type for CiConfigJob.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CiConfigJobEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CiConfigJob", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiConfigJobEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "CiConfigJob", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiConfigJobRestriction", + "description": null, + "fields": [ + { + "name": "refs", + "description": "The Git refs the job restriction applies to.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", "name": "CiConfigNeed", "description": null, "fields": [ @@ -6321,12 +7319,12 @@ }, { "kind": "OBJECT", - "name": "CiConfigStage", - "description": null, + "name": "CiConfigNeedConnection", + "description": "The connection type for CiConfigNeed.", "fields": [ { - "name": "groups", - "description": "Groups of jobs for the stage", + "name": "edges", + "description": "A list of edges.", "args": [ ], @@ -6334,14 +7332,157 @@ "kind": "LIST", "name": null, "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "OBJECT", - "name": "CiConfigGroup", + "kind": "OBJECT", + "name": "CiConfigNeedEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CiConfigNeed", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiConfigNeedEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "CiConfigNeed", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiConfigStage", + "description": null, + "fields": [ + { + "name": "groups", + "description": "Groups of jobs for the stage", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", "ofType": null - } + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null } + ], + "type": { + "kind": "OBJECT", + "name": "CiConfigGroupConnection", + "ofType": null }, "isDeprecated": false, "deprecationReason": null @@ -6369,6 +7510,118 @@ "possibleTypes": null }, { + "kind": "OBJECT", + "name": "CiConfigStageConnection", + "description": "The connection type for CiConfigStage.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CiConfigStageEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "CiConfigStage", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "CiConfigStageEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "CiConfigStage", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { "kind": "ENUM", "name": "CiConfigStatus", "description": "Values for YAML processor result", @@ -6699,7 +7952,7 @@ }, { "name": "needs", - "description": "Builds that must complete before the jobs run", + "description": "References to builds that must complete before the jobs run", "args": [ { "name": "after", @@ -6744,7 +7997,7 @@ ], "type": { "kind": "OBJECT", - "name": "CiJobConnection", + "name": "CiBuildNeedConnection", "ofType": null }, "isDeprecated": false, @@ -7500,7 +8753,7 @@ "inputFields": [ { "name": "id", - "description": "Global ID of the cluster agent that will be deleted", + "description": "Global ID of the cluster agent that will be deleted.", "type": { "kind": "NON_NULL", "name": null, @@ -7777,7 +9030,7 @@ "inputFields": [ { "name": "clusterAgentId", - "description": "Global ID of the cluster agent that will be associated with the new token", + "description": "Global ID of the cluster agent that will be associated with the new token.", "type": { "kind": "NON_NULL", "name": null, @@ -7851,7 +9104,7 @@ }, { "name": "secret", - "description": "Token secret value. Make sure you save it - you won't be able to access it again", + "description": "Token secret value. Make sure you save it - you won't be able to access it again.", "args": [ ], @@ -7865,7 +9118,7 @@ }, { "name": "token", - "description": "Token created after mutation", + "description": "Token created after mutation.", "args": [ ], @@ -7893,7 +9146,7 @@ "inputFields": [ { "name": "id", - "description": "Global ID of the cluster agent token that will be deleted", + "description": "Global ID of the cluster agent token that will be deleted.", "type": { "kind": "NON_NULL", "name": null, @@ -8415,7 +9668,7 @@ "args": [ { "name": "status", - "description": "Filter pipelines by their status", + "description": "Filter pipelines by their status.", "type": { "kind": "ENUM", "name": "PipelineStatusEnum", @@ -8425,7 +9678,7 @@ }, { "name": "ref", - "description": "Filter pipelines by the ref they are run for", + "description": "Filter pipelines by the ref they are run for.", "type": { "kind": "SCALAR", "name": "String", @@ -8435,7 +9688,7 @@ }, { "name": "sha", - "description": "Filter pipelines by the sha of the commit they are run for", + "description": "Filter pipelines by the sha of the commit they are run for.", "type": { "kind": "SCALAR", "name": "String", @@ -8819,7 +10072,7 @@ "inputFields": [ { "name": "projectPath", - "description": "Project full path the branch is associated with", + "description": "Project full path the branch is associated with.", "type": { "kind": "NON_NULL", "name": null, @@ -8833,7 +10086,7 @@ }, { "name": "branch", - "description": "Name of the branch to commit into, it can be a new branch", + "description": "Name of the branch to commit into, it can be a new branch.", "type": { "kind": "NON_NULL", "name": null, @@ -8847,7 +10100,7 @@ }, { "name": "startBranch", - "description": "If on a new branch, name of the original branch", + "description": "If on a new branch, name of the original branch.", "type": { "kind": "SCALAR", "name": "String", @@ -8871,7 +10124,7 @@ }, { "name": "actions", - "description": "Array of action hashes to commit as a batch", + "description": "Array of action hashes to commit as a batch.", "type": { "kind": "NON_NULL", "name": null, @@ -8927,7 +10180,7 @@ }, { "name": "commit", - "description": "The commit after mutation", + "description": "The commit after mutation.", "args": [ ], @@ -9239,6 +10492,47 @@ "possibleTypes": null }, { + "kind": "INPUT_OBJECT", + "name": "ComplianceFrameworkInput", + "description": null, + "fields": null, + "inputFields": [ + { + "name": "name", + "description": "New name for the compliance framework.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "description", + "description": "New description for the compliance framework.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "color", + "description": "New color representation of the compliance framework in hex format. e.g. #FCA121.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { "kind": "SCALAR", "name": "ComplianceManagementFrameworkID", "description": "Identifier of ComplianceManagement::Framework", @@ -9256,7 +10550,7 @@ "inputFields": [ { "name": "projectPath", - "description": "Full path of the project", + "description": "Full path of the project.", "type": { "kind": "NON_NULL", "name": null, @@ -9270,7 +10564,7 @@ }, { "name": "configuration", - "description": "SAST CI configuration for the project", + "description": "SAST CI configuration for the project.", "type": { "kind": "NON_NULL", "name": null, @@ -9344,7 +10638,7 @@ }, { "name": "status", - "description": "Status of creating the commit for the supplied SAST CI configuration", + "description": "Status of creating the commit for the supplied SAST CI configuration.", "args": [ ], @@ -9362,7 +10656,7 @@ }, { "name": "successPath", - "description": "Redirect path to use when the response is successful", + "description": "Redirect path to use when the response is successful.", "args": [ ], @@ -10602,7 +11896,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the alert to mutate is in", + "description": "The project the alert to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -10616,7 +11910,7 @@ }, { "name": "iid", - "description": "The IID of the alert to mutate", + "description": "The IID of the alert to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -10650,7 +11944,7 @@ "fields": [ { "name": "alert", - "description": "The alert after mutation", + "description": "The alert after mutation.", "args": [ ], @@ -10704,7 +11998,7 @@ }, { "name": "issue", - "description": "The issue created after mutation", + "description": "The issue created after mutation.", "args": [ ], @@ -10718,7 +12012,7 @@ }, { "name": "todo", - "description": "The todo after mutation", + "description": "The todo after mutation.", "args": [ ], @@ -10746,7 +12040,7 @@ "inputFields": [ { "name": "environmentId", - "description": "The global ID of the environment to add an annotation to", + "description": "The global ID of the environment to add an annotation to.", "type": { "kind": "SCALAR", "name": "EnvironmentID", @@ -10756,7 +12050,7 @@ }, { "name": "clusterId", - "description": "The global ID of the cluster to add an annotation to", + "description": "The global ID of the cluster to add an annotation to.", "type": { "kind": "SCALAR", "name": "ClustersClusterID", @@ -10766,7 +12060,7 @@ }, { "name": "startingAt", - "description": "Timestamp indicating starting moment to which the annotation relates", + "description": "Timestamp indicating starting moment to which the annotation relates.", "type": { "kind": "NON_NULL", "name": null, @@ -10780,7 +12074,7 @@ }, { "name": "endingAt", - "description": "Timestamp indicating ending moment to which the annotation relates", + "description": "Timestamp indicating ending moment to which the annotation relates.", "type": { "kind": "SCALAR", "name": "Time", @@ -10790,7 +12084,7 @@ }, { "name": "dashboardPath", - "description": "The path to a file defining the dashboard on which the annotation should be added", + "description": "The path to a file defining the dashboard on which the annotation should be added.", "type": { "kind": "NON_NULL", "name": null, @@ -10804,7 +12098,7 @@ }, { "name": "description", - "description": "The description of the annotation", + "description": "The description of the annotation.", "type": { "kind": "NON_NULL", "name": null, @@ -10838,7 +12132,7 @@ "fields": [ { "name": "annotation", - "description": "The created annotation", + "description": "The created annotation.", "args": [ ], @@ -10906,7 +12200,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project full path the resource is associated with", + "description": "The project full path the resource is associated with.", "type": { "kind": "SCALAR", "name": "ID", @@ -10916,7 +12210,7 @@ }, { "name": "groupPath", - "description": "The group full path the resource is associated with", + "description": "The group full path the resource is associated with.", "type": { "kind": "SCALAR", "name": "ID", @@ -10955,6 +12249,82 @@ "defaultValue": null }, { + "name": "assigneeId", + "description": "The ID of user to be assigned to the board.", + "type": { + "kind": "SCALAR", + "name": "UserID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "milestoneId", + "description": "The ID of milestone to be assigned to the board.", + "type": { + "kind": "SCALAR", + "name": "MilestoneID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iterationId", + "description": "The ID of iteration to be assigned to the board.", + "type": { + "kind": "SCALAR", + "name": "IterationID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "weight", + "description": "The weight value to be assigned to the board.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "labels", + "description": "Labels of the issue", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "labelIds", + "description": "The IDs of labels to be added to the board.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "LabelID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", "type": { @@ -11044,7 +12414,7 @@ "inputFields": [ { "name": "projectPath", - "description": "Project full path the branch is associated with", + "description": "Project full path the branch is associated with.", "type": { "kind": "NON_NULL", "name": null, @@ -11058,7 +12428,7 @@ }, { "name": "name", - "description": "Name of the branch", + "description": "Name of the branch.", "type": { "kind": "NON_NULL", "name": null, @@ -11072,7 +12442,7 @@ }, { "name": "ref", - "description": "Branch name or commit SHA to create branch from", + "description": "Branch name or commit SHA to create branch from.", "type": { "kind": "NON_NULL", "name": null, @@ -11106,7 +12476,7 @@ "fields": [ { "name": "branch", - "description": "Branch after mutation", + "description": "Branch after mutation.", "args": [ ], @@ -11174,7 +12544,7 @@ "inputFields": [ { "name": "projectPath", - "description": "Full path of the associated project for this cluster agent", + "description": "Full path of the associated project for this cluster agent.", "type": { "kind": "NON_NULL", "name": null, @@ -11188,7 +12558,7 @@ }, { "name": "name", - "description": "Name of the cluster agent", + "description": "Name of the cluster agent.", "type": { "kind": "NON_NULL", "name": null, @@ -11236,7 +12606,7 @@ }, { "name": "clusterAgent", - "description": "Cluster agent created after mutation", + "description": "Cluster agent created after mutation.", "args": [ ], @@ -11303,42 +12673,14 @@ "defaultValue": null }, { - "name": "name", - "description": "Name of the compliance framework.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "description", - "description": "Description of the compliance framework.", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - }, - { - "name": "color", - "description": "Color to represent the compliance framework as a hexadecimal value. e.g. #ABC123.", + "name": "params", + "description": "Parameters to update the compliance framework with.", "type": { "kind": "NON_NULL", "name": null, "ofType": { - "kind": "SCALAR", - "name": "String", + "kind": "INPUT_OBJECT", + "name": "ComplianceFrameworkInput", "ofType": null } }, @@ -11434,7 +12776,7 @@ "inputFields": [ { "name": "groupPath", - "description": "Namespace full path the emoji is associated with", + "description": "Namespace full path the emoji is associated with.", "type": { "kind": "NON_NULL", "name": null, @@ -11448,7 +12790,7 @@ }, { "name": "name", - "description": "Name of the emoji", + "description": "Name of the emoji.", "type": { "kind": "NON_NULL", "name": null, @@ -11462,7 +12804,7 @@ }, { "name": "url", - "description": "Location of the emoji file", + "description": "Location of the emoji file.", "type": { "kind": "NON_NULL", "name": null, @@ -11510,7 +12852,7 @@ }, { "name": "customEmoji", - "description": "The new custom emoji", + "description": "The new custom emoji.", "args": [ ], @@ -11564,7 +12906,7 @@ "inputFields": [ { "name": "name", - "description": "Name of the segment", + "description": "Name of the segment.", "type": { "kind": "NON_NULL", "name": null, @@ -11578,7 +12920,7 @@ }, { "name": "groupIds", - "description": "The array of group IDs to set for the segment", + "description": "The array of group IDs to set for the segment.", "type": { "kind": "LIST", "name": null, @@ -11656,7 +12998,7 @@ }, { "name": "segment", - "description": "The segment after mutation", + "description": "The segment after mutation.", "args": [ ], @@ -11684,7 +13026,7 @@ "inputFields": [ { "name": "noteableId", - "description": "The global ID of the resource to add a note to", + "description": "The global ID of the resource to add a note to.", "type": { "kind": "NON_NULL", "name": null, @@ -11796,7 +13138,7 @@ }, { "name": "note", - "description": "The note after mutation", + "description": "The note after mutation.", "args": [ ], @@ -11824,7 +13166,7 @@ "inputFields": [ { "name": "groupPath", - "description": "The group the epic to mutate is in", + "description": "The group the epic to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -11838,7 +13180,7 @@ }, { "name": "title", - "description": "The title of the epic", + "description": "The title of the epic.", "type": { "kind": "SCALAR", "name": "String", @@ -11848,7 +13190,7 @@ }, { "name": "description", - "description": "The description of the epic", + "description": "The description of the epic.", "type": { "kind": "SCALAR", "name": "String", @@ -11858,7 +13200,7 @@ }, { "name": "confidential", - "description": "Indicates if the epic is confidential", + "description": "Indicates if the epic is confidential.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -11868,7 +13210,7 @@ }, { "name": "startDateFixed", - "description": "The start date of the epic", + "description": "The start date of the epic.", "type": { "kind": "SCALAR", "name": "String", @@ -11878,7 +13220,7 @@ }, { "name": "dueDateFixed", - "description": "The end date of the epic", + "description": "The end date of the epic.", "type": { "kind": "SCALAR", "name": "String", @@ -11888,7 +13230,7 @@ }, { "name": "startDateIsFixed", - "description": "Indicates start date should be sourced from start_date_fixed field not the issue milestones", + "description": "Indicates start date should be sourced from start_date_fixed field not the issue milestones.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -11898,7 +13240,7 @@ }, { "name": "dueDateIsFixed", - "description": "Indicates end date should be sourced from due_date_fixed field not the issue milestones", + "description": "Indicates end date should be sourced from due_date_fixed field not the issue milestones.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -11978,7 +13320,7 @@ }, { "name": "epic", - "description": "The created epic", + "description": "The created epic.", "args": [ ], @@ -12032,7 +13374,7 @@ "inputFields": [ { "name": "noteableId", - "description": "The global ID of the resource to add a note to", + "description": "The global ID of the resource to add a note to.", "type": { "kind": "NON_NULL", "name": null, @@ -12144,7 +13486,7 @@ }, { "name": "note", - "description": "The note after mutation", + "description": "The note after mutation.", "args": [ ], @@ -12212,7 +13554,7 @@ }, { "name": "projectPath", - "description": "Project full path the issue is associated with", + "description": "Project full path the issue is associated with.", "type": { "kind": "NON_NULL", "name": null, @@ -12226,7 +13568,7 @@ }, { "name": "iid", - "description": "The IID (internal ID) of a project issue. Only admins and project owners can modify", + "description": "The IID (internal ID) of a project issue. Only admins and project owners can modify.", "type": { "kind": "SCALAR", "name": "Int", @@ -12250,7 +13592,7 @@ }, { "name": "milestoneId", - "description": "The ID of the milestone to assign to the issue. On update milestone will be removed if set to null", + "description": "The ID of the milestone to assign to the issue. On update milestone will be removed if set to null.", "type": { "kind": "SCALAR", "name": "MilestoneID", @@ -12278,7 +13620,7 @@ }, { "name": "labelIds", - "description": "The IDs of labels to be added to the issue", + "description": "The IDs of labels to be added to the issue.", "type": { "kind": "LIST", "name": null, @@ -12296,7 +13638,7 @@ }, { "name": "createdAt", - "description": "Timestamp when the issue was created. Available only for admins and project owners", + "description": "Timestamp when the issue was created. Available only for admins and project owners.", "type": { "kind": "SCALAR", "name": "Time", @@ -12306,7 +13648,7 @@ }, { "name": "mergeRequestToResolveDiscussionsOf", - "description": "The IID of a merge request for which to resolve discussions", + "description": "The IID of a merge request for which to resolve discussions.", "type": { "kind": "SCALAR", "name": "MergeRequestID", @@ -12316,7 +13658,7 @@ }, { "name": "discussionToResolve", - "description": "The ID of a discussion to resolve. Also pass `merge_request_to_resolve_discussions_of`", + "description": "The ID of a discussion to resolve. Also pass `merge_request_to_resolve_discussions_of`.", "type": { "kind": "SCALAR", "name": "String", @@ -12326,7 +13668,7 @@ }, { "name": "assigneeIds", - "description": "The array of user IDs to assign to the issue", + "description": "The array of user IDs to assign to the issue.", "type": { "kind": "LIST", "name": null, @@ -12344,7 +13686,7 @@ }, { "name": "healthStatus", - "description": "The desired health status", + "description": "The desired health status.", "type": { "kind": "ENUM", "name": "HealthStatus", @@ -12354,7 +13696,7 @@ }, { "name": "weight", - "description": "The weight of the issue", + "description": "The weight of the issue.", "type": { "kind": "SCALAR", "name": "Int", @@ -12364,7 +13706,7 @@ }, { "name": "epicId", - "description": "The ID of an epic to associate the issue with", + "description": "The ID of an epic to associate the issue with.", "type": { "kind": "SCALAR", "name": "EpicID", @@ -12434,7 +13776,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -12462,7 +13804,7 @@ "inputFields": [ { "name": "groupPath", - "description": "The target group for the iteration", + "description": "The target group for the iteration.", "type": { "kind": "SCALAR", "name": "ID", @@ -12472,7 +13814,7 @@ }, { "name": "projectPath", - "description": "The target project for the iteration", + "description": "The target project for the iteration.", "type": { "kind": "SCALAR", "name": "ID", @@ -12482,7 +13824,7 @@ }, { "name": "title", - "description": "The title of the iteration", + "description": "The title of the iteration.", "type": { "kind": "SCALAR", "name": "String", @@ -12492,7 +13834,7 @@ }, { "name": "description", - "description": "The description of the iteration", + "description": "The description of the iteration.", "type": { "kind": "SCALAR", "name": "String", @@ -12502,7 +13844,7 @@ }, { "name": "startDate", - "description": "The start date of the iteration", + "description": "The start date of the iteration.", "type": { "kind": "SCALAR", "name": "String", @@ -12512,7 +13854,7 @@ }, { "name": "dueDate", - "description": "The end date of the iteration", + "description": "The end date of the iteration.", "type": { "kind": "SCALAR", "name": "String", @@ -12582,7 +13924,7 @@ }, { "name": "iteration", - "description": "The created iteration", + "description": "The created iteration.", "args": [ ], @@ -12610,7 +13952,7 @@ "inputFields": [ { "name": "noteableId", - "description": "The global ID of the resource to add a note to", + "description": "The global ID of the resource to add a note to.", "type": { "kind": "NON_NULL", "name": null, @@ -12648,7 +13990,7 @@ }, { "name": "discussionId", - "description": "The global ID of the discussion this note is in reply to", + "description": "The global ID of the discussion this note is in reply to.", "type": { "kind": "SCALAR", "name": "DiscussionID", @@ -12718,7 +14060,7 @@ }, { "name": "note", - "description": "The note after mutation", + "description": "The note after mutation.", "args": [ ], @@ -12746,7 +14088,7 @@ "inputFields": [ { "name": "title", - "description": "Title of the requirement", + "description": "Title of the requirement.", "type": { "kind": "SCALAR", "name": "String", @@ -12756,7 +14098,7 @@ }, { "name": "description", - "description": "Description of the requirement", + "description": "Description of the requirement.", "type": { "kind": "SCALAR", "name": "String", @@ -12766,7 +14108,7 @@ }, { "name": "projectPath", - "description": "Full project path the requirement is associated with", + "description": "Full project path the requirement is associated with.", "type": { "kind": "NON_NULL", "name": null, @@ -12840,7 +14182,7 @@ }, { "name": "requirement", - "description": "Requirement after mutation", + "description": "Requirement after mutation.", "args": [ ], @@ -12868,7 +14210,7 @@ "inputFields": [ { "name": "title", - "description": "Title of the snippet", + "description": "Title of the snippet.", "type": { "kind": "NON_NULL", "name": null, @@ -12882,7 +14224,7 @@ }, { "name": "description", - "description": "Description of the snippet", + "description": "Description of the snippet.", "type": { "kind": "SCALAR", "name": "String", @@ -12892,7 +14234,7 @@ }, { "name": "visibilityLevel", - "description": "The visibility level of the snippet", + "description": "The visibility level of the snippet.", "type": { "kind": "NON_NULL", "name": null, @@ -12906,7 +14248,7 @@ }, { "name": "projectPath", - "description": "The project full path the snippet is associated with", + "description": "The project full path the snippet is associated with.", "type": { "kind": "SCALAR", "name": "ID", @@ -12916,7 +14258,7 @@ }, { "name": "uploadedFiles", - "description": "The paths to files uploaded in the snippet description", + "description": "The paths to files uploaded in the snippet description.", "type": { "kind": "LIST", "name": null, @@ -12934,7 +14276,7 @@ }, { "name": "blobActions", - "description": "Actions to perform over the snippet repository and blobs", + "description": "Actions to perform over the snippet repository and blobs.", "type": { "kind": "LIST", "name": null, @@ -13012,7 +14354,7 @@ }, { "name": "snippet", - "description": "The snippet after mutation", + "description": "The snippet after mutation.", "args": [ ], @@ -13026,7 +14368,7 @@ }, { "name": "spam", - "description": "Indicates whether the operation returns a record detected as spam", + "description": "Indicates whether the operation returns a record detected as spam.", "args": [ ], @@ -13054,7 +14396,7 @@ "inputFields": [ { "name": "title", - "description": "The test case title", + "description": "The test case title.", "type": { "kind": "NON_NULL", "name": null, @@ -13068,7 +14410,7 @@ }, { "name": "description", - "description": "The test case description", + "description": "The test case description.", "type": { "kind": "SCALAR", "name": "String", @@ -13096,7 +14438,7 @@ }, { "name": "projectPath", - "description": "The project full path to create the test case", + "description": "The project full path to create the test case.", "type": { "kind": "NON_NULL", "name": null, @@ -13170,7 +14512,7 @@ }, { "name": "testCase", - "description": "The test case created", + "description": "The test case created.", "args": [ ], @@ -15596,6 +16938,124 @@ "possibleTypes": null }, { + "kind": "ENUM", + "name": "DataVisualizationColorEnum", + "description": "Color of the data visualization palette", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "BLUE", + "description": "Blue color", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "ORANGE", + "description": "Orange color", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "AQUA", + "description": "Aqua color", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "GREEN", + "description": "Green color", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "MAGENTA", + "description": "Magenta color", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "DataVisualizationWeightEnum", + "description": "Weight of the data visualization palette", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "WEIGHT_50", + "description": "50 weight", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEIGHT_100", + "description": "100 weight", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEIGHT_200", + "description": "200 weight", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEIGHT_300", + "description": "300 weight", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEIGHT_400", + "description": "400 weight", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEIGHT_500", + "description": "500 weight", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEIGHT_600", + "description": "600 weight", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEIGHT_700", + "description": "700 weight", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEIGHT_800", + "description": "800 weight", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEIGHT_900", + "description": "900 weight", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEIGHT_950", + "description": "950 weight", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { "kind": "SCALAR", "name": "Date", "description": "Date represented in ISO 8601", @@ -15613,7 +17073,7 @@ "inputFields": [ { "name": "id", - "description": "Global ID of the annotation to delete", + "description": "Global ID of the annotation to delete.", "type": { "kind": "NON_NULL", "name": null, @@ -15701,7 +17161,7 @@ "inputFields": [ { "name": "id", - "description": "ID of the segment", + "description": "ID of the segment.", "type": { "kind": "NON_NULL", "name": null, @@ -16204,7 +17664,7 @@ "args": [ { "name": "earlierOrEqualToSha", - "description": "The SHA256 of the most recent acceptable version", + "description": "The SHA256 of the most recent acceptable version.", "type": { "kind": "SCALAR", "name": "String", @@ -16214,7 +17674,7 @@ }, { "name": "earlierOrEqualToId", - "description": "The Global ID of the most recent acceptable version", + "description": "The Global ID of the most recent acceptable version.", "type": { "kind": "SCALAR", "name": "DesignManagementVersionID", @@ -16663,7 +18123,7 @@ "args": [ { "name": "id", - "description": "Find a design by its ID", + "description": "Find a design by its ID.", "type": { "kind": "SCALAR", "name": "DesignManagementDesignID", @@ -16673,7 +18133,7 @@ }, { "name": "filename", - "description": "Find a design by its filename", + "description": "Find a design by its filename.", "type": { "kind": "SCALAR", "name": "String", @@ -16696,7 +18156,7 @@ "args": [ { "name": "id", - "description": "The Global ID of the design at this version", + "description": "The Global ID of the design at this version.", "type": { "kind": "NON_NULL", "name": null, @@ -16723,7 +18183,7 @@ "args": [ { "name": "ids", - "description": "Filters designs by their ID", + "description": "Filters designs by their ID.", "type": { "kind": "LIST", "name": null, @@ -16741,7 +18201,7 @@ }, { "name": "filenames", - "description": "Filters designs by their filename", + "description": "Filters designs by their filename.", "type": { "kind": "LIST", "name": null, @@ -16862,7 +18322,7 @@ "args": [ { "name": "sha", - "description": "The SHA256 of a specific version", + "description": "The SHA256 of a specific version.", "type": { "kind": "SCALAR", "name": "String", @@ -16872,7 +18332,7 @@ }, { "name": "id", - "description": "The Global ID of the version", + "description": "The Global ID of the version.", "type": { "kind": "SCALAR", "name": "DesignManagementVersionID", @@ -16895,7 +18355,7 @@ "args": [ { "name": "earlierOrEqualToSha", - "description": "The SHA256 of the most recent acceptable version", + "description": "The SHA256 of the most recent acceptable version.", "type": { "kind": "SCALAR", "name": "String", @@ -16905,7 +18365,7 @@ }, { "name": "earlierOrEqualToId", - "description": "The Global ID of the most recent acceptable version", + "description": "The Global ID of the most recent acceptable version.", "type": { "kind": "SCALAR", "name": "DesignManagementVersionID", @@ -17324,7 +18784,7 @@ "args": [ { "name": "id", - "description": "The Global ID of the design at this version", + "description": "The Global ID of the design at this version.", "type": { "kind": "NON_NULL", "name": null, @@ -17351,7 +18811,7 @@ "args": [ { "name": "id", - "description": "The Global ID of the version", + "description": "The Global ID of the version.", "type": { "kind": "NON_NULL", "name": null, @@ -17388,7 +18848,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project where the issue is to upload designs for", + "description": "The project where the issue is to upload designs for.", "type": { "kind": "NON_NULL", "name": null, @@ -17402,7 +18862,7 @@ }, { "name": "iid", - "description": "The IID of the issue to modify designs for", + "description": "The IID of the issue to modify designs for.", "type": { "kind": "NON_NULL", "name": null, @@ -17416,7 +18876,7 @@ }, { "name": "filenames", - "description": "The filenames of the designs to delete", + "description": "The filenames of the designs to delete.", "type": { "kind": "NON_NULL", "name": null, @@ -17498,7 +18958,7 @@ }, { "name": "version", - "description": "The new version in which the designs are deleted", + "description": "The new version in which the designs are deleted.", "args": [ ], @@ -17546,7 +19006,7 @@ "inputFields": [ { "name": "id", - "description": "ID of the design to move", + "description": "ID of the design to move.", "type": { "kind": "NON_NULL", "name": null, @@ -17560,7 +19020,7 @@ }, { "name": "previous", - "description": "ID of the immediately preceding design", + "description": "ID of the immediately preceding design.", "type": { "kind": "SCALAR", "name": "DesignManagementDesignID", @@ -17570,7 +19030,7 @@ }, { "name": "next", - "description": "ID of the immediately following design", + "description": "ID of the immediately following design.", "type": { "kind": "SCALAR", "name": "DesignManagementDesignID", @@ -17614,7 +19074,7 @@ }, { "name": "designCollection", - "description": "The current state of the collection", + "description": "The current state of the collection.", "args": [ ], @@ -17668,7 +19128,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project where the issue is to upload designs for", + "description": "The project where the issue is to upload designs for.", "type": { "kind": "NON_NULL", "name": null, @@ -17682,7 +19142,7 @@ }, { "name": "iid", - "description": "The IID of the issue to modify designs for", + "description": "The IID of the issue to modify designs for.", "type": { "kind": "NON_NULL", "name": null, @@ -17696,7 +19156,7 @@ }, { "name": "files", - "description": "The files to upload", + "description": "The files to upload.", "type": { "kind": "NON_NULL", "name": null, @@ -17752,7 +19212,7 @@ }, { "name": "designs", - "description": "The designs that were uploaded by the mutation", + "description": "The designs that were uploaded by the mutation.", "args": [ ], @@ -17857,7 +19317,7 @@ "args": [ { "name": "id", - "description": "The ID of the DesignAtVersion", + "description": "The ID of the DesignAtVersion.", "type": { "kind": "SCALAR", "name": "DesignManagementDesignAtVersionID", @@ -17867,7 +19327,7 @@ }, { "name": "designId", - "description": "The ID of a specific design", + "description": "The ID of a specific design.", "type": { "kind": "SCALAR", "name": "DesignManagementDesignID", @@ -17877,7 +19337,7 @@ }, { "name": "filename", - "description": "The filename of a specific design", + "description": "The filename of a specific design.", "type": { "kind": "SCALAR", "name": "String", @@ -17961,7 +19421,7 @@ "args": [ { "name": "ids", - "description": "Filters designs by their ID", + "description": "Filters designs by their ID.", "type": { "kind": "LIST", "name": null, @@ -17979,7 +19439,7 @@ }, { "name": "filenames", - "description": "Filters designs by their filename", + "description": "Filters designs by their filename.", "type": { "kind": "LIST", "name": null, @@ -18247,7 +19707,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the board to destroy", + "description": "The global ID of the board to destroy.", "type": { "kind": "NON_NULL", "name": null, @@ -18383,7 +19843,7 @@ "fields": [ { "name": "board", - "description": "The board after mutation", + "description": "The board after mutation.", "args": [ ], @@ -18451,7 +19911,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the compliance framework to destroy", + "description": "The global ID of the compliance framework to destroy.", "type": { "kind": "NON_NULL", "name": null, @@ -18715,7 +20175,7 @@ }, { "name": "deletedTagNames", - "description": "Deleted container repository tags", + "description": "Deleted container repository tags.", "args": [ ], @@ -18781,7 +20241,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the note to destroy", + "description": "The global ID of the note to destroy.", "type": { "kind": "NON_NULL", "name": null, @@ -18855,7 +20315,7 @@ }, { "name": "note", - "description": "The note after mutation", + "description": "The note after mutation.", "args": [ ], @@ -18883,7 +20343,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the snippet to destroy", + "description": "The global ID of the snippet to destroy.", "type": { "kind": "NON_NULL", "name": null, @@ -18957,7 +20417,7 @@ }, { "name": "snippet", - "description": "The snippet after mutation", + "description": "The snippet after mutation.", "args": [ ], @@ -20492,7 +21952,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the discussion", + "description": "The global ID of the discussion.", "type": { "kind": "NON_NULL", "name": null, @@ -20506,7 +21966,7 @@ }, { "name": "resolve", - "description": "Will resolve the discussion when true, and unresolve the discussion when false", + "description": "Will resolve the discussion when true, and unresolve the discussion when false.", "type": { "kind": "NON_NULL", "name": null, @@ -20554,7 +22014,7 @@ }, { "name": "discussion", - "description": "The discussion after mutation", + "description": "The discussion after mutation.", "args": [ ], @@ -20608,7 +22068,7 @@ "inputFields": [ { "name": "id", - "description": "ID of the vulnerability to be dismissed", + "description": "ID of the vulnerability to be dismissed.", "type": { "kind": "NON_NULL", "name": null, @@ -20622,7 +22082,7 @@ }, { "name": "comment", - "description": "Reason why vulnerability should be dismissed", + "description": "Comment why vulnerability should be dismissed.", "type": { "kind": "SCALAR", "name": "String", @@ -20631,6 +22091,16 @@ "defaultValue": null }, { + "name": "dismissalReason", + "description": "Reason why vulnerability should be dismissed.", + "type": { + "kind": "ENUM", + "name": "VulnerabilityDismissalReason", + "ofType": null + }, + "defaultValue": null + }, + { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", "type": { @@ -20692,7 +22162,7 @@ }, { "name": "vulnerability", - "description": "The vulnerability after dismissal", + "description": "The vulnerability after dismissal.", "args": [ ], @@ -20919,7 +22389,7 @@ "args": [ { "name": "path", - "description": "Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'", + "description": "Path to a file which defines metrics dashboard eg: 'config/prometheus/common_metrics.yml'.", "type": { "kind": "NON_NULL", "name": null, @@ -21132,7 +22602,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the environment to update", + "description": "The global ID of the environment to update.", "type": { "kind": "NON_NULL", "name": null, @@ -21146,7 +22616,7 @@ }, { "name": "weight", - "description": "The weight of the Canary Ingress", + "description": "The weight of the Canary Ingress.", "type": { "kind": "NON_NULL", "name": null, @@ -21275,7 +22745,7 @@ }, { "name": "timeframe", - "description": "List items overlapping the given timeframe", + "description": "List items overlapping the given timeframe.", "type": { "kind": "INPUT_OBJECT", "name": "Timeframe", @@ -21285,7 +22755,7 @@ }, { "name": "iid", - "description": "IID of the epic, e.g., \"1\"", + "description": "IID of the epic, e.g., \"1\".", "type": { "kind": "SCALAR", "name": "ID", @@ -21295,7 +22765,7 @@ }, { "name": "iids", - "description": "List of IIDs of epics, e.g., [1, 2]", + "description": "List of IIDs of epics, e.g., [1, 2].", "type": { "kind": "LIST", "name": null, @@ -21313,7 +22783,7 @@ }, { "name": "state", - "description": "Filter epics by state", + "description": "Filter epics by state.", "type": { "kind": "ENUM", "name": "EpicState", @@ -21323,7 +22793,7 @@ }, { "name": "search", - "description": "Search query for epic title or description", + "description": "Search query for epic title or description.", "type": { "kind": "SCALAR", "name": "String", @@ -21333,7 +22803,7 @@ }, { "name": "sort", - "description": "List epics by sort order", + "description": "List epics by sort order.", "type": { "kind": "ENUM", "name": "EpicSort", @@ -21343,7 +22813,7 @@ }, { "name": "authorUsername", - "description": "Filter epics by author", + "description": "Filter epics by author.", "type": { "kind": "SCALAR", "name": "String", @@ -21353,7 +22823,7 @@ }, { "name": "labelName", - "description": "Filter epics by labels", + "description": "Filter epics by labels.", "type": { "kind": "LIST", "name": null, @@ -21371,7 +22841,7 @@ }, { "name": "milestoneTitle", - "description": "Filter epics by milestone title, computed from epic's issues", + "description": "Filter epics by milestone title, computed from epic's issues.", "type": { "kind": "SCALAR", "name": "String", @@ -21381,7 +22851,7 @@ }, { "name": "iidStartsWith", - "description": "Filter epics by IID for autocomplete", + "description": "Filter epics by IID for autocomplete.", "type": { "kind": "SCALAR", "name": "String", @@ -21391,7 +22861,7 @@ }, { "name": "includeDescendantGroups", - "description": "Include epics from descendant groups", + "description": "Include epics from descendant groups.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -21400,6 +22870,16 @@ "defaultValue": "true" }, { + "name": "confidential", + "description": "Filter epics by given confidentiality.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", "type": { @@ -22390,7 +23870,7 @@ "inputFields": [ { "name": "iid", - "description": "The IID of the epic to mutate", + "description": "The IID of the epic to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -22404,7 +23884,7 @@ }, { "name": "groupPath", - "description": "The group the epic to mutate belongs to", + "description": "The group the epic to mutate belongs to.", "type": { "kind": "NON_NULL", "name": null, @@ -22418,7 +23898,7 @@ }, { "name": "projectPath", - "description": "The full path of the project the issue belongs to", + "description": "The full path of the project the issue belongs to.", "type": { "kind": "NON_NULL", "name": null, @@ -22432,7 +23912,7 @@ }, { "name": "issueIid", - "description": "The IID of the issue to be added", + "description": "The IID of the issue to be added.", "type": { "kind": "NON_NULL", "name": null, @@ -22480,7 +23960,7 @@ }, { "name": "epic", - "description": "The epic after mutation", + "description": "The epic after mutation.", "args": [ ], @@ -22494,7 +23974,7 @@ }, { "name": "epicIssue", - "description": "The epic-issue relation", + "description": "The epic-issue relation.", "args": [ ], @@ -22547,7 +24027,7 @@ "fields": [ { "name": "id", - "description": "Global ID of the board", + "description": "Global ID of the board.", "args": [ ], @@ -22564,8 +24044,71 @@ "deprecationReason": null }, { + "name": "lists", + "description": "Epic board lists.", + "args": [ + { + "name": "id", + "description": "Find an epic board list by ID.", + "type": { + "kind": "SCALAR", + "name": "BoardsEpicListID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EpicListConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "name", - "description": "Name of the board", + "description": "Name of the board.", "args": [ ], @@ -23139,6 +24682,20 @@ "deprecationReason": null }, { + "name": "createNoteEmail", + "description": "User specific email address for the issue", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "createdAt", "description": "Timestamp of when the issue was created", "args": [ @@ -24291,6 +25848,266 @@ }, { "kind": "OBJECT", + "name": "EpicList", + "description": "Represents an epic board list", + "fields": [ + { + "name": "epics", + "description": "List epics.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "EpicConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "Global ID of the board list.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "BoardsEpicListID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "label", + "description": "Label of the list.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "Label", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "listType", + "description": "Type of the list.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "position", + "description": "Position of the list within the board.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "title", + "description": "Title of the list.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EpicListConnection", + "description": "The connection type for EpicList.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EpicListEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "EpicList", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "EpicListEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "EpicList", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", "name": "EpicPermissions", "description": "Check permissions for the current user on an epic", "fields": [ @@ -24454,7 +26271,7 @@ "inputFields": [ { "name": "iid", - "description": "The IID of the epic to mutate", + "description": "The IID of the epic to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -24468,7 +26285,7 @@ }, { "name": "groupPath", - "description": "The group the epic to mutate belongs to", + "description": "The group the epic to mutate belongs to.", "type": { "kind": "NON_NULL", "name": null, @@ -24482,7 +26299,7 @@ }, { "name": "subscribedState", - "description": "The desired state of the subscription", + "description": "The desired state of the subscription.", "type": { "kind": "NON_NULL", "name": null, @@ -24530,7 +26347,7 @@ }, { "name": "epic", - "description": "The epic after mutation", + "description": "The epic after mutation.", "args": [ ], @@ -24726,7 +26543,7 @@ "inputFields": [ { "name": "baseEpicId", - "description": "The ID of the base epic of the tree", + "description": "The ID of the base epic of the tree.", "type": { "kind": "NON_NULL", "name": null, @@ -24740,7 +26557,7 @@ }, { "name": "moved", - "description": "Parameters for updating the tree positions", + "description": "Parameters for updating the tree positions.", "type": { "kind": "NON_NULL", "name": null, @@ -24854,6 +26671,142 @@ "possibleTypes": null }, { + "kind": "INPUT_OBJECT", + "name": "ExportRequirementsInput", + "description": "Autogenerated input type of ExportRequirements", + "fields": null, + "inputFields": [ + { + "name": "sort", + "description": "List requirements by sort order.", + "type": { + "kind": "ENUM", + "name": "Sort", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "state", + "description": "Filter requirements by state.", + "type": { + "kind": "ENUM", + "name": "RequirementState", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "search", + "description": "Search query for requirement title.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "authorUsername", + "description": "Filter requirements by author username.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "projectPath", + "description": "Full project path the requirements are associated with.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "ExportRequirementsPayload", + "description": "Autogenerated return type of ExportRequirements", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { "kind": "OBJECT", "name": "ExternalIssue", "description": "Represents an external issue", @@ -25059,7 +27012,7 @@ "args": [ { "name": "ids", - "description": "Filters registries by their ID", + "description": "Filters registries by their ID.", "type": { "kind": "LIST", "name": null, @@ -25158,7 +27111,7 @@ "args": [ { "name": "ids", - "description": "Filters registries by their ID", + "description": "Filters registries by their ID.", "type": { "kind": "LIST", "name": null, @@ -25346,7 +27299,7 @@ "args": [ { "name": "ids", - "description": "Filters registries by their ID", + "description": "Filters registries by their ID.", "type": { "kind": "LIST", "name": null, @@ -25431,7 +27384,7 @@ "args": [ { "name": "ids", - "description": "Filters registries by their ID", + "description": "Filters registries by their ID.", "type": { "kind": "LIST", "name": null, @@ -25712,7 +27665,7 @@ "args": [ { "name": "id", - "description": "The board's ID", + "description": "The board's ID.", "type": { "kind": "NON_NULL", "name": null, @@ -25739,7 +27692,7 @@ "args": [ { "name": "id", - "description": "Find a board by its ID", + "description": "Find a board by its ID.", "type": { "kind": "SCALAR", "name": "BoardID", @@ -25802,7 +27755,7 @@ "args": [ { "name": "startDate", - "description": "First day for which to fetch code coverage activity (maximum time window is set to 90 days)", + "description": "First day for which to fetch code coverage activity (maximum time window is set to 90 days).", "type": { "kind": "NON_NULL", "name": null, @@ -25865,7 +27818,7 @@ }, { "name": "complianceFrameworks", - "description": "Compliance frameworks available to projects in this namespace Available only when feature flag `ff_custom_compliance_frameworks` is enabled.", + "description": "Compliance frameworks available to projects in this namespace. Available only when feature flag `ff_custom_compliance_frameworks` is enabled.", "args": [ { "name": "after", @@ -25906,6 +27859,16 @@ "ofType": null }, "defaultValue": null + }, + { + "name": "id", + "description": "Global ID of a specific compliance framework to return.", + "type": { + "kind": "SCALAR", + "name": "ComplianceManagementFrameworkID", + "ofType": null + }, + "defaultValue": null } ], "type": { @@ -25922,7 +27885,7 @@ "args": [ { "name": "name", - "description": "Filter the container repositories by their name", + "description": "Filter the container repositories by their name.", "type": { "kind": "SCALAR", "name": "String", @@ -26136,7 +28099,7 @@ }, { "name": "timeframe", - "description": "List items overlapping the given timeframe", + "description": "List items overlapping the given timeframe.", "type": { "kind": "INPUT_OBJECT", "name": "Timeframe", @@ -26146,7 +28109,7 @@ }, { "name": "iid", - "description": "IID of the epic, e.g., \"1\"", + "description": "IID of the epic, e.g., \"1\".", "type": { "kind": "SCALAR", "name": "ID", @@ -26156,7 +28119,7 @@ }, { "name": "iids", - "description": "List of IIDs of epics, e.g., [1, 2]", + "description": "List of IIDs of epics, e.g., [1, 2].", "type": { "kind": "LIST", "name": null, @@ -26174,7 +28137,7 @@ }, { "name": "state", - "description": "Filter epics by state", + "description": "Filter epics by state.", "type": { "kind": "ENUM", "name": "EpicState", @@ -26184,7 +28147,7 @@ }, { "name": "search", - "description": "Search query for epic title or description", + "description": "Search query for epic title or description.", "type": { "kind": "SCALAR", "name": "String", @@ -26194,7 +28157,7 @@ }, { "name": "sort", - "description": "List epics by sort order", + "description": "List epics by sort order.", "type": { "kind": "ENUM", "name": "EpicSort", @@ -26204,7 +28167,7 @@ }, { "name": "authorUsername", - "description": "Filter epics by author", + "description": "Filter epics by author.", "type": { "kind": "SCALAR", "name": "String", @@ -26214,7 +28177,7 @@ }, { "name": "labelName", - "description": "Filter epics by labels", + "description": "Filter epics by labels.", "type": { "kind": "LIST", "name": null, @@ -26232,7 +28195,7 @@ }, { "name": "milestoneTitle", - "description": "Filter epics by milestone title, computed from epic's issues", + "description": "Filter epics by milestone title, computed from epic's issues.", "type": { "kind": "SCALAR", "name": "String", @@ -26242,7 +28205,7 @@ }, { "name": "iidStartsWith", - "description": "Filter epics by IID for autocomplete", + "description": "Filter epics by IID for autocomplete.", "type": { "kind": "SCALAR", "name": "String", @@ -26252,13 +28215,23 @@ }, { "name": "includeDescendantGroups", - "description": "Include epics from descendant groups", + "description": "Include epics from descendant groups.", "type": { "kind": "SCALAR", "name": "Boolean", "ofType": null }, "defaultValue": "true" + }, + { + "name": "confidential", + "description": "Filter epics by given confidentiality.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null } ], "type": { @@ -26275,7 +28248,7 @@ "args": [ { "name": "id", - "description": "Find an epic board by ID", + "description": "Find an epic board by ID.", "type": { "kind": "NON_NULL", "name": null, @@ -26375,7 +28348,7 @@ }, { "name": "timeframe", - "description": "List items overlapping the given timeframe", + "description": "List items overlapping the given timeframe.", "type": { "kind": "INPUT_OBJECT", "name": "Timeframe", @@ -26385,7 +28358,7 @@ }, { "name": "iid", - "description": "IID of the epic, e.g., \"1\"", + "description": "IID of the epic, e.g., \"1\".", "type": { "kind": "SCALAR", "name": "ID", @@ -26395,7 +28368,7 @@ }, { "name": "iids", - "description": "List of IIDs of epics, e.g., [1, 2]", + "description": "List of IIDs of epics, e.g., [1, 2].", "type": { "kind": "LIST", "name": null, @@ -26413,7 +28386,7 @@ }, { "name": "state", - "description": "Filter epics by state", + "description": "Filter epics by state.", "type": { "kind": "ENUM", "name": "EpicState", @@ -26423,7 +28396,7 @@ }, { "name": "search", - "description": "Search query for epic title or description", + "description": "Search query for epic title or description.", "type": { "kind": "SCALAR", "name": "String", @@ -26433,7 +28406,7 @@ }, { "name": "sort", - "description": "List epics by sort order", + "description": "List epics by sort order.", "type": { "kind": "ENUM", "name": "EpicSort", @@ -26443,7 +28416,7 @@ }, { "name": "authorUsername", - "description": "Filter epics by author", + "description": "Filter epics by author.", "type": { "kind": "SCALAR", "name": "String", @@ -26453,7 +28426,7 @@ }, { "name": "labelName", - "description": "Filter epics by labels", + "description": "Filter epics by labels.", "type": { "kind": "LIST", "name": null, @@ -26471,7 +28444,7 @@ }, { "name": "milestoneTitle", - "description": "Filter epics by milestone title, computed from epic's issues", + "description": "Filter epics by milestone title, computed from epic's issues.", "type": { "kind": "SCALAR", "name": "String", @@ -26481,7 +28454,7 @@ }, { "name": "iidStartsWith", - "description": "Filter epics by IID for autocomplete", + "description": "Filter epics by IID for autocomplete.", "type": { "kind": "SCALAR", "name": "String", @@ -26491,7 +28464,7 @@ }, { "name": "includeDescendantGroups", - "description": "Include epics from descendant groups", + "description": "Include epics from descendant groups.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -26500,6 +28473,16 @@ "defaultValue": "true" }, { + "name": "confidential", + "description": "Filter epics by given confidentiality.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", "type": { @@ -26604,7 +28587,7 @@ "args": [ { "name": "search", - "description": "Search query", + "description": "Search query.", "type": { "kind": "SCALAR", "name": "String", @@ -26614,7 +28597,7 @@ }, { "name": "relations", - "description": "Filter members by the given member relations", + "description": "Filter members by the given member relations.", "type": { "kind": "LIST", "name": null, @@ -26735,7 +28718,7 @@ "args": [ { "name": "iid", - "description": "IID of the issue. For example, \"1\"", + "description": "IID of the issue. For example, \"1\".", "type": { "kind": "SCALAR", "name": "String", @@ -26745,7 +28728,7 @@ }, { "name": "iids", - "description": "List of IIDs of issues. For example, [1, 2]", + "description": "List of IIDs of issues. For example, [1, 2].", "type": { "kind": "LIST", "name": null, @@ -26763,7 +28746,7 @@ }, { "name": "labelName", - "description": "Labels applied to this issue", + "description": "Labels applied to this issue.", "type": { "kind": "LIST", "name": null, @@ -26777,7 +28760,7 @@ }, { "name": "milestoneTitle", - "description": "Milestone applied to this issue", + "description": "Milestone applied to this issue.", "type": { "kind": "LIST", "name": null, @@ -26791,7 +28774,7 @@ }, { "name": "authorUsername", - "description": "Username of the author of the issue", + "description": "Username of the author of the issue.", "type": { "kind": "SCALAR", "name": "String", @@ -26801,7 +28784,7 @@ }, { "name": "assigneeUsername", - "description": "Username of a user assigned to the issue", + "description": "Username of a user assigned to the issue.", "type": { "kind": "SCALAR", "name": "String", @@ -26811,7 +28794,7 @@ }, { "name": "assigneeUsernames", - "description": "Usernames of users assigned to the issue", + "description": "Usernames of users assigned to the issue.", "type": { "kind": "LIST", "name": null, @@ -26829,7 +28812,7 @@ }, { "name": "assigneeId", - "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported", + "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported.", "type": { "kind": "SCALAR", "name": "String", @@ -26839,7 +28822,7 @@ }, { "name": "createdBefore", - "description": "Issues created before this date", + "description": "Issues created before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -26849,7 +28832,7 @@ }, { "name": "createdAfter", - "description": "Issues created after this date", + "description": "Issues created after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -26859,7 +28842,7 @@ }, { "name": "updatedBefore", - "description": "Issues updated before this date", + "description": "Issues updated before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -26869,7 +28852,7 @@ }, { "name": "updatedAfter", - "description": "Issues updated after this date", + "description": "Issues updated after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -26879,7 +28862,7 @@ }, { "name": "closedBefore", - "description": "Issues closed before this date", + "description": "Issues closed before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -26889,7 +28872,7 @@ }, { "name": "closedAfter", - "description": "Issues closed after this date", + "description": "Issues closed after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -26899,7 +28882,7 @@ }, { "name": "search", - "description": "Search query for issue title or description", + "description": "Search query for issue title or description.", "type": { "kind": "SCALAR", "name": "String", @@ -26909,7 +28892,7 @@ }, { "name": "types", - "description": "Filter issues by the given issue types", + "description": "Filter issues by the given issue types.", "type": { "kind": "LIST", "name": null, @@ -26927,7 +28910,7 @@ }, { "name": "state", - "description": "Current state of this issue", + "description": "Current state of this issue.", "type": { "kind": "ENUM", "name": "IssuableState", @@ -26937,7 +28920,7 @@ }, { "name": "sort", - "description": "Sort issues by this criteria", + "description": "Sort issues by this criteria.", "type": { "kind": "ENUM", "name": "IssueSort", @@ -26947,7 +28930,7 @@ }, { "name": "iterationId", - "description": "Iterations applied to the issue", + "description": "Iterations applied to the issue.", "type": { "kind": "LIST", "name": null, @@ -26961,7 +28944,7 @@ }, { "name": "epicId", - "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported", + "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported.", "type": { "kind": "SCALAR", "name": "String", @@ -27054,7 +29037,7 @@ }, { "name": "timeframe", - "description": "List items overlapping the given timeframe", + "description": "List items overlapping the given timeframe.", "type": { "kind": "INPUT_OBJECT", "name": "Timeframe", @@ -27285,7 +29268,7 @@ "args": [ { "name": "iids", - "description": "Array of IIDs of merge requests, for example `[1, 2]`", + "description": "Array of IIDs of merge requests, for example `[1, 2]`.", "type": { "kind": "LIST", "name": null, @@ -27367,7 +29350,7 @@ }, { "name": "mergedAfter", - "description": "Merge requests merged after this date", + "description": "Merge requests merged after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -27377,7 +29360,7 @@ }, { "name": "mergedBefore", - "description": "Merge requests merged before this date", + "description": "Merge requests merged before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -27387,7 +29370,7 @@ }, { "name": "milestoneTitle", - "description": "Title of the milestone", + "description": "Title of the milestone.", "type": { "kind": "SCALAR", "name": "String", @@ -27397,7 +29380,7 @@ }, { "name": "sort", - "description": "Sort merge requests by this criteria", + "description": "Sort merge requests by this criteria.", "type": { "kind": "ENUM", "name": "MergeRequestSort", @@ -27417,7 +29400,7 @@ }, { "name": "assigneeUsername", - "description": "Username of the assignee", + "description": "Username of the assignee.", "type": { "kind": "SCALAR", "name": "String", @@ -27427,7 +29410,7 @@ }, { "name": "authorUsername", - "description": "Username of the author", + "description": "Username of the author.", "type": { "kind": "SCALAR", "name": "String", @@ -27510,7 +29493,7 @@ }, { "name": "timeframe", - "description": "List items overlapping the given timeframe", + "description": "List items overlapping the given timeframe.", "type": { "kind": "INPUT_OBJECT", "name": "Timeframe", @@ -27520,7 +29503,7 @@ }, { "name": "ids", - "description": "Array of global milestone IDs, e.g., \"gid://gitlab/Milestone/1\"", + "description": "Array of global milestone IDs, e.g., \"gid://gitlab/Milestone/1\".", "type": { "kind": "LIST", "name": null, @@ -27538,7 +29521,7 @@ }, { "name": "state", - "description": "Filter milestones by state", + "description": "Filter milestones by state.", "type": { "kind": "ENUM", "name": "MilestoneStateEnum", @@ -27548,7 +29531,7 @@ }, { "name": "title", - "description": "The title of the milestone", + "description": "The title of the milestone.", "type": { "kind": "SCALAR", "name": "String", @@ -27558,7 +29541,7 @@ }, { "name": "searchTitle", - "description": "A search string for the title", + "description": "A search string for the title.", "type": { "kind": "SCALAR", "name": "String", @@ -27568,7 +29551,7 @@ }, { "name": "containingDate", - "description": "A date that the milestone contains", + "description": "A date that the milestone contains.", "type": { "kind": "SCALAR", "name": "Time", @@ -27578,7 +29561,7 @@ }, { "name": "includeDescendants", - "description": "Also return milestones in all subgroups and subprojects", + "description": "Also return milestones in all subgroups and subprojects.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -27654,6 +29637,20 @@ "deprecationReason": null }, { + "name": "packageSettings", + "description": "The package settings for the namespace", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "PackageSettings", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "parent", "description": "Parent group", "args": [ @@ -27705,7 +29702,7 @@ "args": [ { "name": "includeSubgroups", - "description": "Include also subgroup projects", + "description": "Include also subgroup projects.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -27715,7 +29712,7 @@ }, { "name": "search", - "description": "Search project with most similar names or paths", + "description": "Search project with most similar names or paths.", "type": { "kind": "SCALAR", "name": "String", @@ -27725,7 +29722,7 @@ }, { "name": "sort", - "description": "Sort projects by this criteria", + "description": "Sort projects by this criteria.", "type": { "kind": "ENUM", "name": "NamespaceProjectSort", @@ -27735,7 +29732,7 @@ }, { "name": "hasVulnerabilities", - "description": "Returns only the projects which have vulnerabilities", + "description": "Returns only the projects which have vulnerabilities.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -27932,7 +29929,7 @@ "args": [ { "name": "startDate", - "description": "List time logs within a date range where the logged date is equal to or after startDate", + "description": "List time logs within a date range where the logged date is equal to or after startDate.", "type": { "kind": "SCALAR", "name": "Time", @@ -27942,7 +29939,7 @@ }, { "name": "endDate", - "description": "List time logs within a date range where the logged date is equal to or before endDate", + "description": "List time logs within a date range where the logged date is equal to or before endDate.", "type": { "kind": "SCALAR", "name": "Time", @@ -27952,7 +29949,7 @@ }, { "name": "startTime", - "description": "List time-logs within a time range where the logged time is equal to or after startTime", + "description": "List time-logs within a time range where the logged time is equal to or after startTime.", "type": { "kind": "SCALAR", "name": "Time", @@ -27962,7 +29959,7 @@ }, { "name": "endTime", - "description": "List time-logs within a time range where the logged time is equal to or before endTime", + "description": "List time-logs within a time range where the logged time is equal to or before endTime.", "type": { "kind": "SCALAR", "name": "Time", @@ -28103,7 +30100,7 @@ "args": [ { "name": "projectId", - "description": "Filter vulnerabilities by project", + "description": "Filter vulnerabilities by project.", "type": { "kind": "LIST", "name": null, @@ -28121,7 +30118,7 @@ }, { "name": "reportType", - "description": "Filter vulnerabilities by report type", + "description": "Filter vulnerabilities by report type.", "type": { "kind": "LIST", "name": null, @@ -28139,7 +30136,7 @@ }, { "name": "severity", - "description": "Filter vulnerabilities by severity", + "description": "Filter vulnerabilities by severity.", "type": { "kind": "LIST", "name": null, @@ -28157,7 +30154,7 @@ }, { "name": "state", - "description": "Filter vulnerabilities by state", + "description": "Filter vulnerabilities by state.", "type": { "kind": "LIST", "name": null, @@ -28175,7 +30172,7 @@ }, { "name": "scanner", - "description": "Filter vulnerabilities by scanner", + "description": "Filter vulnerabilities by VulnerabilityScanner.externalId.", "type": { "kind": "LIST", "name": null, @@ -28193,7 +30190,7 @@ }, { "name": "sort", - "description": "List vulnerabilities by sort order", + "description": "List vulnerabilities by sort order.", "type": { "kind": "ENUM", "name": "VulnerabilitySort", @@ -28203,7 +30200,7 @@ }, { "name": "hasResolution", - "description": "Returns only the vulnerabilities which have been resolved on default branch", + "description": "Returns only the vulnerabilities which have been resolved on default branch.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -28213,7 +30210,7 @@ }, { "name": "hasIssues", - "description": "Returns only the vulnerabilities which have linked issues", + "description": "Returns only the vulnerabilities which have linked issues.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -28276,7 +30273,7 @@ "args": [ { "name": "startDate", - "description": "First day for which to fetch vulnerability history", + "description": "First day for which to fetch vulnerability history.", "type": { "kind": "NON_NULL", "name": null, @@ -28290,7 +30287,7 @@ }, { "name": "endDate", - "description": "Last day for which to fetch vulnerability history", + "description": "Last day for which to fetch vulnerability history.", "type": { "kind": "NON_NULL", "name": null, @@ -28357,7 +30354,7 @@ "args": [ { "name": "startDate", - "description": "First day for which to fetch vulnerability history", + "description": "First day for which to fetch vulnerability history.", "type": { "kind": "NON_NULL", "name": null, @@ -28371,7 +30368,7 @@ }, { "name": "endDate", - "description": "Last day for which to fetch vulnerability history", + "description": "Last day for which to fetch vulnerability history.", "type": { "kind": "NON_NULL", "name": null, @@ -28438,7 +30435,7 @@ "args": [ { "name": "includeSubgroups", - "description": "Include grades belonging to subgroups", + "description": "Include grades belonging to subgroups.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -28526,7 +30523,7 @@ "args": [ { "name": "projectId", - "description": "Filter vulnerabilities by project", + "description": "Filter vulnerabilities by project.", "type": { "kind": "LIST", "name": null, @@ -28544,7 +30541,7 @@ }, { "name": "reportType", - "description": "Filter vulnerabilities by report type", + "description": "Filter vulnerabilities by report type.", "type": { "kind": "LIST", "name": null, @@ -28562,7 +30559,7 @@ }, { "name": "severity", - "description": "Filter vulnerabilities by severity", + "description": "Filter vulnerabilities by severity.", "type": { "kind": "LIST", "name": null, @@ -28580,7 +30577,7 @@ }, { "name": "state", - "description": "Filter vulnerabilities by state", + "description": "Filter vulnerabilities by state.", "type": { "kind": "LIST", "name": null, @@ -28598,7 +30595,7 @@ }, { "name": "scanner", - "description": "Filter vulnerabilities by scanner", + "description": "Filter vulnerabilities by scanner.", "type": { "kind": "LIST", "name": null, @@ -29091,7 +31088,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project to create the integration in", + "description": "The project to create the integration in.", "type": { "kind": "NON_NULL", "name": null, @@ -29105,7 +31102,7 @@ }, { "name": "name", - "description": "The name of the integration", + "description": "The name of the integration.", "type": { "kind": "NON_NULL", "name": null, @@ -29119,7 +31116,7 @@ }, { "name": "active", - "description": "Whether the integration is receiving alerts", + "description": "Whether the integration is receiving alerts.", "type": { "kind": "NON_NULL", "name": null, @@ -29132,6 +31129,34 @@ "defaultValue": null }, { + "name": "payloadExample", + "description": "The example of an alert payload.", + "type": { + "kind": "SCALAR", + "name": "JsonString", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "payloadAttributeMappings", + "description": "The custom mapping of GitLab alert attributes to fields from the payload_example.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "AlertManagementPayloadAlertFieldInput", + "ofType": null + } + } + }, + "defaultValue": null + }, + { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", "type": { @@ -29193,7 +31218,7 @@ }, { "name": "integration", - "description": "The HTTP integration", + "description": "The HTTP integration.", "args": [ ], @@ -29221,7 +31246,7 @@ "inputFields": [ { "name": "id", - "description": "The ID of the integration to remove", + "description": "The ID of the integration to remove.", "type": { "kind": "NON_NULL", "name": null, @@ -29295,7 +31320,7 @@ }, { "name": "integration", - "description": "The HTTP integration", + "description": "The HTTP integration.", "args": [ ], @@ -29323,7 +31348,7 @@ "inputFields": [ { "name": "id", - "description": "The ID of the integration to mutate", + "description": "The ID of the integration to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -29397,7 +31422,7 @@ }, { "name": "integration", - "description": "The HTTP integration", + "description": "The HTTP integration.", "args": [ ], @@ -29425,7 +31450,7 @@ "inputFields": [ { "name": "id", - "description": "The ID of the integration to mutate", + "description": "The ID of the integration to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -29439,7 +31464,7 @@ }, { "name": "name", - "description": "The name of the integration", + "description": "The name of the integration.", "type": { "kind": "SCALAR", "name": "String", @@ -29449,7 +31474,7 @@ }, { "name": "active", - "description": "Whether the integration is receiving alerts", + "description": "Whether the integration is receiving alerts.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -29519,7 +31544,7 @@ }, { "name": "integration", - "description": "The HTTP integration", + "description": "The HTTP integration.", "args": [ ], @@ -29560,6 +31585,282 @@ "possibleTypes": null }, { + "kind": "SCALAR", + "name": "IncidentManagementOncallParticipantID", + "description": "Identifier of IncidentManagement::OncallParticipant", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "IncidentManagementOncallRotation", + "description": "Describes an incident management on-call rotation", + "fields": [ + { + "name": "id", + "description": "ID of the on-call rotation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "IncidentManagementOncallRotationID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "length", + "description": "Length of the on-call schedule, in the units specified by lengthUnit.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "lengthUnit", + "description": "Unit of the on-call rotation length.", + "args": [ + + ], + "type": { + "kind": "ENUM", + "name": "OncallRotationUnitEnum", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": "Name of the on-call rotation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "participants", + "description": "Participants of the on-call rotation.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "OncallParticipantTypeConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "startsAt", + "description": "Start date of the on-call rotation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "IncidentManagementOncallRotationConnection", + "description": "The connection type for IncidentManagementOncallRotation.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "IncidentManagementOncallRotationEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "IncidentManagementOncallRotation", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "IncidentManagementOncallRotationEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "IncidentManagementOncallRotation", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "SCALAR", + "name": "IncidentManagementOncallRotationID", + "description": "Identifier of IncidentManagement::OncallRotation", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { "kind": "OBJECT", "name": "IncidentManagementOncallSchedule", "description": "Describes an incident management on-call schedule", @@ -29615,6 +31916,63 @@ "deprecationReason": null }, { + "name": "rotations", + "description": "On-call rotations for the on-call schedule", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "IncidentManagementOncallRotationConnection", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "timezone", "description": "Time zone of the on-call schedule", "args": [ @@ -29899,7 +32257,7 @@ "args": [ { "name": "projectId", - "description": "Filter vulnerabilities by project", + "description": "Filter vulnerabilities by project.", "type": { "kind": "LIST", "name": null, @@ -29917,7 +32275,7 @@ }, { "name": "reportType", - "description": "Filter vulnerabilities by report type", + "description": "Filter vulnerabilities by report type.", "type": { "kind": "LIST", "name": null, @@ -29935,7 +32293,7 @@ }, { "name": "severity", - "description": "Filter vulnerabilities by severity", + "description": "Filter vulnerabilities by severity.", "type": { "kind": "LIST", "name": null, @@ -29953,7 +32311,7 @@ }, { "name": "state", - "description": "Filter vulnerabilities by state", + "description": "Filter vulnerabilities by state.", "type": { "kind": "LIST", "name": null, @@ -29971,7 +32329,7 @@ }, { "name": "scanner", - "description": "Filter vulnerabilities by scanner", + "description": "Filter vulnerabilities by scanner.", "type": { "kind": "LIST", "name": null, @@ -30420,6 +32778,20 @@ "deprecationReason": null }, { + "name": "createNoteEmail", + "description": "User specific email address for the issue", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "createdAt", "description": "Timestamp of when the issue was created", "args": [ @@ -31560,7 +33932,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the issue to mutate is in", + "description": "The project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -31574,7 +33946,7 @@ }, { "name": "iid", - "description": "The IID of the issue to mutate", + "description": "The IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -31588,7 +33960,7 @@ }, { "name": "targetProjectPath", - "description": "The project to move the issue to", + "description": "The project to move the issue to.", "type": { "kind": "NON_NULL", "name": null, @@ -31623,7 +33995,7 @@ "inputFields": [ { "name": "projectPath", - "description": "Project the issue to mutate is in", + "description": "Project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -31637,7 +34009,7 @@ }, { "name": "iid", - "description": "IID of the issue to mutate", + "description": "IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -31651,7 +34023,7 @@ }, { "name": "boardId", - "description": "Global ID of the board that the issue is in", + "description": "Global ID of the board that the issue is in.", "type": { "kind": "NON_NULL", "name": null, @@ -31665,7 +34037,7 @@ }, { "name": "fromListId", - "description": "ID of the board list that the issue will be moved from", + "description": "ID of the board list that the issue will be moved from.", "type": { "kind": "SCALAR", "name": "ID", @@ -31675,7 +34047,7 @@ }, { "name": "toListId", - "description": "ID of the board list that the issue will be moved to", + "description": "ID of the board list that the issue will be moved to.", "type": { "kind": "SCALAR", "name": "ID", @@ -31685,7 +34057,7 @@ }, { "name": "moveBeforeId", - "description": "ID of issue that should be placed before the current issue", + "description": "ID of issue that should be placed before the current issue.", "type": { "kind": "SCALAR", "name": "ID", @@ -31695,7 +34067,7 @@ }, { "name": "moveAfterId", - "description": "ID of issue that should be placed after the current issue", + "description": "ID of issue that should be placed after the current issue.", "type": { "kind": "SCALAR", "name": "ID", @@ -31705,7 +34077,7 @@ }, { "name": "epicId", - "description": "The ID of the parent epic. NULL when removing the association", + "description": "The ID of the parent epic. NULL when removing the association.", "type": { "kind": "SCALAR", "name": "EpicID", @@ -31775,7 +34147,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -31842,7 +34214,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -32027,7 +34399,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the issue to mutate is in", + "description": "The project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -32041,7 +34413,7 @@ }, { "name": "iid", - "description": "The IID of the issue to mutate", + "description": "The IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -32147,7 +34519,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -32175,7 +34547,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the issue to mutate is in", + "description": "The project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -32189,7 +34561,7 @@ }, { "name": "iid", - "description": "The IID of the issue to mutate", + "description": "The IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -32277,7 +34649,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -32305,7 +34677,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the issue to mutate is in", + "description": "The project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -32319,7 +34691,7 @@ }, { "name": "iid", - "description": "The IID of the issue to mutate", + "description": "The IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -32333,7 +34705,7 @@ }, { "name": "dueDate", - "description": "The desired due date for the issue", + "description": "The desired due date for the issue.", "type": { "kind": "NON_NULL", "name": null, @@ -32407,7 +34779,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -32435,7 +34807,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the issue to mutate is in", + "description": "The project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -32449,7 +34821,7 @@ }, { "name": "iid", - "description": "The IID of the issue to mutate", + "description": "The IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -32533,7 +34905,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -32561,7 +34933,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the issue to mutate is in", + "description": "The project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -32575,7 +34947,7 @@ }, { "name": "iid", - "description": "The IID of the issue to mutate", + "description": "The IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -32659,7 +35031,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -32687,7 +35059,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the issue to mutate is in", + "description": "The project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -32701,7 +35073,7 @@ }, { "name": "iid", - "description": "The IID of the issue to mutate", + "description": "The IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -32715,7 +35087,7 @@ }, { "name": "locked", - "description": "Whether or not to lock discussion on the issue", + "description": "Whether or not to lock discussion on the issue.", "type": { "kind": "NON_NULL", "name": null, @@ -32789,7 +35161,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -32817,7 +35189,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the issue to mutate is in", + "description": "The project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -32831,7 +35203,7 @@ }, { "name": "iid", - "description": "The IID of the issue to mutate", + "description": "The IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -32919,7 +35291,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -32947,7 +35319,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the issue to mutate is in", + "description": "The project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -32961,7 +35333,7 @@ }, { "name": "iid", - "description": "The IID of the issue to mutate", + "description": "The IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -32975,7 +35347,7 @@ }, { "name": "subscribedState", - "description": "The desired state of the subscription", + "description": "The desired state of the subscription.", "type": { "kind": "NON_NULL", "name": null, @@ -33049,7 +35421,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -33077,7 +35449,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the issue to mutate is in", + "description": "The project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -33091,7 +35463,7 @@ }, { "name": "iid", - "description": "The IID of the issue to mutate", + "description": "The IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -33105,7 +35477,7 @@ }, { "name": "weight", - "description": "The desired weight for the issue", + "description": "The desired weight for the issue.", "type": { "kind": "NON_NULL", "name": null, @@ -33179,7 +35551,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -34210,7 +36582,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project to import the Jira project into", + "description": "The project to import the Jira project into.", "type": { "kind": "NON_NULL", "name": null, @@ -34224,7 +36596,7 @@ }, { "name": "jiraProjectKey", - "description": "Project key of the importer Jira project", + "description": "Project key of the importer Jira project.", "type": { "kind": "NON_NULL", "name": null, @@ -34238,7 +36610,7 @@ }, { "name": "jiraProjectName", - "description": "Project name of the importer Jira project", + "description": "Project name of the importer Jira project.", "type": { "kind": "SCALAR", "name": "String", @@ -34248,7 +36620,7 @@ }, { "name": "usersMapping", - "description": "The mapping of Jira to GitLab users", + "description": "The mapping of Jira to GitLab users.", "type": { "kind": "LIST", "name": null, @@ -34326,7 +36698,7 @@ }, { "name": "jiraImport", - "description": "The Jira import data after mutation", + "description": "The Jira import data after mutation.", "args": [ ], @@ -34354,7 +36726,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project to import the Jira users into", + "description": "The project to import the Jira users into.", "type": { "kind": "NON_NULL", "name": null, @@ -34368,7 +36740,7 @@ }, { "name": "startAt", - "description": "The index of the record the import should started at, default 0 (50 records returned)", + "description": "The index of the record the import should started at, default 0 (50 records returned).", "type": { "kind": "SCALAR", "name": "Int", @@ -34666,7 +37038,7 @@ "args": [ { "name": "name", - "description": "Project name or key", + "description": "Project name or key.", "type": { "kind": "SCALAR", "name": "String", @@ -35063,6 +37435,16 @@ "possibleTypes": null }, { + "kind": "SCALAR", + "name": "JsonString", + "description": "JSON object as raw string", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { "kind": "OBJECT", "name": "Label", "description": null, @@ -35268,7 +37650,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project full path the resource is associated with", + "description": "The project full path the resource is associated with.", "type": { "kind": "SCALAR", "name": "ID", @@ -35278,7 +37660,7 @@ }, { "name": "groupPath", - "description": "The group full path the resource is associated with", + "description": "The group full path the resource is associated with.", "type": { "kind": "SCALAR", "name": "ID", @@ -35288,7 +37670,7 @@ }, { "name": "title", - "description": "Title of the label", + "description": "Title of the label.", "type": { "kind": "NON_NULL", "name": null, @@ -35302,7 +37684,7 @@ }, { "name": "description", - "description": "Description of the label", + "description": "Description of the label.", "type": { "kind": "SCALAR", "name": "String", @@ -35312,7 +37694,7 @@ }, { "name": "color", - "description": "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the CSS color names in https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords", + "description": "The color of the label given in 6-digit hex notation with leading '#' sign (e.g. #FFAABB) or one of the CSS color names in https://developer.mozilla.org/en-US/docs/Web/CSS/color_value#Color_keywords.", "type": { "kind": "SCALAR", "name": "String", @@ -35382,7 +37764,7 @@ }, { "name": "label", - "description": "The label after mutation", + "description": "The label after mutation.", "args": [ ], @@ -35504,7 +37886,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the snippet to update", + "description": "The global ID of the snippet to update.", "type": { "kind": "NON_NULL", "name": null, @@ -35578,7 +37960,7 @@ }, { "name": "snippet", - "description": "The snippet after mutation", + "description": "The snippet after mutation.", "args": [ ], @@ -36113,6 +38495,20 @@ "deprecationReason": null }, { + "name": "autoMergeStrategy", + "description": "Selected auto merge strategy", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "availableAutoMergeStrategies", "description": "Array of available auto merge strategies", "args": [ @@ -36333,6 +38729,20 @@ "deprecationReason": null }, { + "name": "defaultSquashCommitMessage", + "description": "Default squash commit message of the merge request", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "description", "description": "Description of the merge request (Markdown rendered as HTML for caching)", "args": [ @@ -36750,6 +39160,20 @@ "deprecationReason": null }, { + "name": "mergeUser", + "description": "User who merged this merge request", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "mergeWhenPipelineSucceeds", "description": "Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS)", "args": [ @@ -36882,7 +39306,7 @@ }, { "name": "participants", - "description": "Participants in the merge request", + "description": "Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes.", "args": [ { "name": "after", @@ -36939,7 +39363,7 @@ "args": [ { "name": "status", - "description": "Filter pipelines by their status", + "description": "Filter pipelines by their status.", "type": { "kind": "ENUM", "name": "PipelineStatusEnum", @@ -36949,7 +39373,7 @@ }, { "name": "ref", - "description": "Filter pipelines by the ref they are run for", + "description": "Filter pipelines by the ref they are run for.", "type": { "kind": "SCALAR", "name": "String", @@ -36959,7 +39383,7 @@ }, { "name": "sha", - "description": "Filter pipelines by the sha of the commit they are run for", + "description": "Filter pipelines by the sha of the commit they are run for.", "type": { "kind": "SCALAR", "name": "String", @@ -37112,6 +39536,59 @@ "deprecationReason": null }, { + "name": "reviewers", + "description": "Users from whom a review has been requested.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "UserConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "securityAutoFix", "description": "Indicates if the merge request is created by @GitLab-Security-Bot.", "args": [ @@ -37240,6 +39717,24 @@ "deprecationReason": null }, { + "name": "squash", + "description": "Indicates if squash on merge is enabled", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "squashOnMerge", "description": "Indicates if squash on merge is enabled", "args": [ @@ -37689,7 +40184,7 @@ "inputFields": [ { "name": "projectPath", - "description": "Project full path the merge request is associated with", + "description": "Project full path the merge request is associated with.", "type": { "kind": "NON_NULL", "name": null, @@ -37833,7 +40328,7 @@ }, { "name": "mergeRequest", - "description": "The merge request after mutation", + "description": "The merge request after mutation.", "args": [ ], @@ -38336,7 +40831,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the merge request to mutate is in", + "description": "The project the merge request to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -38350,7 +40845,7 @@ }, { "name": "iid", - "description": "The IID of the merge request to mutate", + "description": "The IID of the merge request to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -38456,7 +40951,7 @@ }, { "name": "mergeRequest", - "description": "The merge request after mutation", + "description": "The merge request after mutation.", "args": [ ], @@ -38484,7 +40979,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the merge request to mutate is in", + "description": "The project the merge request to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -38498,7 +40993,7 @@ }, { "name": "iid", - "description": "The IID of the merge request to mutate", + "description": "The IID of the merge request to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -38604,7 +41099,7 @@ }, { "name": "mergeRequest", - "description": "The merge request after mutation", + "description": "The merge request after mutation.", "args": [ ], @@ -38632,7 +41127,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the merge request to mutate is in", + "description": "The project the merge request to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -38646,7 +41141,7 @@ }, { "name": "iid", - "description": "The IID of the merge request to mutate", + "description": "The IID of the merge request to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -38734,7 +41229,7 @@ }, { "name": "mergeRequest", - "description": "The merge request after mutation", + "description": "The merge request after mutation.", "args": [ ], @@ -38762,7 +41257,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the merge request to mutate is in", + "description": "The project the merge request to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -38776,7 +41271,7 @@ }, { "name": "iid", - "description": "The IID of the merge request to mutate", + "description": "The IID of the merge request to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -38860,7 +41355,7 @@ }, { "name": "mergeRequest", - "description": "The merge request after mutation", + "description": "The merge request after mutation.", "args": [ ], @@ -38888,7 +41383,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the merge request to mutate is in", + "description": "The project the merge request to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -38902,7 +41397,7 @@ }, { "name": "iid", - "description": "The IID of the merge request to mutate", + "description": "The IID of the merge request to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -38916,7 +41411,7 @@ }, { "name": "subscribedState", - "description": "The desired state of the subscription", + "description": "The desired state of the subscription.", "type": { "kind": "NON_NULL", "name": null, @@ -38990,7 +41485,7 @@ }, { "name": "mergeRequest", - "description": "The merge request after mutation", + "description": "The merge request after mutation.", "args": [ ], @@ -39018,7 +41513,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the merge request to mutate is in", + "description": "The project the merge request to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -39032,7 +41527,7 @@ }, { "name": "iid", - "description": "The IID of the merge request to mutate", + "description": "The IID of the merge request to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -39120,7 +41615,7 @@ }, { "name": "mergeRequest", - "description": "The merge request after mutation", + "description": "The merge request after mutation.", "args": [ ], @@ -39296,7 +41791,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the merge request to mutate is in", + "description": "The project the merge request to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -39310,7 +41805,7 @@ }, { "name": "iid", - "description": "The IID of the merge request to mutate", + "description": "The IID of the merge request to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -39414,7 +41909,7 @@ }, { "name": "mergeRequest", - "description": "The merge request after mutation", + "description": "The merge request after mutation.", "args": [ ], @@ -39589,7 +42084,7 @@ "args": [ { "name": "from", - "description": "Timestamp marking date and time from which annotations need to be fetched", + "description": "Timestamp marking date and time from which annotations need to be fetched.", "type": { "kind": "NON_NULL", "name": null, @@ -39603,7 +42098,7 @@ }, { "name": "to", - "description": "Timestamp marking date and time to which annotations need to be fetched", + "description": "Timestamp marking date and time to which annotations need to be fetched.", "type": { "kind": "SCALAR", "name": "Time", @@ -40647,6 +43142,33 @@ "deprecationReason": null }, { + "name": "ciCdSettingsUpdate", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "CiCdSettingsUpdateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "CiCdSettingsUpdatePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "clusterAgentDelete", "description": null, "args": [ @@ -41970,6 +44492,33 @@ "deprecationReason": null }, { + "name": "exportRequirements", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ExportRequirementsInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "ExportRequirementsPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "httpIntegrationCreate", "description": null, "args": [ @@ -42726,6 +45275,33 @@ "deprecationReason": null }, { + "name": "oncallRotationCreate", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "OncallRotationCreateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "OncallRotationCreatePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "oncallScheduleCreate", "description": null, "args": [ @@ -43752,6 +46328,33 @@ "deprecationReason": null }, { + "name": "updateNamespacePackageSettings", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "UpdateNamespacePackageSettingsInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "UpdateNamespacePackageSettingsPayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "updateNote", "description": "Updates a Note. If the body of the Note contains only quick actions, the Note will be destroyed during the update, and no Note will be returned", "args": [ @@ -44066,7 +46669,7 @@ }, { "name": "complianceFrameworks", - "description": "Compliance frameworks available to projects in this namespace Available only when feature flag `ff_custom_compliance_frameworks` is enabled.", + "description": "Compliance frameworks available to projects in this namespace. Available only when feature flag `ff_custom_compliance_frameworks` is enabled.", "args": [ { "name": "after", @@ -44107,6 +46710,16 @@ "ofType": null }, "defaultValue": null + }, + { + "name": "id", + "description": "Global ID of a specific compliance framework to return.", + "type": { + "kind": "SCALAR", + "name": "ComplianceManagementFrameworkID", + "ofType": null + }, + "defaultValue": null } ], "type": { @@ -44268,6 +46881,20 @@ "deprecationReason": null }, { + "name": "packageSettings", + "description": "The package settings for the namespace", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "PackageSettings", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "path", "description": "Path of the namespace", "args": [ @@ -44291,7 +46918,7 @@ "args": [ { "name": "includeSubgroups", - "description": "Include also subgroup projects", + "description": "Include also subgroup projects.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -44301,7 +46928,7 @@ }, { "name": "search", - "description": "Search project with most similar names or paths", + "description": "Search project with most similar names or paths.", "type": { "kind": "SCALAR", "name": "String", @@ -44311,7 +46938,7 @@ }, { "name": "sort", - "description": "Sort projects by this criteria", + "description": "Sort projects by this criteria.", "type": { "kind": "ENUM", "name": "NamespaceProjectSort", @@ -44321,7 +46948,7 @@ }, { "name": "hasVulnerabilities", - "description": "Returns only the projects which have vulnerabilities", + "description": "Returns only the projects which have vulnerabilities.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -44636,7 +47263,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the namespace to mutate", + "description": "The global ID of the namespace to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -44710,7 +47337,7 @@ }, { "name": "namespace", - "description": "The namespace after mutation", + "description": "The namespace after mutation.", "args": [ ], @@ -45124,6 +47751,20 @@ "deprecationReason": null }, { + "name": "url", + "description": "URL to view this Note in the Web UI", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "userPermissions", "description": "Permissions for the current user on the resource", "args": [ @@ -45578,6 +48219,482 @@ "possibleTypes": null }, { + "kind": "OBJECT", + "name": "OncallParticipantType", + "description": "The rotation participant and color palette", + "fields": [ + { + "name": "colorPalette", + "description": "The color palette to assign to the on-call user. For example \"blue\".", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "colorWeight", + "description": "The color weight to assign to for the on-call user, for example \"500\". Max 4 chars. For easy identification of the user.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "ID of the on-call participant.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "IncidentManagementOncallParticipantID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "user", + "description": "The user who is participating.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "User", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "OncallParticipantTypeConnection", + "description": "The connection type for OncallParticipantType.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "OncallParticipantTypeEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "OncallParticipantType", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "OncallParticipantTypeEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "OncallParticipantType", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "OncallRotationCreateInput", + "description": "Autogenerated input type of OncallRotationCreate", + "fields": null, + "inputFields": [ + { + "name": "projectPath", + "description": "The project to create the on-call schedule in.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "scheduleIid", + "description": "The IID of the on-call schedule to create the on-call rotation in.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "name", + "description": "The name of the on-call rotation.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "startsAt", + "description": "The start date and time of the on-call rotation, in the timezone of the on-call schedule.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "OncallRotationDateInputType", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "rotationLength", + "description": "The rotation length of the on-call rotation.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "OncallRotationLengthInputType", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "participants", + "description": "The usernames of users participating in the on-call rotation.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "OncallUserInputType", + "ofType": null + } + } + } + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "OncallRotationCreatePayload", + "description": "Autogenerated return type of OncallRotationCreate", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "oncallRotation", + "description": "The on-call rotation.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "IncidentManagementOncallRotation", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "OncallRotationDateInputType", + "description": "Date input type for on-call rotation", + "fields": null, + "inputFields": [ + { + "name": "date", + "description": "The date component of the date in YYYY-MM-DD format.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "time", + "description": "The time component of the date in 24hr HH:MM format.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", + "name": "OncallRotationLengthInputType", + "description": "The rotation length of the on-call rotation", + "fields": null, + "inputFields": [ + { + "name": "length", + "description": "The rotation length of the on-call rotation.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "unit", + "description": "The unit of the rotation length of the on-call rotation.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "OncallRotationUnitEnum", + "ofType": null + } + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "ENUM", + "name": "OncallRotationUnitEnum", + "description": "Rotation length unit of an on-call rotation", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "HOURS", + "description": "Hours", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "DAYS", + "description": "Days", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "WEEKS", + "description": "Weeks", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { "kind": "INPUT_OBJECT", "name": "OncallScheduleCreateInput", "description": "Autogenerated input type of OncallScheduleCreate", @@ -45585,7 +48702,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project to create the on-call schedule in", + "description": "The project to create the on-call schedule in.", "type": { "kind": "NON_NULL", "name": null, @@ -45599,7 +48716,7 @@ }, { "name": "name", - "description": "The name of the on-call schedule", + "description": "The name of the on-call schedule.", "type": { "kind": "NON_NULL", "name": null, @@ -45613,7 +48730,7 @@ }, { "name": "description", - "description": "The description of the on-call schedule", + "description": "The description of the on-call schedule.", "type": { "kind": "SCALAR", "name": "String", @@ -45623,7 +48740,7 @@ }, { "name": "timezone", - "description": "The timezone of the on-call schedule", + "description": "The timezone of the on-call schedule.", "type": { "kind": "NON_NULL", "name": null, @@ -45697,7 +48814,7 @@ }, { "name": "oncallSchedule", - "description": "The on-call schedule", + "description": "The on-call schedule.", "args": [ ], @@ -45725,7 +48842,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project to remove the on-call schedule from", + "description": "The project to remove the on-call schedule from.", "type": { "kind": "NON_NULL", "name": null, @@ -45739,7 +48856,7 @@ }, { "name": "iid", - "description": "The on-call schedule internal ID to remove", + "description": "The on-call schedule internal ID to remove.", "type": { "kind": "NON_NULL", "name": null, @@ -45813,7 +48930,7 @@ }, { "name": "oncallSchedule", - "description": "The on-call schedule", + "description": "The on-call schedule.", "args": [ ], @@ -45841,7 +48958,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project to update the on-call schedule in", + "description": "The project to update the on-call schedule in.", "type": { "kind": "NON_NULL", "name": null, @@ -45855,7 +48972,7 @@ }, { "name": "iid", - "description": "The on-call schedule internal ID to update", + "description": "The on-call schedule internal ID to update.", "type": { "kind": "NON_NULL", "name": null, @@ -45869,7 +48986,7 @@ }, { "name": "name", - "description": "The name of the on-call schedule", + "description": "The name of the on-call schedule.", "type": { "kind": "SCALAR", "name": "String", @@ -45879,7 +48996,7 @@ }, { "name": "description", - "description": "The description of the on-call schedule", + "description": "The description of the on-call schedule.", "type": { "kind": "SCALAR", "name": "String", @@ -45889,7 +49006,7 @@ }, { "name": "timezone", - "description": "The timezone of the on-call schedule", + "description": "The timezone of the on-call schedule.", "type": { "kind": "SCALAR", "name": "String", @@ -45959,7 +49076,7 @@ }, { "name": "oncallSchedule", - "description": "The on-call schedule", + "description": "The on-call schedule.", "args": [ ], @@ -45980,13 +49097,370 @@ "possibleTypes": null }, { + "kind": "INPUT_OBJECT", + "name": "OncallUserInputType", + "description": "The rotation user and color palette", + "fields": null, + "inputFields": [ + { + "name": "username", + "description": "The username of the user to participate in the on-call rotation, such as `user_one`.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "colorPalette", + "description": "A value of DataVisualizationColorEnum. The color from the palette to assign to the on-call user.", + "type": { + "kind": "ENUM", + "name": "DataVisualizationColorEnum", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "colorWeight", + "description": "A value of DataVisualizationWeightEnum. The color weight to assign to for the on-call user.", + "type": { + "kind": "ENUM", + "name": "DataVisualizationWeightEnum", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { "kind": "OBJECT", "name": "Package", - "description": "Represents a package", + "description": "Represents a package in the Package Registry", + "fields": [ + { + "name": "createdAt", + "description": "The created date.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "The ID of the package.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": "The name of the package.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "packageType", + "description": "The type of the package.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "ENUM", + "name": "PackageTypeEnum", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pipelines", + "description": "Pipelines that built the package.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PipelineConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "project", + "description": "Project where the package is stored.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Project", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tags", + "description": "The package tags.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PackageTagConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatedAt", + "description": "The updated date.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "version", + "description": "The version of the package.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "versions", + "description": "The other versions of the package.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PackageConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "PackageComposerDetails", + "description": "Details of a Composer package", "fields": [ { + "name": "composerMetadatum", + "description": "The Composer metadatum.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PackageComposerMetadatumType", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "createdAt", - "description": "The created date", + "description": "The created date.", "args": [ ], @@ -46004,7 +49478,7 @@ }, { "name": "id", - "description": "The ID of the package", + "description": "The ID of the package.", "args": [ ], @@ -46022,7 +49496,7 @@ }, { "name": "name", - "description": "The name of the package", + "description": "The name of the package.", "args": [ ], @@ -46040,7 +49514,7 @@ }, { "name": "packageType", - "description": "The type of the package", + "description": "The type of the package.", "args": [ ], @@ -46057,8 +49531,132 @@ "deprecationReason": null }, { + "name": "pipelines", + "description": "Pipelines that built the package.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PipelineConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "project", + "description": "Project where the package is stored.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "Project", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "tags", + "description": "The package tags.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PackageTagConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "updatedAt", - "description": "The update date", + "description": "The updated date.", "args": [ ], @@ -46076,7 +49674,129 @@ }, { "name": "version", - "description": "The version of the package", + "description": "The version of the package.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "versions", + "description": "The other versions of the package.", + "args": [ + { + "name": "after", + "description": "Returns the elements in the list that come after the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "before", + "description": "Returns the elements in the list that come before the specified cursor.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "first", + "description": "Returns the first _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "last", + "description": "Returns the last _n_ elements from the list.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PackageConnection", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "PackageComposerJsonType", + "description": "Represents a composer JSON file", + "fields": [ + { + "name": "license", + "description": "The license set in the Composer JSON file.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": "The name set in the Composer JSON file.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "type", + "description": "The type set in the Composer JSON file.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "version", + "description": "The version set in the Composer JSON file.", "args": [ ], @@ -46098,6 +49818,55 @@ }, { "kind": "OBJECT", + "name": "PackageComposerMetadatumType", + "description": "Composer metadatum", + "fields": [ + { + "name": "composerJson", + "description": "Data of the Composer JSON file.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PackageComposerJsonType", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "targetSha", + "description": "Target SHA of the package.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", "name": "PackageConnection", "description": "The connection type for Package.", "fields": [ @@ -46454,6 +50223,248 @@ "possibleTypes": null }, { + "kind": "OBJECT", + "name": "PackageSettings", + "description": "Namespace-level Package Registry settings", + "fields": [ + { + "name": "mavenDuplicateExceptionRegex", + "description": "When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "UntrustedRegexp", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "mavenDuplicatesAllowed", + "description": "Indicates whether duplicate Maven packages are allowed for this namespace.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "PackageTag", + "description": "Represents a package tag", + "fields": [ + { + "name": "createdAt", + "description": "The created date.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "The ID of the tag.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "name", + "description": "The name of the tag.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "updatedAt", + "description": "The updated date.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "Time", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "PackageTagConnection", + "description": "The connection type for PackageTag.", + "fields": [ + { + "name": "edges", + "description": "A list of edges.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PackageTagEdge", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "nodes", + "description": "A list of nodes.", + "args": [ + + ], + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PackageTag", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "pageInfo", + "description": "Information to aid in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "OBJECT", + "name": "PageInfo", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "PackageTagEdge", + "description": "An edge in a connection.", + "fields": [ + { + "name": "cursor", + "description": "A cursor for use in pagination.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "node", + "description": "The item at the end of the edge.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "PackageTag", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { "kind": "ENUM", "name": "PackageTypeEnum", "description": null, @@ -46519,6 +50530,16 @@ "possibleTypes": null }, { + "kind": "SCALAR", + "name": "PackagesPackageID", + "description": "Identifier of Packages::Package", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { "kind": "OBJECT", "name": "PageInfo", "description": "Information about pagination in a connection.", @@ -46851,7 +50872,7 @@ "args": [ { "name": "securityReportTypes", - "description": "Filter jobs by the type of security report they produce", + "description": "Filter jobs by the type of security report they produce.", "type": { "kind": "LIST", "name": null, @@ -47428,7 +51449,7 @@ "inputFields": [ { "name": "id", - "description": "The ID of the pipeline to mutate", + "description": "The ID of the pipeline to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -47660,7 +51681,7 @@ "inputFields": [ { "name": "id", - "description": "The ID of the pipeline to mutate", + "description": "The ID of the pipeline to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -47860,7 +51881,7 @@ "inputFields": [ { "name": "id", - "description": "The ID of the pipeline to mutate", + "description": "The ID of the pipeline to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -47934,7 +51955,7 @@ }, { "name": "pipeline", - "description": "The pipeline after mutation", + "description": "The pipeline after mutation.", "args": [ ], @@ -48056,7 +52077,7 @@ "args": [ { "name": "iid", - "description": "IID of the alert. For example, \"1\"", + "description": "IID of the alert. For example, \"1\".", "type": { "kind": "SCALAR", "name": "String", @@ -48066,7 +52087,7 @@ }, { "name": "statuses", - "description": "Alerts with the specified statues. For example, [TRIGGERED]", + "description": "Alerts with the specified statues. For example, [TRIGGERED].", "type": { "kind": "LIST", "name": null, @@ -48084,7 +52105,7 @@ }, { "name": "sort", - "description": "Sort alerts by this criteria", + "description": "Sort alerts by this criteria.", "type": { "kind": "ENUM", "name": "AlertManagementAlertSort", @@ -48094,7 +52115,7 @@ }, { "name": "domain", - "description": "Filter query for given domain", + "description": "Filter query for given domain.", "type": { "kind": "NON_NULL", "name": null, @@ -48118,7 +52139,7 @@ }, { "name": "assigneeUsername", - "description": "Username of a user assigned to the issue", + "description": "Username of a user assigned to the issue.", "type": { "kind": "SCALAR", "name": "String", @@ -48151,7 +52172,7 @@ }, { "name": "assigneeUsername", - "description": "Username of a user assigned to the issue", + "description": "Username of a user assigned to the issue.", "type": { "kind": "SCALAR", "name": "String", @@ -48174,7 +52195,7 @@ "args": [ { "name": "iid", - "description": "IID of the alert. For example, \"1\"", + "description": "IID of the alert. For example, \"1\".", "type": { "kind": "SCALAR", "name": "String", @@ -48184,7 +52205,7 @@ }, { "name": "statuses", - "description": "Alerts with the specified statues. For example, [TRIGGERED]", + "description": "Alerts with the specified statues. For example, [TRIGGERED].", "type": { "kind": "LIST", "name": null, @@ -48202,7 +52223,7 @@ }, { "name": "sort", - "description": "Sort alerts by this criteria", + "description": "Sort alerts by this criteria.", "type": { "kind": "ENUM", "name": "AlertManagementAlertSort", @@ -48212,7 +52233,7 @@ }, { "name": "domain", - "description": "Filter query for given domain", + "description": "Filter query for given domain.", "type": { "kind": "NON_NULL", "name": null, @@ -48236,7 +52257,7 @@ }, { "name": "assigneeUsername", - "description": "Username of a user assigned to the issue", + "description": "Username of a user assigned to the issue.", "type": { "kind": "SCALAR", "name": "String", @@ -48408,7 +52429,7 @@ "args": [ { "name": "id", - "description": "The board's ID", + "description": "The board's ID.", "type": { "kind": "NON_NULL", "name": null, @@ -48435,7 +52456,7 @@ "args": [ { "name": "id", - "description": "Find a board by its ID", + "description": "Find a board by its ID.", "type": { "kind": "SCALAR", "name": "BoardID", @@ -48512,7 +52533,7 @@ "args": [ { "name": "name", - "description": "Name of the cluster agent", + "description": "Name of the cluster agent.", "type": { "kind": "NON_NULL", "name": null, @@ -48687,7 +52708,7 @@ "args": [ { "name": "name", - "description": "Filter the container repositories by their name", + "description": "Filter the container repositories by their name.", "type": { "kind": "SCALAR", "name": "String", @@ -48835,7 +52856,7 @@ "args": [ { "name": "id", - "description": "ID of the site profile", + "description": "ID of the site profile.", "type": { "kind": "NON_NULL", "name": null, @@ -48910,57 +52931,12 @@ "deprecationReason": null }, { - "name": "dastSiteValidation", - "description": "DAST Site Validation associated with the project. Will always return `null` if `security_on_demand_scans_site_validation` is disabled", - "args": [ - { - "name": "normalizedTargetUrls", - "description": "Normalized URL of the target to be scanned", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - } - }, - "defaultValue": null - }, - { - "name": "targetUrl", - "description": "URL of the target to be scanned", - "type": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "String", - "ofType": null - } - }, - "defaultValue": null - } - ], - "type": { - "kind": "OBJECT", - "name": "DastSiteValidation", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "dastSiteValidations", "description": "DAST Site Validations associated with the project. Will always return no nodes if `security_on_demand_scans_site_validation` is disabled", "args": [ { "name": "normalizedTargetUrls", - "description": "Normalized URL of the target to be scanned", + "description": "Normalized URL of the target to be scanned.", "type": { "kind": "LIST", "name": null, @@ -49059,7 +53035,7 @@ "args": [ { "name": "name", - "description": "Name of the environment", + "description": "Name of the environment.", "type": { "kind": "SCALAR", "name": "String", @@ -49069,7 +53045,7 @@ }, { "name": "search", - "description": "Search query for environment name", + "description": "Search query for environment name.", "type": { "kind": "SCALAR", "name": "String", @@ -49079,7 +53055,7 @@ }, { "name": "states", - "description": "States of environments that should be included in result", + "description": "States of environments that should be included in result.", "type": { "kind": "LIST", "name": null, @@ -49110,7 +53086,7 @@ "args": [ { "name": "name", - "description": "Name of the environment", + "description": "Name of the environment.", "type": { "kind": "SCALAR", "name": "String", @@ -49120,7 +53096,7 @@ }, { "name": "search", - "description": "Search query for environment name", + "description": "Search query for environment name.", "type": { "kind": "SCALAR", "name": "String", @@ -49130,7 +53106,7 @@ }, { "name": "states", - "description": "States of environments that should be included in result", + "description": "States of environments that should be included in result.", "type": { "kind": "LIST", "name": null, @@ -49364,7 +53340,7 @@ "args": [ { "name": "iid", - "description": "IID of the issue. For example, \"1\"", + "description": "IID of the issue. For example, \"1\".", "type": { "kind": "SCALAR", "name": "String", @@ -49374,7 +53350,7 @@ }, { "name": "iids", - "description": "List of IIDs of issues. For example, [1, 2]", + "description": "List of IIDs of issues. For example, [1, 2].", "type": { "kind": "LIST", "name": null, @@ -49392,7 +53368,7 @@ }, { "name": "labelName", - "description": "Labels applied to this issue", + "description": "Labels applied to this issue.", "type": { "kind": "LIST", "name": null, @@ -49406,7 +53382,7 @@ }, { "name": "milestoneTitle", - "description": "Milestone applied to this issue", + "description": "Milestone applied to this issue.", "type": { "kind": "LIST", "name": null, @@ -49420,7 +53396,7 @@ }, { "name": "authorUsername", - "description": "Username of the author of the issue", + "description": "Username of the author of the issue.", "type": { "kind": "SCALAR", "name": "String", @@ -49430,7 +53406,7 @@ }, { "name": "assigneeUsername", - "description": "Username of a user assigned to the issue", + "description": "Username of a user assigned to the issue.", "type": { "kind": "SCALAR", "name": "String", @@ -49440,7 +53416,7 @@ }, { "name": "assigneeUsernames", - "description": "Usernames of users assigned to the issue", + "description": "Usernames of users assigned to the issue.", "type": { "kind": "LIST", "name": null, @@ -49458,7 +53434,7 @@ }, { "name": "assigneeId", - "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported", + "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported.", "type": { "kind": "SCALAR", "name": "String", @@ -49468,7 +53444,7 @@ }, { "name": "createdBefore", - "description": "Issues created before this date", + "description": "Issues created before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49478,7 +53454,7 @@ }, { "name": "createdAfter", - "description": "Issues created after this date", + "description": "Issues created after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49488,7 +53464,7 @@ }, { "name": "updatedBefore", - "description": "Issues updated before this date", + "description": "Issues updated before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49498,7 +53474,7 @@ }, { "name": "updatedAfter", - "description": "Issues updated after this date", + "description": "Issues updated after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49508,7 +53484,7 @@ }, { "name": "closedBefore", - "description": "Issues closed before this date", + "description": "Issues closed before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49518,7 +53494,7 @@ }, { "name": "closedAfter", - "description": "Issues closed after this date", + "description": "Issues closed after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49528,7 +53504,7 @@ }, { "name": "search", - "description": "Search query for issue title or description", + "description": "Search query for issue title or description.", "type": { "kind": "SCALAR", "name": "String", @@ -49538,7 +53514,7 @@ }, { "name": "types", - "description": "Filter issues by the given issue types", + "description": "Filter issues by the given issue types.", "type": { "kind": "LIST", "name": null, @@ -49556,7 +53532,7 @@ }, { "name": "state", - "description": "Current state of this issue", + "description": "Current state of this issue.", "type": { "kind": "ENUM", "name": "IssuableState", @@ -49566,7 +53542,7 @@ }, { "name": "sort", - "description": "Sort issues by this criteria", + "description": "Sort issues by this criteria.", "type": { "kind": "ENUM", "name": "IssueSort", @@ -49576,7 +53552,7 @@ }, { "name": "iterationId", - "description": "Iterations applied to the issue", + "description": "Iterations applied to the issue.", "type": { "kind": "LIST", "name": null, @@ -49590,7 +53566,7 @@ }, { "name": "epicId", - "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported", + "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported.", "type": { "kind": "SCALAR", "name": "String", @@ -49613,7 +53589,7 @@ "args": [ { "name": "iid", - "description": "IID of the issue. For example, \"1\"", + "description": "IID of the issue. For example, \"1\".", "type": { "kind": "SCALAR", "name": "String", @@ -49623,7 +53599,7 @@ }, { "name": "iids", - "description": "List of IIDs of issues. For example, [1, 2]", + "description": "List of IIDs of issues. For example, [1, 2].", "type": { "kind": "LIST", "name": null, @@ -49641,7 +53617,7 @@ }, { "name": "labelName", - "description": "Labels applied to this issue", + "description": "Labels applied to this issue.", "type": { "kind": "LIST", "name": null, @@ -49655,7 +53631,7 @@ }, { "name": "milestoneTitle", - "description": "Milestone applied to this issue", + "description": "Milestone applied to this issue.", "type": { "kind": "LIST", "name": null, @@ -49669,7 +53645,7 @@ }, { "name": "authorUsername", - "description": "Username of the author of the issue", + "description": "Username of the author of the issue.", "type": { "kind": "SCALAR", "name": "String", @@ -49679,7 +53655,7 @@ }, { "name": "assigneeUsername", - "description": "Username of a user assigned to the issue", + "description": "Username of a user assigned to the issue.", "type": { "kind": "SCALAR", "name": "String", @@ -49689,7 +53665,7 @@ }, { "name": "assigneeUsernames", - "description": "Usernames of users assigned to the issue", + "description": "Usernames of users assigned to the issue.", "type": { "kind": "LIST", "name": null, @@ -49707,7 +53683,7 @@ }, { "name": "assigneeId", - "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported", + "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported.", "type": { "kind": "SCALAR", "name": "String", @@ -49717,7 +53693,7 @@ }, { "name": "createdBefore", - "description": "Issues created before this date", + "description": "Issues created before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49727,7 +53703,7 @@ }, { "name": "createdAfter", - "description": "Issues created after this date", + "description": "Issues created after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49737,7 +53713,7 @@ }, { "name": "updatedBefore", - "description": "Issues updated before this date", + "description": "Issues updated before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49747,7 +53723,7 @@ }, { "name": "updatedAfter", - "description": "Issues updated after this date", + "description": "Issues updated after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49757,7 +53733,7 @@ }, { "name": "closedBefore", - "description": "Issues closed before this date", + "description": "Issues closed before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49767,7 +53743,7 @@ }, { "name": "closedAfter", - "description": "Issues closed after this date", + "description": "Issues closed after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49777,7 +53753,7 @@ }, { "name": "search", - "description": "Search query for issue title or description", + "description": "Search query for issue title or description.", "type": { "kind": "SCALAR", "name": "String", @@ -49787,7 +53763,7 @@ }, { "name": "types", - "description": "Filter issues by the given issue types", + "description": "Filter issues by the given issue types.", "type": { "kind": "LIST", "name": null, @@ -49818,7 +53794,7 @@ "args": [ { "name": "iid", - "description": "IID of the issue. For example, \"1\"", + "description": "IID of the issue. For example, \"1\".", "type": { "kind": "SCALAR", "name": "String", @@ -49828,7 +53804,7 @@ }, { "name": "iids", - "description": "List of IIDs of issues. For example, [1, 2]", + "description": "List of IIDs of issues. For example, [1, 2].", "type": { "kind": "LIST", "name": null, @@ -49846,7 +53822,7 @@ }, { "name": "labelName", - "description": "Labels applied to this issue", + "description": "Labels applied to this issue.", "type": { "kind": "LIST", "name": null, @@ -49860,7 +53836,7 @@ }, { "name": "milestoneTitle", - "description": "Milestone applied to this issue", + "description": "Milestone applied to this issue.", "type": { "kind": "LIST", "name": null, @@ -49874,7 +53850,7 @@ }, { "name": "authorUsername", - "description": "Username of the author of the issue", + "description": "Username of the author of the issue.", "type": { "kind": "SCALAR", "name": "String", @@ -49884,7 +53860,7 @@ }, { "name": "assigneeUsername", - "description": "Username of a user assigned to the issue", + "description": "Username of a user assigned to the issue.", "type": { "kind": "SCALAR", "name": "String", @@ -49894,7 +53870,7 @@ }, { "name": "assigneeUsernames", - "description": "Usernames of users assigned to the issue", + "description": "Usernames of users assigned to the issue.", "type": { "kind": "LIST", "name": null, @@ -49912,7 +53888,7 @@ }, { "name": "assigneeId", - "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported", + "description": "ID of a user assigned to the issues, \"none\" and \"any\" values are supported.", "type": { "kind": "SCALAR", "name": "String", @@ -49922,7 +53898,7 @@ }, { "name": "createdBefore", - "description": "Issues created before this date", + "description": "Issues created before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49932,7 +53908,7 @@ }, { "name": "createdAfter", - "description": "Issues created after this date", + "description": "Issues created after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49942,7 +53918,7 @@ }, { "name": "updatedBefore", - "description": "Issues updated before this date", + "description": "Issues updated before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49952,7 +53928,7 @@ }, { "name": "updatedAfter", - "description": "Issues updated after this date", + "description": "Issues updated after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49962,7 +53938,7 @@ }, { "name": "closedBefore", - "description": "Issues closed before this date", + "description": "Issues closed before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49972,7 +53948,7 @@ }, { "name": "closedAfter", - "description": "Issues closed after this date", + "description": "Issues closed after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -49982,7 +53958,7 @@ }, { "name": "search", - "description": "Search query for issue title or description", + "description": "Search query for issue title or description.", "type": { "kind": "SCALAR", "name": "String", @@ -49992,7 +53968,7 @@ }, { "name": "types", - "description": "Filter issues by the given issue types", + "description": "Filter issues by the given issue types.", "type": { "kind": "LIST", "name": null, @@ -50010,7 +53986,7 @@ }, { "name": "state", - "description": "Current state of this issue", + "description": "Current state of this issue.", "type": { "kind": "ENUM", "name": "IssuableState", @@ -50020,7 +53996,7 @@ }, { "name": "sort", - "description": "Sort issues by this criteria", + "description": "Sort issues by this criteria.", "type": { "kind": "ENUM", "name": "IssueSort", @@ -50030,7 +54006,7 @@ }, { "name": "iterationId", - "description": "Iterations applied to the issue", + "description": "Iterations applied to the issue.", "type": { "kind": "LIST", "name": null, @@ -50044,7 +54020,7 @@ }, { "name": "epicId", - "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported", + "description": "ID of an epic associated with the issues, \"none\" and \"any\" values are supported.", "type": { "kind": "SCALAR", "name": "String", @@ -50141,7 +54117,7 @@ }, { "name": "timeframe", - "description": "List items overlapping the given timeframe", + "description": "List items overlapping the given timeframe.", "type": { "kind": "INPUT_OBJECT", "name": "Timeframe", @@ -50453,7 +54429,7 @@ "args": [ { "name": "iid", - "description": "IID of the merge request, for example `1`", + "description": "IID of the merge request, for example `1`.", "type": { "kind": "NON_NULL", "name": null, @@ -50480,7 +54456,7 @@ "args": [ { "name": "iids", - "description": "Array of IIDs of merge requests, for example `[1, 2]`", + "description": "Array of IIDs of merge requests, for example `[1, 2]`.", "type": { "kind": "LIST", "name": null, @@ -50562,7 +54538,7 @@ }, { "name": "mergedAfter", - "description": "Merge requests merged after this date", + "description": "Merge requests merged after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -50572,7 +54548,7 @@ }, { "name": "mergedBefore", - "description": "Merge requests merged before this date", + "description": "Merge requests merged before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -50582,7 +54558,7 @@ }, { "name": "milestoneTitle", - "description": "Title of the milestone", + "description": "Title of the milestone.", "type": { "kind": "SCALAR", "name": "String", @@ -50592,7 +54568,7 @@ }, { "name": "sort", - "description": "Sort merge requests by this criteria", + "description": "Sort merge requests by this criteria.", "type": { "kind": "ENUM", "name": "MergeRequestSort", @@ -50602,7 +54578,7 @@ }, { "name": "assigneeUsername", - "description": "Username of the assignee", + "description": "Username of the assignee.", "type": { "kind": "SCALAR", "name": "String", @@ -50612,7 +54588,7 @@ }, { "name": "authorUsername", - "description": "Username of the author", + "description": "Username of the author.", "type": { "kind": "SCALAR", "name": "String", @@ -50622,7 +54598,7 @@ }, { "name": "reviewerUsername", - "description": "Username of the reviewer", + "description": "Username of the reviewer.", "type": { "kind": "SCALAR", "name": "String", @@ -50733,7 +54709,7 @@ }, { "name": "timeframe", - "description": "List items overlapping the given timeframe", + "description": "List items overlapping the given timeframe.", "type": { "kind": "INPUT_OBJECT", "name": "Timeframe", @@ -50743,7 +54719,7 @@ }, { "name": "ids", - "description": "Array of global milestone IDs, e.g., \"gid://gitlab/Milestone/1\"", + "description": "Array of global milestone IDs, e.g., \"gid://gitlab/Milestone/1\".", "type": { "kind": "LIST", "name": null, @@ -50761,7 +54737,7 @@ }, { "name": "state", - "description": "Filter milestones by state", + "description": "Filter milestones by state.", "type": { "kind": "ENUM", "name": "MilestoneStateEnum", @@ -50771,7 +54747,7 @@ }, { "name": "title", - "description": "The title of the milestone", + "description": "The title of the milestone.", "type": { "kind": "SCALAR", "name": "String", @@ -50781,7 +54757,7 @@ }, { "name": "searchTitle", - "description": "A search string for the title", + "description": "A search string for the title.", "type": { "kind": "SCALAR", "name": "String", @@ -50791,7 +54767,7 @@ }, { "name": "containingDate", - "description": "A date that the milestone contains", + "description": "A date that the milestone contains.", "type": { "kind": "SCALAR", "name": "Time", @@ -50801,7 +54777,7 @@ }, { "name": "includeAncestors", - "description": "Also return milestones in the project's parent group and its ancestors", + "description": "Also return milestones in the project's parent group and its ancestors.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -51027,7 +55003,7 @@ "args": [ { "name": "iid", - "description": "IID of the Pipeline, e.g., \"1\"", + "description": "IID of the Pipeline, e.g., \"1\".", "type": { "kind": "NON_NULL", "name": null, @@ -51068,7 +55044,7 @@ "args": [ { "name": "status", - "description": "Filter pipelines by their status", + "description": "Filter pipelines by their status.", "type": { "kind": "ENUM", "name": "PipelineStatusEnum", @@ -51078,7 +55054,7 @@ }, { "name": "ref", - "description": "Filter pipelines by the ref they are run for", + "description": "Filter pipelines by the ref they are run for.", "type": { "kind": "SCALAR", "name": "String", @@ -51088,7 +55064,7 @@ }, { "name": "sha", - "description": "Filter pipelines by the sha of the commit they are run for", + "description": "Filter pipelines by the sha of the commit they are run for.", "type": { "kind": "SCALAR", "name": "String", @@ -51165,7 +55141,7 @@ "args": [ { "name": "search", - "description": "Search query", + "description": "Search query.", "type": { "kind": "SCALAR", "name": "String", @@ -51175,7 +55151,7 @@ }, { "name": "relations", - "description": "Filter members by the given member relations", + "description": "Filter members by the given member relations.", "type": { "kind": "LIST", "name": null, @@ -51260,7 +55236,7 @@ "args": [ { "name": "tagName", - "description": "The name of the tag associated to the release", + "description": "The name of the tag associated to the release.", "type": { "kind": "NON_NULL", "name": null, @@ -51287,7 +55263,7 @@ "args": [ { "name": "sort", - "description": "Sort releases by this criteria", + "description": "Sort releases by this criteria.", "type": { "kind": "ENUM", "name": "ReleaseSort", @@ -51405,36 +55381,8 @@ "description": "Find a single requirement", "args": [ { - "name": "iid", - "description": "IID of the requirement, e.g., \"1\"", - "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "iids", - "description": "List of IIDs of requirements, e.g., [1, 2]", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - } - }, - "defaultValue": null - }, - { "name": "sort", - "description": "List requirements by sort order", + "description": "List requirements by sort order.", "type": { "kind": "ENUM", "name": "Sort", @@ -51444,7 +55392,7 @@ }, { "name": "state", - "description": "Filter requirements by state", + "description": "Filter requirements by state.", "type": { "kind": "ENUM", "name": "RequirementState", @@ -51454,7 +55402,7 @@ }, { "name": "search", - "description": "Search query for requirement title", + "description": "Search query for requirement title.", "type": { "kind": "SCALAR", "name": "String", @@ -51464,7 +55412,7 @@ }, { "name": "authorUsername", - "description": "Filter requirements by author username", + "description": "Filter requirements by author username.", "type": { "kind": "LIST", "name": null, @@ -51479,6 +55427,34 @@ } }, "defaultValue": null + }, + { + "name": "iid", + "description": "IID of the requirement, e.g., \"1\".", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iids", + "description": "List of IIDs of requirements, e.g., [1, 2].", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null } ], "type": { @@ -51508,36 +55484,8 @@ "description": "Find requirements", "args": [ { - "name": "iid", - "description": "IID of the requirement, e.g., \"1\"", - "type": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "iids", - "description": "List of IIDs of requirements, e.g., [1, 2]", - "type": { - "kind": "LIST", - "name": null, - "ofType": { - "kind": "NON_NULL", - "name": null, - "ofType": { - "kind": "SCALAR", - "name": "ID", - "ofType": null - } - } - }, - "defaultValue": null - }, - { "name": "sort", - "description": "List requirements by sort order", + "description": "List requirements by sort order.", "type": { "kind": "ENUM", "name": "Sort", @@ -51547,7 +55495,7 @@ }, { "name": "state", - "description": "Filter requirements by state", + "description": "Filter requirements by state.", "type": { "kind": "ENUM", "name": "RequirementState", @@ -51557,7 +55505,7 @@ }, { "name": "search", - "description": "Search query for requirement title", + "description": "Search query for requirement title.", "type": { "kind": "SCALAR", "name": "String", @@ -51567,7 +55515,7 @@ }, { "name": "authorUsername", - "description": "Filter requirements by author username", + "description": "Filter requirements by author username.", "type": { "kind": "LIST", "name": null, @@ -51584,6 +55532,34 @@ "defaultValue": null }, { + "name": "iid", + "description": "IID of the requirement, e.g., \"1\".", + "type": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iids", + "description": "List of IIDs of requirements, e.g., [1, 2].", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", "type": { @@ -51680,7 +55656,7 @@ "args": [ { "name": "id", - "description": "ID of the Sentry issue", + "description": "ID of the Sentry issue.", "type": { "kind": "NON_NULL", "name": null, @@ -51749,7 +55725,7 @@ "args": [ { "name": "active", - "description": "Indicates if the service is active", + "description": "Indicates if the service is active.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -51759,7 +55735,7 @@ }, { "name": "type", - "description": "Class name of the service", + "description": "Class name of the service.", "type": { "kind": "ENUM", "name": "ServiceType", @@ -51836,7 +55812,7 @@ "args": [ { "name": "ids", - "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\"", + "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\".", "type": { "kind": "LIST", "name": null, @@ -51854,7 +55830,7 @@ }, { "name": "visibility", - "description": "The visibility of the snippet", + "description": "The visibility of the snippet.", "type": { "kind": "ENUM", "name": "VisibilityScopesEnum", @@ -52071,20 +56047,6 @@ "deprecationReason": null }, { - "name": "totalPipelineDuration", - "description": "Total pipeline duration for all of the pipelines in a project", - "args": [ - - ], - "type": { - "kind": "SCALAR", - "name": "Int", - "ofType": null - }, - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "userPermissions", "description": "Permissions for the current user on the resource", "args": [ @@ -52122,7 +56084,7 @@ "args": [ { "name": "projectId", - "description": "Filter vulnerabilities by project", + "description": "Filter vulnerabilities by project.", "type": { "kind": "LIST", "name": null, @@ -52140,7 +56102,7 @@ }, { "name": "reportType", - "description": "Filter vulnerabilities by report type", + "description": "Filter vulnerabilities by report type.", "type": { "kind": "LIST", "name": null, @@ -52158,7 +56120,7 @@ }, { "name": "severity", - "description": "Filter vulnerabilities by severity", + "description": "Filter vulnerabilities by severity.", "type": { "kind": "LIST", "name": null, @@ -52176,7 +56138,7 @@ }, { "name": "state", - "description": "Filter vulnerabilities by state", + "description": "Filter vulnerabilities by state.", "type": { "kind": "LIST", "name": null, @@ -52194,7 +56156,7 @@ }, { "name": "scanner", - "description": "Filter vulnerabilities by scanner", + "description": "Filter vulnerabilities by VulnerabilityScanner.externalId.", "type": { "kind": "LIST", "name": null, @@ -52212,7 +56174,7 @@ }, { "name": "sort", - "description": "List vulnerabilities by sort order", + "description": "List vulnerabilities by sort order.", "type": { "kind": "ENUM", "name": "VulnerabilitySort", @@ -52222,7 +56184,7 @@ }, { "name": "hasResolution", - "description": "Returns only the vulnerabilities which have been resolved on default branch", + "description": "Returns only the vulnerabilities which have been resolved on default branch.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -52232,7 +56194,7 @@ }, { "name": "hasIssues", - "description": "Returns only the vulnerabilities which have linked issues", + "description": "Returns only the vulnerabilities which have linked issues.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -52295,7 +56257,7 @@ "args": [ { "name": "startDate", - "description": "First day for which to fetch vulnerability history", + "description": "First day for which to fetch vulnerability history.", "type": { "kind": "NON_NULL", "name": null, @@ -52309,7 +56271,7 @@ }, { "name": "endDate", - "description": "Last day for which to fetch vulnerability history", + "description": "Last day for which to fetch vulnerability history.", "type": { "kind": "NON_NULL", "name": null, @@ -52429,7 +56391,7 @@ "args": [ { "name": "projectId", - "description": "Filter vulnerabilities by project", + "description": "Filter vulnerabilities by project.", "type": { "kind": "LIST", "name": null, @@ -52447,7 +56409,7 @@ }, { "name": "reportType", - "description": "Filter vulnerabilities by report type", + "description": "Filter vulnerabilities by report type.", "type": { "kind": "LIST", "name": null, @@ -52465,7 +56427,7 @@ }, { "name": "severity", - "description": "Filter vulnerabilities by severity", + "description": "Filter vulnerabilities by severity.", "type": { "kind": "LIST", "name": null, @@ -52483,7 +56445,7 @@ }, { "name": "state", - "description": "Filter vulnerabilities by state", + "description": "Filter vulnerabilities by state.", "type": { "kind": "LIST", "name": null, @@ -52501,7 +56463,7 @@ }, { "name": "scanner", - "description": "Filter vulnerabilities by scanner", + "description": "Filter vulnerabilities by scanner.", "type": { "kind": "LIST", "name": null, @@ -52568,6 +56530,20 @@ "description": null, "fields": [ { + "name": "keepLatestArtifact", + "description": "Whether to keep the latest builds artifacts.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "mergePipelinesEnabled", "description": "Whether merge pipelines are enabled.", "args": [ @@ -54030,7 +58006,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project to create the integration in", + "description": "The project to create the integration in.", "type": { "kind": "NON_NULL", "name": null, @@ -54044,7 +58020,7 @@ }, { "name": "active", - "description": "Whether the integration is receiving alerts", + "description": "Whether the integration is receiving alerts.", "type": { "kind": "NON_NULL", "name": null, @@ -54058,7 +58034,7 @@ }, { "name": "apiUrl", - "description": "Endpoint at which prometheus can be queried", + "description": "Endpoint at which prometheus can be queried.", "type": { "kind": "NON_NULL", "name": null, @@ -54132,7 +58108,7 @@ }, { "name": "integration", - "description": "The newly created integration", + "description": "The newly created integration.", "args": [ ], @@ -54160,7 +58136,7 @@ "inputFields": [ { "name": "id", - "description": "The ID of the integration to mutate", + "description": "The ID of the integration to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -54234,7 +58210,7 @@ }, { "name": "integration", - "description": "The newly created integration", + "description": "The newly created integration.", "args": [ ], @@ -54262,7 +58238,7 @@ "inputFields": [ { "name": "id", - "description": "The ID of the integration to mutate", + "description": "The ID of the integration to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -54276,7 +58252,7 @@ }, { "name": "active", - "description": "Whether the integration is receiving alerts", + "description": "Whether the integration is receiving alerts.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -54286,7 +58262,7 @@ }, { "name": "apiUrl", - "description": "Endpoint at which prometheus can be queried", + "description": "Endpoint at which prometheus can be queried.", "type": { "kind": "SCALAR", "name": "String", @@ -54356,7 +58332,7 @@ }, { "name": "integration", - "description": "The newly created integration", + "description": "The newly created integration.", "args": [ ], @@ -54394,7 +58370,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the issue to mutate is in", + "description": "The project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -54408,7 +58384,7 @@ }, { "name": "iid", - "description": "The IID of the issue to mutate", + "description": "The IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -54422,7 +58398,7 @@ }, { "name": "groupPath", - "description": "The group the promoted epic will belong to", + "description": "The group the promoted epic will belong to.", "type": { "kind": "SCALAR", "name": "ID", @@ -54466,7 +58442,7 @@ }, { "name": "epic", - "description": "The epic after issue promotion", + "description": "The epic after issue promotion.", "args": [ ], @@ -54506,7 +58482,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -54536,8 +58512,22 @@ "description": "Get linted and processed contents of a CI config. Should not be requested more than once per request.", "args": [ { + "name": "projectPath", + "description": "The project of the CI config.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { "name": "content", - "description": "Contents of .gitlab-ci.yml", + "description": "Contents of '.gitlab-ci.yml'.", "type": { "kind": "NON_NULL", "name": null, @@ -54548,6 +58538,16 @@ } }, "defaultValue": null + }, + { + "name": "dryRun", + "description": "Run pipeline creation simulation, or only do static check.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null } ], "type": { @@ -54676,7 +58676,7 @@ "args": [ { "name": "text", - "description": "Text to echo back", + "description": "Text to echo back.", "type": { "kind": "NON_NULL", "name": null, @@ -54730,7 +58730,7 @@ "args": [ { "name": "fullPath", - "description": "The full path of the project, group or namespace, e.g., \"gitlab-org/gitlab-foss\"", + "description": "The full path of the project, group or namespace, e.g., \"gitlab-org/gitlab-foss\".", "type": { "kind": "NON_NULL", "name": null, @@ -54771,7 +58771,7 @@ "args": [ { "name": "identifier", - "description": "The type of measurement/statistics to retrieve", + "description": "The type of measurement/statistics to retrieve.", "type": { "kind": "NON_NULL", "name": null, @@ -54785,7 +58785,7 @@ }, { "name": "recordedAfter", - "description": "Measurement recorded after this date", + "description": "Measurement recorded after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -54795,7 +58795,7 @@ }, { "name": "recordedBefore", - "description": "Measurement recorded before this date", + "description": "Measurement recorded before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -54953,7 +58953,7 @@ "args": [ { "name": "fullPath", - "description": "The full path of the project, group or namespace, e.g., \"gitlab-org/gitlab-foss\"", + "description": "The full path of the project, group or namespace, e.g., \"gitlab-org/gitlab-foss\".", "type": { "kind": "NON_NULL", "name": null, @@ -54975,12 +58975,39 @@ "deprecationReason": null }, { + "name": "packageComposerDetails", + "description": "Find a composer package", + "args": [ + { + "name": "id", + "description": "The global ID of the package.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "PackagesPackageID", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "PackageComposerDetails", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "project", "description": "Find a project", "args": [ { "name": "fullPath", - "description": "The full path of the project, group or namespace, e.g., \"gitlab-org/gitlab-foss\"", + "description": "The full path of the project, group or namespace, e.g., \"gitlab-org/gitlab-foss\".", "type": { "kind": "NON_NULL", "name": null, @@ -55007,7 +59034,7 @@ "args": [ { "name": "membership", - "description": "Limit projects that the current user is a member of", + "description": "Limit projects that the current user is a member of.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -55017,7 +59044,7 @@ }, { "name": "search", - "description": "Search query for project name, path, or description", + "description": "Search query for project name, path, or description.", "type": { "kind": "SCALAR", "name": "String", @@ -55027,7 +59054,7 @@ }, { "name": "ids", - "description": "Filter projects by IDs", + "description": "Filter projects by IDs.", "type": { "kind": "LIST", "name": null, @@ -55045,7 +59072,7 @@ }, { "name": "searchNamespaces", - "description": "Include namespace in project search", + "description": "Include namespace in project search.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -55055,7 +59082,7 @@ }, { "name": "sort", - "description": "Sort order of results", + "description": "Sort order of results.", "type": { "kind": "SCALAR", "name": "String", @@ -55171,7 +59198,7 @@ "args": [ { "name": "platform", - "description": "Platform to generate the instructions for", + "description": "Platform to generate the instructions for.", "type": { "kind": "NON_NULL", "name": null, @@ -55185,7 +59212,7 @@ }, { "name": "architecture", - "description": "Architecture to generate the instructions for", + "description": "Architecture to generate the instructions for.", "type": { "kind": "NON_NULL", "name": null, @@ -55199,7 +59226,7 @@ }, { "name": "projectId", - "description": "Project to register the runner for", + "description": "Project to register the runner for.", "type": { "kind": "SCALAR", "name": "ProjectID", @@ -55209,7 +59236,7 @@ }, { "name": "groupId", - "description": "Group to register the runner for", + "description": "Group to register the runner for.", "type": { "kind": "SCALAR", "name": "GroupID", @@ -55232,7 +59259,7 @@ "args": [ { "name": "ids", - "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\"", + "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\".", "type": { "kind": "LIST", "name": null, @@ -55250,7 +59277,7 @@ }, { "name": "visibility", - "description": "The visibility of the snippet", + "description": "The visibility of the snippet.", "type": { "kind": "ENUM", "name": "VisibilityScopesEnum", @@ -55260,7 +59287,7 @@ }, { "name": "authorId", - "description": "The ID of an author", + "description": "The ID of an author.", "type": { "kind": "SCALAR", "name": "UserID", @@ -55270,7 +59297,7 @@ }, { "name": "projectId", - "description": "The ID of a project", + "description": "The ID of a project.", "type": { "kind": "SCALAR", "name": "ProjectID", @@ -55280,7 +59307,7 @@ }, { "name": "type", - "description": "The type of snippet", + "description": "The type of snippet.", "type": { "kind": "ENUM", "name": "TypeEnum", @@ -55290,7 +59317,7 @@ }, { "name": "explore", - "description": "Explore personal snippets", + "description": "Explore personal snippets.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -55353,7 +59380,7 @@ "args": [ { "name": "id", - "description": "ID of the User", + "description": "ID of the User.", "type": { "kind": "SCALAR", "name": "UserID", @@ -55363,7 +59390,7 @@ }, { "name": "username", - "description": "Username of the User", + "description": "Username of the User.", "type": { "kind": "SCALAR", "name": "String", @@ -55386,7 +59413,7 @@ "args": [ { "name": "ids", - "description": "List of user Global IDs", + "description": "List of user Global IDs.", "type": { "kind": "LIST", "name": null, @@ -55404,7 +59431,7 @@ }, { "name": "usernames", - "description": "List of usernames", + "description": "List of usernames.", "type": { "kind": "LIST", "name": null, @@ -55422,7 +59449,7 @@ }, { "name": "sort", - "description": "Sort users by this criteria", + "description": "Sort users by this criteria.", "type": { "kind": "ENUM", "name": "Sort", @@ -55441,6 +59468,16 @@ "defaultValue": null }, { + "name": "admins", + "description": "Return only admin users.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": "false" + }, + { "name": "after", "description": "Returns the elements in the list that come after the specified cursor.", "type": { @@ -55495,7 +59532,7 @@ "args": [ { "name": "projectId", - "description": "Filter vulnerabilities by project", + "description": "Filter vulnerabilities by project.", "type": { "kind": "LIST", "name": null, @@ -55513,7 +59550,7 @@ }, { "name": "reportType", - "description": "Filter vulnerabilities by report type", + "description": "Filter vulnerabilities by report type.", "type": { "kind": "LIST", "name": null, @@ -55531,7 +59568,7 @@ }, { "name": "severity", - "description": "Filter vulnerabilities by severity", + "description": "Filter vulnerabilities by severity.", "type": { "kind": "LIST", "name": null, @@ -55549,7 +59586,7 @@ }, { "name": "state", - "description": "Filter vulnerabilities by state", + "description": "Filter vulnerabilities by state.", "type": { "kind": "LIST", "name": null, @@ -55567,7 +59604,7 @@ }, { "name": "scanner", - "description": "Filter vulnerabilities by scanner", + "description": "Filter vulnerabilities by VulnerabilityScanner.externalId.", "type": { "kind": "LIST", "name": null, @@ -55585,7 +59622,7 @@ }, { "name": "sort", - "description": "List vulnerabilities by sort order", + "description": "List vulnerabilities by sort order.", "type": { "kind": "ENUM", "name": "VulnerabilitySort", @@ -55595,7 +59632,7 @@ }, { "name": "hasResolution", - "description": "Returns only the vulnerabilities which have been resolved on default branch", + "description": "Returns only the vulnerabilities which have been resolved on default branch.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -55605,7 +59642,7 @@ }, { "name": "hasIssues", - "description": "Returns only the vulnerabilities which have linked issues", + "description": "Returns only the vulnerabilities which have linked issues.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -55668,7 +59705,7 @@ "args": [ { "name": "startDate", - "description": "First day for which to fetch vulnerability history", + "description": "First day for which to fetch vulnerability history.", "type": { "kind": "NON_NULL", "name": null, @@ -55682,7 +59719,7 @@ }, { "name": "endDate", - "description": "Last day for which to fetch vulnerability history", + "description": "Last day for which to fetch vulnerability history.", "type": { "kind": "NON_NULL", "name": null, @@ -55749,7 +59786,7 @@ "args": [ { "name": "startDate", - "description": "First day for which to fetch vulnerability history", + "description": "First day for which to fetch vulnerability history.", "type": { "kind": "NON_NULL", "name": null, @@ -55763,7 +59800,7 @@ }, { "name": "endDate", - "description": "Last day for which to fetch vulnerability history", + "description": "Last day for which to fetch vulnerability history.", "type": { "kind": "NON_NULL", "name": null, @@ -56743,7 +60780,7 @@ "inputFields": [ { "name": "projectPath", - "description": "Full path of the project the release is associated with", + "description": "Full path of the project the release is associated with.", "type": { "kind": "NON_NULL", "name": null, @@ -56757,7 +60794,7 @@ }, { "name": "tagName", - "description": "Name of the tag to associate with the release", + "description": "Name of the tag to associate with the release.", "type": { "kind": "NON_NULL", "name": null, @@ -56771,7 +60808,7 @@ }, { "name": "ref", - "description": "The commit SHA or branch name to use if creating a new tag", + "description": "The commit SHA or branch name to use if creating a new tag.", "type": { "kind": "SCALAR", "name": "String", @@ -56781,7 +60818,7 @@ }, { "name": "name", - "description": "Name of the release", + "description": "Name of the release.", "type": { "kind": "SCALAR", "name": "String", @@ -56791,7 +60828,7 @@ }, { "name": "description", - "description": "Description (also known as \"release notes\") of the release", + "description": "Description (also known as \"release notes\") of the release.", "type": { "kind": "SCALAR", "name": "String", @@ -56829,7 +60866,7 @@ }, { "name": "assets", - "description": "Assets associated to the release", + "description": "Assets associated to the release.", "type": { "kind": "INPUT_OBJECT", "name": "ReleaseAssetsInput", @@ -56899,7 +60936,7 @@ }, { "name": "release", - "description": "The release after mutation", + "description": "The release after mutation.", "args": [ ], @@ -56927,7 +60964,7 @@ "inputFields": [ { "name": "projectPath", - "description": "Full path of the project the release is associated with", + "description": "Full path of the project the release is associated with.", "type": { "kind": "NON_NULL", "name": null, @@ -57572,7 +61609,7 @@ "inputFields": [ { "name": "projectPath", - "description": "Full path of the project the release is associated with", + "description": "Full path of the project the release is associated with.", "type": { "kind": "NON_NULL", "name": null, @@ -57586,7 +61623,7 @@ }, { "name": "tagName", - "description": "Name of the tag associated with the release", + "description": "Name of the tag associated with the release.", "type": { "kind": "NON_NULL", "name": null, @@ -57600,7 +61637,7 @@ }, { "name": "name", - "description": "Name of the release", + "description": "Name of the release.", "type": { "kind": "SCALAR", "name": "String", @@ -57610,7 +61647,7 @@ }, { "name": "description", - "description": "Description (release notes) of the release", + "description": "Description (release notes) of the release.", "type": { "kind": "SCALAR", "name": "String", @@ -57620,7 +61657,7 @@ }, { "name": "releasedAt", - "description": "The release date", + "description": "The release date.", "type": { "kind": "SCALAR", "name": "Time", @@ -57736,7 +61773,7 @@ "inputFields": [ { "name": "awardableId", - "description": "The global ID of the awardable resource", + "description": "The global ID of the awardable resource.", "type": { "kind": "NON_NULL", "name": null, @@ -57784,7 +61821,7 @@ "fields": [ { "name": "awardEmoji", - "description": "The award emoji after mutation", + "description": "The award emoji after mutation.", "args": [ ], @@ -57852,7 +61889,7 @@ "inputFields": [ { "name": "id", - "description": "ID of the project to remove from the Instance Security Dashboard", + "description": "ID of the project to remove from the Instance Security Dashboard.", "type": { "kind": "NON_NULL", "name": null, @@ -57940,7 +61977,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the DiffNote to update", + "description": "The global ID of the DiffNote to update.", "type": { "kind": "NON_NULL", "name": null, @@ -58028,7 +62065,7 @@ }, { "name": "note", - "description": "The note after mutation", + "description": "The note after mutation.", "args": [ ], @@ -58109,7 +62146,7 @@ "args": [ { "name": "path", - "description": "The path to get the tree for. Default value is the root of the repository", + "description": "The path to get the tree for. Default value is the root of the repository.", "type": { "kind": "SCALAR", "name": "String", @@ -58119,7 +62156,7 @@ }, { "name": "ref", - "description": "The commit ref to get the tree for. Default value is HEAD", + "description": "The commit ref to get the tree for. Default value is HEAD.", "type": { "kind": "SCALAR", "name": "String", @@ -58129,7 +62166,7 @@ }, { "name": "recursive", - "description": "Used to get a recursive tree. Default is false", + "description": "Used to get a recursive tree. Default is false.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -58329,7 +62366,7 @@ "args": [ { "name": "sort", - "description": "List test reports by sort order", + "description": "List test reports by sort order.", "type": { "kind": "ENUM", "name": "Sort", @@ -58831,7 +62868,7 @@ "inputFields": [ { "name": "id", - "description": "ID of the vulnerability to be reverted", + "description": "ID of the vulnerability to be reverted.", "type": { "kind": "NON_NULL", "name": null, @@ -58905,7 +62942,7 @@ }, { "name": "vulnerability", - "description": "The vulnerability after revert", + "description": "The vulnerability after revert.", "args": [ ], @@ -62079,7 +66116,7 @@ "args": [ { "name": "id", - "description": "ID of the Sentry issue", + "description": "ID of the Sentry issue.", "type": { "kind": "NON_NULL", "name": null, @@ -62106,7 +66143,7 @@ "args": [ { "name": "id", - "description": "ID of the Sentry issue", + "description": "ID of the Sentry issue.", "type": { "kind": "NON_NULL", "name": null, @@ -62133,7 +66170,7 @@ "args": [ { "name": "searchTerm", - "description": "Search query for the Sentry error details", + "description": "Search query for the Sentry error details.", "type": { "kind": "SCALAR", "name": "String", @@ -62143,7 +66180,7 @@ }, { "name": "sort", - "description": "Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default", + "description": "Attribute to sort on. Options are frequency, first_seen, last_seen. last_seen is default.", "type": { "kind": "SCALAR", "name": "String", @@ -62845,12 +66882,6 @@ "interfaces": null, "enumValues": [ { - "name": "ALERTS_SERVICE", - "description": null, - "isDeprecated": false, - "deprecationReason": null - }, - { "name": "ASANA_SERVICE", "description": null, "isDeprecated": false, @@ -63112,7 +67143,7 @@ "args": [ { "name": "paths", - "description": "Paths of the blobs", + "description": "Paths of the blobs.", "type": { "kind": "LIST", "name": null, @@ -65247,7 +69278,7 @@ "inputFields": [ { "name": "id", - "description": "Global ID of the Terraform state", + "description": "Global ID of the Terraform state.", "type": { "kind": "NON_NULL", "name": null, @@ -65390,7 +69421,7 @@ "inputFields": [ { "name": "id", - "description": "Global ID of the Terraform state", + "description": "Global ID of the Terraform state.", "type": { "kind": "NON_NULL", "name": null, @@ -65478,7 +69509,7 @@ "inputFields": [ { "name": "id", - "description": "Global ID of the Terraform state", + "description": "Global ID of the Terraform state.", "type": { "kind": "NON_NULL", "name": null, @@ -66878,7 +70909,7 @@ "inputFields": [ { "name": "targetId", - "description": "The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported", + "description": "The global ID of the to-do item's parent. Issues, merge requests, designs and epics are supported.", "type": { "kind": "NON_NULL", "name": null, @@ -66952,7 +70983,7 @@ }, { "name": "todo", - "description": "The to-do created", + "description": "The to-do created.", "args": [ ], @@ -67035,7 +71066,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the todo to mark as done", + "description": "The global ID of the todo to mark as done.", "type": { "kind": "NON_NULL", "name": null, @@ -67109,7 +71140,7 @@ }, { "name": "todo", - "description": "The requested todo", + "description": "The requested todo.", "args": [ ], @@ -67141,7 +71172,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the todo to restore", + "description": "The global ID of the todo to restore.", "type": { "kind": "NON_NULL", "name": null, @@ -67176,7 +71207,7 @@ "inputFields": [ { "name": "ids", - "description": "The global IDs of the todos to restore (a maximum of 50 is supported at once)", + "description": "The global IDs of the todos to restore (a maximum of 50 is supported at once).", "type": { "kind": "NON_NULL", "name": null, @@ -67258,7 +71289,7 @@ }, { "name": "todos", - "description": "Updated todos", + "description": "Updated todos.", "args": [ ], @@ -67284,7 +71315,7 @@ }, { "name": "updatedIds", - "description": "The IDs of the updated todo items Deprecated in 13.2: Use todos.", + "description": "The IDs of the updated todo items. Deprecated in 13.2: Use todos.", "args": [ ], @@ -67363,7 +71394,7 @@ }, { "name": "todo", - "description": "The requested todo", + "description": "The requested todo.", "args": [ ], @@ -67535,7 +71566,7 @@ }, { "name": "todos", - "description": "Updated todos", + "description": "Updated todos.", "args": [ ], @@ -67561,7 +71592,7 @@ }, { "name": "updatedIds", - "description": "Ids of the updated todos Deprecated in 13.2: Use todos.", + "description": "Ids of the updated todos. Deprecated in 13.2: Use todos.", "args": [ ], @@ -67601,7 +71632,7 @@ "inputFields": [ { "name": "awardableId", - "description": "The global ID of the awardable resource", + "description": "The global ID of the awardable resource.", "type": { "kind": "NON_NULL", "name": null, @@ -67649,7 +71680,7 @@ "fields": [ { "name": "awardEmoji", - "description": "The award emoji after mutation", + "description": "The award emoji after mutation.", "args": [ ], @@ -68231,7 +72262,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the alert to mutate is in", + "description": "The project the alert to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -68245,7 +72276,7 @@ }, { "name": "iid", - "description": "The IID of the alert to mutate", + "description": "The IID of the alert to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -68259,7 +72290,7 @@ }, { "name": "status", - "description": "The status to set the alert", + "description": "The status to set the alert.", "type": { "kind": "NON_NULL", "name": null, @@ -68293,7 +72324,7 @@ "fields": [ { "name": "alert", - "description": "The alert after mutation", + "description": "The alert after mutation.", "args": [ ], @@ -68347,7 +72378,7 @@ }, { "name": "issue", - "description": "The issue created after mutation", + "description": "The issue created after mutation.", "args": [ ], @@ -68361,7 +72392,7 @@ }, { "name": "todo", - "description": "The todo after mutation", + "description": "The todo after mutation.", "args": [ ], @@ -68389,7 +72420,7 @@ "inputFields": [ { "name": "boardId", - "description": "The board global ID", + "description": "The board global ID.", "type": { "kind": "NON_NULL", "name": null, @@ -68403,7 +72434,7 @@ }, { "name": "epicId", - "description": "ID of an epic to set preferences for", + "description": "ID of an epic to set preferences for.", "type": { "kind": "NON_NULL", "name": null, @@ -68417,7 +72448,7 @@ }, { "name": "collapsed", - "description": "Whether the epic should be collapsed in the board", + "description": "Whether the epic should be collapsed in the board.", "type": { "kind": "NON_NULL", "name": null, @@ -68465,7 +72496,7 @@ }, { "name": "epicUserPreferences", - "description": "User preferences for the epic in the board after mutation", + "description": "User preferences for the epic in the board after mutation.", "args": [ ], @@ -68562,6 +72593,82 @@ "defaultValue": null }, { + "name": "assigneeId", + "description": "The ID of user to be assigned to the board.", + "type": { + "kind": "SCALAR", + "name": "UserID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "milestoneId", + "description": "The ID of milestone to be assigned to the board.", + "type": { + "kind": "SCALAR", + "name": "MilestoneID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "iterationId", + "description": "The ID of iteration to be assigned to the board.", + "type": { + "kind": "SCALAR", + "name": "IterationID", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "weight", + "description": "The weight value to be assigned to the board.", + "type": { + "kind": "SCALAR", + "name": "Int", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "labels", + "description": "Labels of the issue", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + }, + "defaultValue": null + }, + { + "name": "labelIds", + "description": "The IDs of labels to be added to the board.", + "type": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "LabelID", + "ofType": null + } + } + }, + "defaultValue": null + }, + { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", "type": { @@ -68598,7 +72705,7 @@ }, { "name": "position", - "description": "Position of list within the board", + "description": "Position of list within the board.", "type": { "kind": "SCALAR", "name": "Int", @@ -68608,7 +72715,7 @@ }, { "name": "collapsed", - "description": "Indicates if list is collapsed for this user", + "description": "Indicates if list is collapsed for this user.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -68678,7 +72785,7 @@ }, { "name": "list", - "description": "Mutated list", + "description": "Mutated list.", "args": [ ], @@ -68773,7 +72880,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the compliance framework to update", + "description": "The global ID of the compliance framework to update.", "type": { "kind": "NON_NULL", "name": null, @@ -68786,32 +72893,16 @@ "defaultValue": null }, { - "name": "name", - "description": "New name for the compliance framework", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "description", - "description": "New description for the compliance framework", - "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null - }, - "defaultValue": null - }, - { - "name": "color", - "description": "New color representation of the compliance framework in hex format. e.g. #FCA121", + "name": "params", + "description": "Parameters to update the compliance framework with.", "type": { - "kind": "SCALAR", - "name": "String", - "ofType": null + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "ComplianceFrameworkInput", + "ofType": null + } }, "defaultValue": null }, @@ -68851,7 +72942,7 @@ }, { "name": "complianceFramework", - "description": "The compliance framework after mutation", + "description": "The compliance framework after mutation.", "args": [ ], @@ -68905,7 +72996,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project path where the container expiration policy is located", + "description": "The project path where the container expiration policy is located.", "type": { "kind": "NON_NULL", "name": null, @@ -69013,7 +73104,7 @@ }, { "name": "containerExpirationPolicy", - "description": "The container expiration policy after mutation", + "description": "The container expiration policy after mutation.", "args": [ ], @@ -69067,7 +73158,7 @@ "inputFields": [ { "name": "name", - "description": "Name of the segment", + "description": "Name of the segment.", "type": { "kind": "NON_NULL", "name": null, @@ -69081,7 +73172,7 @@ }, { "name": "groupIds", - "description": "The array of group IDs to set for the segment", + "description": "The array of group IDs to set for the segment.", "type": { "kind": "LIST", "name": null, @@ -69099,7 +73190,7 @@ }, { "name": "id", - "description": "ID of the segment", + "description": "ID of the segment.", "type": { "kind": "NON_NULL", "name": null, @@ -69173,7 +73264,7 @@ }, { "name": "segment", - "description": "The segment after mutation", + "description": "The segment after mutation.", "args": [ ], @@ -69252,7 +73343,7 @@ "inputFields": [ { "name": "iid", - "description": "The IID of the epic to mutate", + "description": "The IID of the epic to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -69266,7 +73357,7 @@ }, { "name": "groupPath", - "description": "The group the epic to mutate is in", + "description": "The group the epic to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -69280,7 +73371,7 @@ }, { "name": "title", - "description": "The title of the epic", + "description": "The title of the epic.", "type": { "kind": "SCALAR", "name": "String", @@ -69290,7 +73381,7 @@ }, { "name": "description", - "description": "The description of the epic", + "description": "The description of the epic.", "type": { "kind": "SCALAR", "name": "String", @@ -69300,7 +73391,7 @@ }, { "name": "confidential", - "description": "Indicates if the epic is confidential", + "description": "Indicates if the epic is confidential.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -69310,7 +73401,7 @@ }, { "name": "startDateFixed", - "description": "The start date of the epic", + "description": "The start date of the epic.", "type": { "kind": "SCALAR", "name": "String", @@ -69320,7 +73411,7 @@ }, { "name": "dueDateFixed", - "description": "The end date of the epic", + "description": "The end date of the epic.", "type": { "kind": "SCALAR", "name": "String", @@ -69330,7 +73421,7 @@ }, { "name": "startDateIsFixed", - "description": "Indicates start date should be sourced from start_date_fixed field not the issue milestones", + "description": "Indicates start date should be sourced from start_date_fixed field not the issue milestones.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -69340,7 +73431,7 @@ }, { "name": "dueDateIsFixed", - "description": "Indicates end date should be sourced from due_date_fixed field not the issue milestones", + "description": "Indicates end date should be sourced from due_date_fixed field not the issue milestones.", "type": { "kind": "SCALAR", "name": "Boolean", @@ -69386,7 +73477,7 @@ }, { "name": "stateEvent", - "description": "State event for the epic", + "description": "State event for the epic.", "type": { "kind": "ENUM", "name": "EpicStateEvent", @@ -69430,7 +73521,7 @@ }, { "name": "epic", - "description": "The epic after mutation", + "description": "The epic after mutation.", "args": [ ], @@ -69484,7 +73575,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the note to update", + "description": "The global ID of the note to update.", "type": { "kind": "NON_NULL", "name": null, @@ -69578,7 +73669,7 @@ }, { "name": "note", - "description": "The note after mutation", + "description": "The note after mutation.", "args": [ ], @@ -69606,7 +73697,7 @@ "inputFields": [ { "name": "projectPath", - "description": "The project the issue to mutate is in", + "description": "The project the issue to mutate is in.", "type": { "kind": "NON_NULL", "name": null, @@ -69620,7 +73711,7 @@ }, { "name": "iid", - "description": "The IID of the issue to mutate", + "description": "The IID of the issue to mutate.", "type": { "kind": "NON_NULL", "name": null, @@ -69684,7 +73775,7 @@ }, { "name": "milestoneId", - "description": "The ID of the milestone to assign to the issue. On update milestone will be removed if set to null", + "description": "The ID of the milestone to assign to the issue. On update milestone will be removed if set to null.", "type": { "kind": "SCALAR", "name": "ID", @@ -69694,7 +73785,7 @@ }, { "name": "addLabelIds", - "description": "The IDs of labels to be added to the issue", + "description": "The IDs of labels to be added to the issue.", "type": { "kind": "LIST", "name": null, @@ -69712,7 +73803,7 @@ }, { "name": "removeLabelIds", - "description": "The IDs of labels to be removed from the issue", + "description": "The IDs of labels to be removed from the issue.", "type": { "kind": "LIST", "name": null, @@ -69730,7 +73821,7 @@ }, { "name": "stateEvent", - "description": "Close or reopen an issue", + "description": "Close or reopen an issue.", "type": { "kind": "ENUM", "name": "IssueStateEvent", @@ -69740,7 +73831,7 @@ }, { "name": "healthStatus", - "description": "The desired health status", + "description": "The desired health status.", "type": { "kind": "ENUM", "name": "HealthStatus", @@ -69750,7 +73841,7 @@ }, { "name": "weight", - "description": "The weight of the issue", + "description": "The weight of the issue.", "type": { "kind": "SCALAR", "name": "Int", @@ -69760,7 +73851,7 @@ }, { "name": "epicId", - "description": "The ID of the parent epic. NULL when removing the association", + "description": "The ID of the parent epic. NULL when removing the association.", "type": { "kind": "SCALAR", "name": "EpicID", @@ -69830,7 +73921,7 @@ }, { "name": "issue", - "description": "The issue after mutation", + "description": "The issue after mutation.", "args": [ ], @@ -70008,13 +74099,135 @@ }, { "kind": "INPUT_OBJECT", + "name": "UpdateNamespacePackageSettingsInput", + "description": "Autogenerated input type of UpdateNamespacePackageSettings", + "fields": null, + "inputFields": [ + { + "name": "namespacePath", + "description": "The namespace path where the namespace package setting is located.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "mavenDuplicatesAllowed", + "description": "Indicates whether duplicate Maven packages are allowed for this namespace.", + "type": { + "kind": "SCALAR", + "name": "Boolean", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "mavenDuplicateExceptionRegex", + "description": "When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect.", + "type": { + "kind": "SCALAR", + "name": "UntrustedRegexp", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "UpdateNamespacePackageSettingsPayload", + "description": "Autogenerated return type of UpdateNamespacePackageSettings", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "packageSettings", + "description": "The namespace package setting after mutation.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "PackageSettings", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "INPUT_OBJECT", "name": "UpdateNoteInput", "description": "Autogenerated input type of UpdateNote", "fields": null, "inputFields": [ { "name": "id", - "description": "The global ID of the note to update", + "description": "The global ID of the note to update.", "type": { "kind": "NON_NULL", "name": null, @@ -70108,7 +74321,7 @@ }, { "name": "note", - "description": "The note after mutation", + "description": "The note after mutation.", "args": [ ], @@ -70136,7 +74349,7 @@ "inputFields": [ { "name": "title", - "description": "Title of the requirement", + "description": "Title of the requirement.", "type": { "kind": "SCALAR", "name": "String", @@ -70146,7 +74359,7 @@ }, { "name": "description", - "description": "Description of the requirement", + "description": "Description of the requirement.", "type": { "kind": "SCALAR", "name": "String", @@ -70156,7 +74369,7 @@ }, { "name": "projectPath", - "description": "Full project path the requirement is associated with", + "description": "Full project path the requirement is associated with.", "type": { "kind": "NON_NULL", "name": null, @@ -70170,7 +74383,7 @@ }, { "name": "state", - "description": "State of the requirement", + "description": "State of the requirement.", "type": { "kind": "ENUM", "name": "RequirementState", @@ -70180,7 +74393,7 @@ }, { "name": "iid", - "description": "The IID of the requirement to update", + "description": "The IID of the requirement to update.", "type": { "kind": "NON_NULL", "name": null, @@ -70194,7 +74407,7 @@ }, { "name": "lastTestReportState", - "description": "Creates a test report for the requirement with the given state", + "description": "Creates a test report for the requirement with the given state.", "type": { "kind": "ENUM", "name": "TestReportState", @@ -70264,7 +74477,7 @@ }, { "name": "requirement", - "description": "Requirement after mutation", + "description": "Requirement after mutation.", "args": [ ], @@ -70292,7 +74505,7 @@ "inputFields": [ { "name": "id", - "description": "The global ID of the snippet to update", + "description": "The global ID of the snippet to update.", "type": { "kind": "NON_NULL", "name": null, @@ -70306,7 +74519,7 @@ }, { "name": "title", - "description": "Title of the snippet", + "description": "Title of the snippet.", "type": { "kind": "SCALAR", "name": "String", @@ -70316,7 +74529,7 @@ }, { "name": "description", - "description": "Description of the snippet", + "description": "Description of the snippet.", "type": { "kind": "SCALAR", "name": "String", @@ -70326,7 +74539,7 @@ }, { "name": "visibilityLevel", - "description": "The visibility level of the snippet", + "description": "The visibility level of the snippet.", "type": { "kind": "ENUM", "name": "VisibilityLevelsEnum", @@ -70336,7 +74549,7 @@ }, { "name": "blobActions", - "description": "Actions to perform over the snippet repository and blobs", + "description": "Actions to perform over the snippet repository and blobs.", "type": { "kind": "LIST", "name": null, @@ -70414,7 +74627,7 @@ }, { "name": "snippet", - "description": "The snippet after mutation", + "description": "The snippet after mutation.", "args": [ ], @@ -70428,7 +74641,7 @@ }, { "name": "spam", - "description": "Indicates whether the operation returns a record detected as spam", + "description": "Indicates whether the operation returns a record detected as spam.", "args": [ ], @@ -70469,7 +74682,7 @@ "args": [ { "name": "iids", - "description": "Array of IIDs of merge requests, for example `[1, 2]`", + "description": "Array of IIDs of merge requests, for example `[1, 2]`.", "type": { "kind": "LIST", "name": null, @@ -70551,7 +74764,7 @@ }, { "name": "mergedAfter", - "description": "Merge requests merged after this date", + "description": "Merge requests merged after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -70561,7 +74774,7 @@ }, { "name": "mergedBefore", - "description": "Merge requests merged before this date", + "description": "Merge requests merged before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -70571,7 +74784,7 @@ }, { "name": "milestoneTitle", - "description": "Title of the milestone", + "description": "Title of the milestone.", "type": { "kind": "SCALAR", "name": "String", @@ -70581,7 +74794,7 @@ }, { "name": "sort", - "description": "Sort merge requests by this criteria", + "description": "Sort merge requests by this criteria.", "type": { "kind": "ENUM", "name": "MergeRequestSort", @@ -70611,7 +74824,7 @@ }, { "name": "authorUsername", - "description": "Username of the author", + "description": "Username of the author.", "type": { "kind": "SCALAR", "name": "String", @@ -70621,7 +74834,7 @@ }, { "name": "reviewerUsername", - "description": "Username of the reviewer", + "description": "Username of the reviewer.", "type": { "kind": "SCALAR", "name": "String", @@ -70684,7 +74897,7 @@ "args": [ { "name": "iids", - "description": "Array of IIDs of merge requests, for example `[1, 2]`", + "description": "Array of IIDs of merge requests, for example `[1, 2]`.", "type": { "kind": "LIST", "name": null, @@ -70766,7 +74979,7 @@ }, { "name": "mergedAfter", - "description": "Merge requests merged after this date", + "description": "Merge requests merged after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -70776,7 +74989,7 @@ }, { "name": "mergedBefore", - "description": "Merge requests merged before this date", + "description": "Merge requests merged before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -70786,7 +74999,7 @@ }, { "name": "milestoneTitle", - "description": "Title of the milestone", + "description": "Title of the milestone.", "type": { "kind": "SCALAR", "name": "String", @@ -70796,7 +75009,7 @@ }, { "name": "sort", - "description": "Sort merge requests by this criteria", + "description": "Sort merge requests by this criteria.", "type": { "kind": "ENUM", "name": "MergeRequestSort", @@ -70826,7 +75039,7 @@ }, { "name": "assigneeUsername", - "description": "Username of the assignee", + "description": "Username of the assignee.", "type": { "kind": "SCALAR", "name": "String", @@ -70836,7 +75049,7 @@ }, { "name": "reviewerUsername", - "description": "Username of the reviewer", + "description": "Username of the reviewer.", "type": { "kind": "SCALAR", "name": "String", @@ -71111,7 +75324,7 @@ "args": [ { "name": "iids", - "description": "Array of IIDs of merge requests, for example `[1, 2]`", + "description": "Array of IIDs of merge requests, for example `[1, 2]`.", "type": { "kind": "LIST", "name": null, @@ -71193,7 +75406,7 @@ }, { "name": "mergedAfter", - "description": "Merge requests merged after this date", + "description": "Merge requests merged after this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -71203,7 +75416,7 @@ }, { "name": "mergedBefore", - "description": "Merge requests merged before this date", + "description": "Merge requests merged before this date.", "type": { "kind": "SCALAR", "name": "Time", @@ -71213,7 +75426,7 @@ }, { "name": "milestoneTitle", - "description": "Title of the milestone", + "description": "Title of the milestone.", "type": { "kind": "SCALAR", "name": "String", @@ -71223,7 +75436,7 @@ }, { "name": "sort", - "description": "Sort merge requests by this criteria", + "description": "Sort merge requests by this criteria.", "type": { "kind": "ENUM", "name": "MergeRequestSort", @@ -71253,7 +75466,7 @@ }, { "name": "authorUsername", - "description": "Username of the author", + "description": "Username of the author.", "type": { "kind": "SCALAR", "name": "String", @@ -71263,7 +75476,7 @@ }, { "name": "assigneeUsername", - "description": "Username of the assignee", + "description": "Username of the assignee.", "type": { "kind": "SCALAR", "name": "String", @@ -71326,7 +75539,7 @@ "args": [ { "name": "ids", - "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\"", + "description": "Array of global snippet ids, e.g., \"gid://gitlab/ProjectSnippet/1\".", "type": { "kind": "LIST", "name": null, @@ -71344,7 +75557,7 @@ }, { "name": "visibility", - "description": "The visibility of the snippet", + "description": "The visibility of the snippet.", "type": { "kind": "ENUM", "name": "VisibilityScopesEnum", @@ -71354,7 +75567,7 @@ }, { "name": "type", - "description": "The type of snippet", + "description": "The type of snippet.", "type": { "kind": "ENUM", "name": "TypeEnum", @@ -71417,7 +75630,7 @@ "args": [ { "name": "search", - "description": "Search query", + "description": "Search query.", "type": { "kind": "SCALAR", "name": "String", @@ -71512,7 +75725,7 @@ "args": [ { "name": "action", - "description": "The action to be filtered", + "description": "The action to be filtered.", "type": { "kind": "LIST", "name": null, @@ -71530,7 +75743,7 @@ }, { "name": "authorId", - "description": "The ID of an author", + "description": "The ID of an author.", "type": { "kind": "LIST", "name": null, @@ -71548,7 +75761,7 @@ }, { "name": "projectId", - "description": "The ID of a project", + "description": "The ID of a project.", "type": { "kind": "LIST", "name": null, @@ -71566,7 +75779,7 @@ }, { "name": "groupId", - "description": "The ID of a group", + "description": "The ID of a group.", "type": { "kind": "LIST", "name": null, @@ -71584,7 +75797,7 @@ }, { "name": "state", - "description": "The state of the todo", + "description": "The state of the todo.", "type": { "kind": "LIST", "name": null, @@ -71602,7 +75815,7 @@ }, { "name": "type", - "description": "The type of the todo", + "description": "The type of the todo.", "type": { "kind": "LIST", "name": null, @@ -72530,6 +76743,20 @@ "deprecationReason": null }, { + "name": "confirmedBy", + "description": "The user that confirmed the vulnerability.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "description", "description": "Description of the vulnerability", "args": [ @@ -72633,6 +76860,20 @@ "deprecationReason": null }, { + "name": "dismissedBy", + "description": "The user that dismissed the vulnerability.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "externalIssueLinks", "description": "List of external issue links related to the vulnerability", "args": [ @@ -72753,7 +76994,7 @@ "args": [ { "name": "linkType", - "description": "Filter issue links by link type", + "description": "Filter issue links by link type.", "type": { "kind": "ENUM", "name": "VulnerabilityIssueLinkType", @@ -72956,6 +77197,20 @@ "deprecationReason": null }, { + "name": "resolvedBy", + "description": "The user that resolved the vulnerability.", + "args": [ + + ], + "type": { + "kind": "OBJECT", + "name": "User", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { "name": "resolvedOnDefaultBranch", "description": "Indicates whether the vulnerability is fixed on the default branch or not", "args": [ @@ -73099,7 +77354,7 @@ "inputFields": [ { "name": "id", - "description": "ID of the vulnerability to be confirmed", + "description": "ID of the vulnerability to be confirmed.", "type": { "kind": "NON_NULL", "name": null, @@ -73173,7 +77428,7 @@ }, { "name": "vulnerability", - "description": "The vulnerability after state change", + "description": "The vulnerability after state change.", "args": [ ], @@ -73268,7 +77523,7 @@ "inputFields": [ { "name": "id", - "description": "ID of the vulnerability to be dismissed", + "description": "ID of the vulnerability to be dismissed.", "type": { "kind": "NON_NULL", "name": null, @@ -73282,7 +77537,7 @@ }, { "name": "comment", - "description": "Reason why vulnerability should be dismissed", + "description": "Comment why vulnerability should be dismissed.", "type": { "kind": "SCALAR", "name": "String", @@ -73291,6 +77546,16 @@ "defaultValue": null }, { + "name": "dismissalReason", + "description": "Reason why vulnerability should be dismissed.", + "type": { + "kind": "ENUM", + "name": "VulnerabilityDismissalReason", + "ofType": null + }, + "defaultValue": null + }, + { "name": "clientMutationId", "description": "A unique identifier for the client performing the mutation.", "type": { @@ -73352,7 +77617,7 @@ }, { "name": "vulnerability", - "description": "The vulnerability after dismissal", + "description": "The vulnerability after dismissal.", "args": [ ], @@ -73373,6 +77638,47 @@ "possibleTypes": null }, { + "kind": "ENUM", + "name": "VulnerabilityDismissalReason", + "description": "The dismissal reason of the Vulnerability", + "fields": null, + "inputFields": null, + "interfaces": null, + "enumValues": [ + { + "name": "ACCEPTABLE_RISK", + "description": "The likelihood of the Vulnerability occurring and its impact are deemed acceptable", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "FALSE_POSITIVE", + "description": "The Vulnerability was incorrectly identified as being present", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "MITIGATING_CONTROL", + "description": "There is a mitigating control that eliminates the Vulnerability or makes its risk acceptable", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "USED_IN_TESTS", + "description": "The Vulnerability is used in tests and does not pose an actual risk", + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "NOT_APPLICABLE", + "description": "Other reasons for dismissal", + "isDeprecated": false, + "deprecationReason": null + } + ], + "possibleTypes": null + }, + { "kind": "OBJECT", "name": "VulnerabilityEdge", "description": "An edge in a connection.", @@ -74857,7 +79163,7 @@ "inputFields": [ { "name": "id", - "description": "ID of the vulnerability to be resolved", + "description": "ID of the vulnerability to be resolved.", "type": { "kind": "NON_NULL", "name": null, @@ -74931,7 +79237,7 @@ }, { "name": "vulnerability", - "description": "The vulnerability after state change", + "description": "The vulnerability after state change.", "args": [ ], @@ -74959,7 +79265,7 @@ "inputFields": [ { "name": "id", - "description": "ID of the vulnerability to be reverted", + "description": "ID of the vulnerability to be reverted.", "type": { "kind": "NON_NULL", "name": null, @@ -75033,7 +79339,7 @@ }, { "name": "vulnerability", - "description": "The vulnerability after revert", + "description": "The vulnerability after revert.", "args": [ ], diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 4cb79d71ab5..c098de16ef6 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -50,7 +50,7 @@ Autogenerated return type of AddAwardEmoji. | Field | Type | Description | | ----- | ---- | ----------- | -| `awardEmoji` | AwardEmoji | The award emoji after mutation | +| `awardEmoji` | AwardEmoji | The award emoji after mutation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | @@ -62,7 +62,7 @@ Autogenerated return type of AddProjectToSecurityDashboard. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `project` | Project | Project that was added to the Instance Security Dashboard | +| `project` | Project | Project that was added to the Instance Security Dashboard. | ### AdminSidekiqQueuesDeleteJobsPayload @@ -72,7 +72,7 @@ Autogenerated return type of AdminSidekiqQueuesDeleteJobs. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `result` | DeleteJobsResponse | Information about the status of the deletion request | +| `result` | DeleteJobsResponse | Information about the status of the deletion request. | ### AlertManagementAlert @@ -152,11 +152,11 @@ Autogenerated return type of AlertSetAssignees. | Field | Type | Description | | ----- | ---- | ----------- | -| `alert` | AlertManagementAlert | The alert after mutation | +| `alert` | AlertManagementAlert | The alert after mutation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue created after mutation | -| `todo` | Todo | The todo after mutation | +| `issue` | Issue | The issue created after mutation. | +| `todo` | Todo | The todo after mutation. | ### AlertTodoCreatePayload @@ -164,11 +164,11 @@ Autogenerated return type of AlertTodoCreate. | Field | Type | Description | | ----- | ---- | ----------- | -| `alert` | AlertManagementAlert | The alert after mutation | +| `alert` | AlertManagementAlert | The alert after mutation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue created after mutation | -| `todo` | Todo | The todo after mutation | +| `issue` | Issue | The issue created after mutation. | +| `todo` | Todo | The todo after mutation. | ### AwardEmoji @@ -189,7 +189,7 @@ Autogenerated return type of AwardEmojiAdd. | Field | Type | Description | | ----- | ---- | ----------- | -| `awardEmoji` | AwardEmoji | The award emoji after mutation | +| `awardEmoji` | AwardEmoji | The award emoji after mutation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | @@ -199,7 +199,7 @@ Autogenerated return type of AwardEmojiRemove. | Field | Type | Description | | ----- | ---- | ----------- | -| `awardEmoji` | AwardEmoji | The award emoji after mutation | +| `awardEmoji` | AwardEmoji | The award emoji after mutation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | @@ -209,7 +209,7 @@ Autogenerated return type of AwardEmojiToggle. | Field | Type | Description | | ----- | ---- | ----------- | -| `awardEmoji` | AwardEmoji | The award emoji after mutation | +| `awardEmoji` | AwardEmoji | The award emoji after mutation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | | `toggledOn` | Boolean! | Indicates the status of the emoji. True if the toggle awarded the emoji, and false if the toggle removed the emoji. | @@ -252,6 +252,8 @@ Represents a project or group board. | `lists` | BoardListConnection | Lists of the board | | `milestone` | Milestone | The board milestone | | `name` | String | Name of the board | +| `webPath` | String! | Web path of the board. | +| `webUrl` | String! | Web URL of the board. | | `weight` | Int | Weight of the board | ### BoardEpic @@ -325,6 +327,7 @@ Represents a list for an issue board. | `id` | ID! | ID (global ID) of the list | | `issues` | IssueConnection | Board issues | | `issuesCount` | Int | Count of issues in the list | +| `iteration` | Iteration | Iteration of the list | | `label` | Label | Label of the list | | `limitMetric` | ListLimitMetric | The current limit metric for the list | | `listType` | String! | Type of the list | @@ -343,7 +346,7 @@ Autogenerated return type of BoardListCreate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `list` | BoardList | List of the issue board | +| `list` | BoardList | List of the issue board. | ### BoardListUpdateLimitMetricsPayload @@ -353,7 +356,7 @@ Autogenerated return type of BoardListUpdateLimitMetrics. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `list` | BoardList | The updated list | +| `list` | BoardList | The updated list. | ### Branch @@ -374,20 +377,35 @@ Represents the total number of issues and their weights for a particular day. | `scopeCount` | Int! | Number of issues as of this day | | `scopeWeight` | Int! | Total weight of issues as of this day | +### CiBuildNeed + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `name` | String | Name of the job we need to complete. | + +### CiCdSettingsUpdatePayload + +Autogenerated return type of CiCdSettingsUpdate. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | + ### CiConfig | Field | Type | Description | | ----- | ---- | ----------- | | `errors` | String! => Array | Linting errors | | `mergedYaml` | String | Merged CI config YAML | -| `stages` | CiConfigStage! => Array | Stages of the pipeline | +| `stages` | CiConfigStageConnection | Stages of the pipeline | | `status` | CiConfigStatus | Status of linting, can be either valid or invalid | ### CiConfigGroup | Field | Type | Description | | ----- | ---- | ----------- | -| `jobs` | CiConfigJob! => Array | Jobs in group | +| `jobs` | CiConfigJobConnection | Jobs in group | | `name` | String | Name of the job group | | `size` | Int | Size of the job group | @@ -395,10 +413,25 @@ Represents the total number of issues and their weights for a particular day. | Field | Type | Description | | ----- | ---- | ----------- | -| `groupName` | String | Name of the job group | -| `name` | String | Name of the job | -| `needs` | CiConfigNeed! => Array | Builds that must complete before the jobs run | -| `stage` | String | Name of the job stage | +| `afterScript` | String! => Array | Override a set of commands that are executed after the job. | +| `allowFailure` | Boolean | Allow job to fail. | +| `beforeScript` | String! => Array | Override a set of commands that are executed before the job. | +| `environment` | String | Name of an environment to which the job deploys. | +| `except` | CiConfigJobRestriction | Limit when jobs are not created. | +| `groupName` | String | Name of the job group. | +| `name` | String | Name of the job. | +| `needs` | CiConfigNeedConnection | Builds that must complete before the jobs run. | +| `only` | CiConfigJobRestriction | Jobs are created when these conditions do not apply. | +| `script` | String! => Array | Shell script that is executed by a runner. | +| `stage` | String | Name of the job stage. | +| `tags` | String! => Array | List of tags that are used to select a runner. | +| `when` | String | When to run the job. | + +### CiConfigJobRestriction + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `refs` | String! => Array | The Git refs the job restriction applies to. | ### CiConfigNeed @@ -410,7 +443,7 @@ Represents the total number of issues and their weights for a particular day. | Field | Type | Description | | ----- | ---- | ----------- | -| `groups` | CiConfigGroup! => Array | Groups of jobs for the stage | +| `groups` | CiConfigGroupConnection | Groups of jobs for the stage | | `name` | String | Name of the stage | ### CiGroup @@ -429,7 +462,7 @@ Represents the total number of issues and their weights for a particular day. | `artifacts` | CiJobArtifactConnection | Artifacts generated by the job | | `detailedStatus` | DetailedStatus | Detailed status of the job | | `name` | String | Name of the job | -| `needs` | CiJobConnection | Builds that must complete before the jobs run | +| `needs` | CiBuildNeedConnection | References to builds that must complete before the jobs run | | `pipeline` | Pipeline | Pipeline the job belongs to | | `scheduledAt` | Time | Schedule for the build | @@ -484,8 +517,8 @@ Autogenerated return type of ClusterAgentTokenCreate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `secret` | String | Token secret value. Make sure you save it - you won't be able to access it again | -| `token` | ClusterAgentToken | Token created after mutation | +| `secret` | String | Token secret value. Make sure you save it - you won't be able to access it again. | +| `token` | ClusterAgentToken | Token created after mutation. | ### ClusterAgentTokenDeletePayload @@ -545,7 +578,7 @@ Autogenerated return type of CommitCreate. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `commit` | Commit | The commit after mutation | +| `commit` | Commit | The commit after mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### ComplianceFramework @@ -567,8 +600,8 @@ Autogenerated return type of ConfigureSast. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `status` | String! | Status of creating the commit for the supplied SAST CI configuration | -| `successPath` | String | Redirect path to use when the response is successful | +| `status` | String! | Status of creating the commit for the supplied SAST CI configuration. | +| `successPath` | String | Redirect path to use when the response is successful. | ### ContainerExpirationPolicy @@ -647,11 +680,11 @@ Autogenerated return type of CreateAlertIssue. | Field | Type | Description | | ----- | ---- | ----------- | -| `alert` | AlertManagementAlert | The alert after mutation | +| `alert` | AlertManagementAlert | The alert after mutation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue created after mutation | -| `todo` | Todo | The todo after mutation | +| `issue` | Issue | The issue created after mutation. | +| `todo` | Todo | The todo after mutation. | ### CreateAnnotationPayload @@ -659,7 +692,7 @@ Autogenerated return type of CreateAnnotation. | Field | Type | Description | | ----- | ---- | ----------- | -| `annotation` | MetricsDashboardAnnotation | The created annotation | +| `annotation` | MetricsDashboardAnnotation | The created annotation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | @@ -679,7 +712,7 @@ Autogenerated return type of CreateBranch. | Field | Type | Description | | ----- | ---- | ----------- | -| `branch` | Branch | Branch after mutation | +| `branch` | Branch | Branch after mutation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | @@ -690,7 +723,7 @@ Autogenerated return type of CreateClusterAgent. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `clusterAgent` | ClusterAgent | Cluster agent created after mutation | +| `clusterAgent` | ClusterAgent | Cluster agent created after mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### CreateComplianceFrameworkPayload @@ -710,7 +743,7 @@ Autogenerated return type of CreateCustomEmoji. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `customEmoji` | CustomEmoji | The new custom emoji | +| `customEmoji` | CustomEmoji | The new custom emoji. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### CreateDevopsAdoptionSegmentPayload @@ -721,7 +754,7 @@ Autogenerated return type of CreateDevopsAdoptionSegment. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `segment` | DevopsAdoptionSegment | The segment after mutation | +| `segment` | DevopsAdoptionSegment | The segment after mutation. | ### CreateDiffNotePayload @@ -731,7 +764,7 @@ Autogenerated return type of CreateDiffNote. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `note` | Note | The note after mutation | +| `note` | Note | The note after mutation. | ### CreateEpicPayload @@ -740,7 +773,7 @@ Autogenerated return type of CreateEpic. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `epic` | Epic | The created epic | +| `epic` | Epic | The created epic. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### CreateImageDiffNotePayload @@ -751,7 +784,7 @@ Autogenerated return type of CreateImageDiffNote. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `note` | Note | The note after mutation | +| `note` | Note | The note after mutation. | ### CreateIssuePayload @@ -761,7 +794,7 @@ Autogenerated return type of CreateIssue. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### CreateIterationPayload @@ -771,7 +804,7 @@ Autogenerated return type of CreateIteration. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `iteration` | Iteration | The created iteration | +| `iteration` | Iteration | The created iteration. | ### CreateNotePayload @@ -781,7 +814,7 @@ Autogenerated return type of CreateNote. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `note` | Note | The note after mutation | +| `note` | Note | The note after mutation. | ### CreateRequirementPayload @@ -791,7 +824,7 @@ Autogenerated return type of CreateRequirement. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `requirement` | Requirement | Requirement after mutation | +| `requirement` | Requirement | Requirement after mutation. | ### CreateSnippetPayload @@ -801,8 +834,8 @@ Autogenerated return type of CreateSnippet. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `snippet` | Snippet | The snippet after mutation | -| `spam` | Boolean | Indicates whether the operation returns a record detected as spam | +| `snippet` | Snippet | The snippet after mutation. | +| `spam` | Boolean | Indicates whether the operation returns a record detected as spam. | ### CreateTestCasePayload @@ -812,7 +845,7 @@ Autogenerated return type of CreateTestCase. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `testCase` | Issue | The test case created | +| `testCase` | Issue | The test case created. | ### CustomEmoji @@ -1063,7 +1096,7 @@ Autogenerated return type of DesignManagementDelete. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `version` | DesignVersion | The new version in which the designs are deleted | +| `version` | DesignVersion | The new version in which the designs are deleted. | ### DesignManagementMovePayload @@ -1072,7 +1105,7 @@ Autogenerated return type of DesignManagementMove. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `designCollection` | DesignCollection | The current state of the collection | +| `designCollection` | DesignCollection | The current state of the collection. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### DesignManagementUploadPayload @@ -1082,7 +1115,7 @@ Autogenerated return type of DesignManagementUpload. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `designs` | Design! => Array | The designs that were uploaded by the mutation | +| `designs` | Design! => Array | The designs that were uploaded by the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | | `skippedDesigns` | Design! => Array | Any designs that were skipped from the upload due to there being no change to their content since their last version | @@ -1114,7 +1147,7 @@ Autogenerated return type of DestroyBoard. | Field | Type | Description | | ----- | ---- | ----------- | -| `board` | Board | The board after mutation | +| `board` | Board | The board after mutation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | @@ -1144,7 +1177,7 @@ Autogenerated return type of DestroyContainerRepositoryTags. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `deletedTagNames` | String! => Array | Deleted container repository tags | +| `deletedTagNames` | String! => Array | Deleted container repository tags. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### DestroyNotePayload @@ -1155,7 +1188,7 @@ Autogenerated return type of DestroyNote. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `note` | Note | The note after mutation | +| `note` | Note | The note after mutation. | ### DestroySnippetPayload @@ -1165,7 +1198,7 @@ Autogenerated return type of DestroySnippet. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `snippet` | Snippet | The snippet after mutation | +| `snippet` | Snippet | The snippet after mutation. | ### DetailedStatus @@ -1274,7 +1307,7 @@ Autogenerated return type of DiscussionToggleResolve. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `discussion` | Discussion | The discussion after mutation | +| `discussion` | Discussion | The discussion after mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### DismissVulnerabilityPayload @@ -1285,7 +1318,7 @@ Autogenerated return type of DismissVulnerability. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `vulnerability` | Vulnerability | The vulnerability after dismissal | +| `vulnerability` | Vulnerability | The vulnerability after dismissal. | ### Environment @@ -1367,8 +1400,8 @@ Autogenerated return type of EpicAddIssue. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `epic` | Epic | The epic after mutation | -| `epicIssue` | EpicIssue | The epic-issue relation | +| `epic` | Epic | The epic after mutation. | +| `epicIssue` | EpicIssue | The epic-issue relation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### EpicBoard @@ -1377,8 +1410,9 @@ Represents an epic board. | Field | Type | Description | | ----- | ---- | ----------- | -| `id` | BoardsEpicBoardID! | Global ID of the board | -| `name` | String | Name of the board | +| `id` | BoardsEpicBoardID! | Global ID of the board. | +| `lists` | EpicListConnection | Epic board lists. | +| `name` | String | Name of the board. | ### EpicDescendantCount @@ -1423,6 +1457,7 @@ Relationship between an epic and an issue. | `blockedByCount` | Int | Count of issues blocking this issue. | | `closedAt` | Time | Timestamp of when the issue was closed | | `confidential` | Boolean! | Indicates the issue is confidential | +| `createNoteEmail` | String | User specific email address for the issue | | `createdAt` | Time! | Timestamp of when the issue was created | | `currentUserTodos` | TodoConnection! | Todos for the current user | | `description` | String | Description of the issue | @@ -1472,6 +1507,19 @@ Relationship between an epic and an issue. | `webUrl` | String! | Web URL of the issue | | `weight` | Int | Weight of the issue. | +### EpicList + +Represents an epic board list. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `epics` | EpicConnection | List epics. | +| `id` | BoardsEpicListID! | Global ID of the board list. | +| `label` | Label | Label of the list. | +| `listType` | String! | Type of the list. | +| `position` | Int | Position of the list within the board. | +| `title` | String! | Title of the list. | + ### EpicPermissions Check permissions for the current user on an epic. @@ -1494,7 +1542,7 @@ Autogenerated return type of EpicSetSubscription. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `epic` | Epic | The epic after mutation | +| `epic` | Epic | The epic after mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### EpicTreeReorderPayload @@ -1506,6 +1554,15 @@ Autogenerated return type of EpicTreeReorder. | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | +### ExportRequirementsPayload + +Autogenerated return type of ExportRequirements. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | + ### ExternalIssue Represents an external issue. @@ -1565,7 +1622,7 @@ Represents an external issue. | `board` | Board | A single board of the group | | `boards` | BoardConnection | Boards of the group | | `codeCoverageActivities` | CodeCoverageActivityConnection | Represents the code coverage activity for this group | -| `complianceFrameworks` | ComplianceFrameworkConnection | Compliance frameworks available to projects in this namespace Available only when feature flag `ff_custom_compliance_frameworks` is enabled. | +| `complianceFrameworks` | ComplianceFrameworkConnection | Compliance frameworks available to projects in this namespace. Available only when feature flag `ff_custom_compliance_frameworks` is enabled. | | `containerRepositories` | ContainerRepositoryConnection | Container repositories of the group | | `containerRepositoriesCount` | Int! | Number of container repositories in the group | | `containsLockedProjects` | Boolean! | Includes at least one project where the repository size exceeds the limit | @@ -1593,6 +1650,7 @@ Represents an external issue. | `mergeRequests` | MergeRequestConnection | Merge requests for projects in this group | | `milestones` | MilestoneConnection | Milestones of the group | | `name` | String! | Name of the namespace | +| `packageSettings` | PackageSettings | The package settings for the namespace | | `parent` | Group | Parent group | | `path` | String! | Path of the namespace | | `projectCreationLevel` | String | The permission level required to create projects in the group | @@ -1667,7 +1725,7 @@ Autogenerated return type of HttpIntegrationCreate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `integration` | AlertManagementHttpIntegration | The HTTP integration | +| `integration` | AlertManagementHttpIntegration | The HTTP integration. | ### HttpIntegrationDestroyPayload @@ -1677,7 +1735,7 @@ Autogenerated return type of HttpIntegrationDestroy. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `integration` | AlertManagementHttpIntegration | The HTTP integration | +| `integration` | AlertManagementHttpIntegration | The HTTP integration. | ### HttpIntegrationResetTokenPayload @@ -1687,7 +1745,7 @@ Autogenerated return type of HttpIntegrationResetToken. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `integration` | AlertManagementHttpIntegration | The HTTP integration | +| `integration` | AlertManagementHttpIntegration | The HTTP integration. | ### HttpIntegrationUpdatePayload @@ -1697,7 +1755,20 @@ Autogenerated return type of HttpIntegrationUpdate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `integration` | AlertManagementHttpIntegration | The HTTP integration | +| `integration` | AlertManagementHttpIntegration | The HTTP integration. | + +### IncidentManagementOncallRotation + +Describes an incident management on-call rotation. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `id` | IncidentManagementOncallRotationID! | ID of the on-call rotation. | +| `length` | Int | Length of the on-call schedule, in the units specified by lengthUnit. | +| `lengthUnit` | OncallRotationUnitEnum | Unit of the on-call rotation length. | +| `name` | String! | Name of the on-call rotation. | +| `participants` | OncallParticipantTypeConnection | Participants of the on-call rotation. | +| `startsAt` | Time | Start date of the on-call rotation. | ### IncidentManagementOncallSchedule @@ -1708,6 +1779,7 @@ Describes an incident management on-call schedule. | `description` | String | Description of the on-call schedule | | `iid` | ID! | Internal ID of the on-call schedule | | `name` | String! | Name of the on-call schedule | +| `rotations` | IncidentManagementOncallRotationConnection! | On-call rotations for the on-call schedule | | `timezone` | String! | Time zone of the on-call schedule | ### InstanceSecurityDashboard @@ -1740,6 +1812,7 @@ Represents a recorded measurement (object count) for the Admins. | `blockedByCount` | Int | Count of issues blocking this issue. | | `closedAt` | Time | Timestamp of when the issue was closed | | `confidential` | Boolean! | Indicates the issue is confidential | +| `createNoteEmail` | String | User specific email address for the issue | | `createdAt` | Time! | Timestamp of when the issue was created | | `currentUserTodos` | TodoConnection! | Todos for the current user | | `description` | String | Description of the issue | @@ -1795,7 +1868,7 @@ Autogenerated return type of IssueMoveList. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### IssueMovePayload @@ -1805,7 +1878,7 @@ Autogenerated return type of IssueMove. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### IssuePermissions @@ -1830,7 +1903,7 @@ Autogenerated return type of IssueSetAssignees. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### IssueSetConfidentialPayload @@ -1840,7 +1913,7 @@ Autogenerated return type of IssueSetConfidential. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### IssueSetDueDatePayload @@ -1850,7 +1923,7 @@ Autogenerated return type of IssueSetDueDate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### IssueSetEpicPayload @@ -1860,7 +1933,7 @@ Autogenerated return type of IssueSetEpic. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### IssueSetIterationPayload @@ -1870,7 +1943,7 @@ Autogenerated return type of IssueSetIteration. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### IssueSetLockedPayload @@ -1880,7 +1953,7 @@ Autogenerated return type of IssueSetLocked. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### IssueSetSeverityPayload @@ -1890,7 +1963,7 @@ Autogenerated return type of IssueSetSeverity. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### IssueSetSubscriptionPayload @@ -1900,7 +1973,7 @@ Autogenerated return type of IssueSetSubscription. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### IssueSetWeightPayload @@ -1910,7 +1983,7 @@ Autogenerated return type of IssueSetWeight. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### IssueStatusCountsType @@ -1964,7 +2037,7 @@ Autogenerated return type of JiraImportStart. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `jiraImport` | JiraImport | The Jira import data after mutation | +| `jiraImport` | JiraImport | The Jira import data after mutation. | ### JiraImportUsersPayload @@ -2022,7 +2095,7 @@ Autogenerated return type of LabelCreate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `label` | Label | The label after mutation | +| `label` | Label | The label after mutation. | ### MarkAsSpamSnippetPayload @@ -2032,7 +2105,7 @@ Autogenerated return type of MarkAsSpamSnippet. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `snippet` | Snippet | The snippet after mutation | +| `snippet` | Snippet | The snippet after mutation. | ### MergeRequest @@ -2046,6 +2119,7 @@ Autogenerated return type of MarkAsSpamSnippet. | `assignees` | UserConnection | Assignees of the merge request | | `author` | User | User who created this merge request | | `autoMergeEnabled` | Boolean! | Indicates if auto merge is enabled for the merge request | +| `autoMergeStrategy` | String | Selected auto merge strategy | | `availableAutoMergeStrategies` | String! => Array | Array of available auto merge strategies | | `commitCount` | Int | Number of commits in the merge request | | `commitsWithoutMergeCommits` | CommitConnection | Merge request commits excluding merge commits | @@ -2054,6 +2128,7 @@ Autogenerated return type of MarkAsSpamSnippet. | `currentUserTodos` | TodoConnection! | Todos for the current user | | `defaultMergeCommitMessage` | String | Default merge commit message of the merge request | | `defaultMergeCommitMessageWithDescription` | String | Default merge commit message of the merge request with description | +| `defaultSquashCommitMessage` | String | Default squash commit message of the merge request | | `description` | String | Description of the merge request (Markdown rendered as HTML for caching) | | `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | | `diffHeadSha` | String | Diff head SHA of the merge request | @@ -2075,19 +2150,21 @@ Autogenerated return type of MarkAsSpamSnippet. | `mergeOngoing` | Boolean! | Indicates if a merge is currently occurring | | `mergeStatus` | String | Status of the merge request | | `mergeTrainsCount` | Int | | +| `mergeUser` | User | User who merged this merge request | | `mergeWhenPipelineSucceeds` | Boolean | Indicates if the merge has been set to be merged when its pipeline succeeds (MWPS) | | `mergeable` | Boolean! | Indicates if the merge request is mergeable | | `mergeableDiscussionsState` | Boolean | Indicates if all discussions in the merge request have been resolved, allowing the merge request to be merged | | `mergedAt` | Time | Timestamp of when the merge request was merged, null if not merged | | `milestone` | Milestone | The milestone of the merge request | | `notes` | NoteConnection! | All notes on this noteable | -| `participants` | UserConnection | Participants in the merge request | +| `participants` | UserConnection | Participants in the merge request. This includes the author, assignees, reviewers, and users mentioned in notes. | | `pipelines` | PipelineConnection | Pipelines for the merge request. Note: for performance reasons, no more than the most recent 500 pipelines will be returned. | | `project` | Project! | Alias for target_project | | `projectId` | Int! | ID of the merge request project | | `rebaseCommitSha` | String | Rebase commit SHA of the merge request | | `rebaseInProgress` | Boolean! | Indicates if there is a rebase currently in progress for the merge request | | `reference` | String! | Internal reference of the merge request. Returned in shortened format by default | +| `reviewers` | UserConnection | Users from whom a review has been requested. | | `securityAutoFix` | Boolean | Indicates if the merge request is created by @GitLab-Security-Bot. | | `shouldBeRebased` | Boolean! | Indicates if the merge request will be rebased | | `shouldRemoveSourceBranch` | Boolean | Indicates if the source branch of the merge request will be deleted after merge | @@ -2096,6 +2173,7 @@ Autogenerated return type of MarkAsSpamSnippet. | `sourceBranchProtected` | Boolean! | Indicates if the source branch is protected | | `sourceProject` | Project | Source project of the merge request | | `sourceProjectId` | Int | ID of the merge request source project | +| `squash` | Boolean! | Indicates if squash on merge is enabled | | `squashOnMerge` | Boolean! | Indicates if squash on merge is enabled | | `state` | MergeRequestState! | State of the merge request | | `subscribed` | Boolean! | Indicates if the currently logged in user is subscribed to this merge request | @@ -2124,7 +2202,7 @@ Autogenerated return type of MergeRequestCreate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `mergeRequest` | MergeRequest | The merge request after mutation | +| `mergeRequest` | MergeRequest | The merge request after mutation. | ### MergeRequestDiffRegistry @@ -2165,7 +2243,7 @@ Autogenerated return type of MergeRequestSetAssignees. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `mergeRequest` | MergeRequest | The merge request after mutation | +| `mergeRequest` | MergeRequest | The merge request after mutation. | ### MergeRequestSetLabelsPayload @@ -2175,7 +2253,7 @@ Autogenerated return type of MergeRequestSetLabels. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `mergeRequest` | MergeRequest | The merge request after mutation | +| `mergeRequest` | MergeRequest | The merge request after mutation. | ### MergeRequestSetLockedPayload @@ -2185,7 +2263,7 @@ Autogenerated return type of MergeRequestSetLocked. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `mergeRequest` | MergeRequest | The merge request after mutation | +| `mergeRequest` | MergeRequest | The merge request after mutation. | ### MergeRequestSetMilestonePayload @@ -2195,7 +2273,7 @@ Autogenerated return type of MergeRequestSetMilestone. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `mergeRequest` | MergeRequest | The merge request after mutation | +| `mergeRequest` | MergeRequest | The merge request after mutation. | ### MergeRequestSetSubscriptionPayload @@ -2205,7 +2283,7 @@ Autogenerated return type of MergeRequestSetSubscription. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `mergeRequest` | MergeRequest | The merge request after mutation | +| `mergeRequest` | MergeRequest | The merge request after mutation. | ### MergeRequestSetWipPayload @@ -2215,7 +2293,7 @@ Autogenerated return type of MergeRequestSetWip. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `mergeRequest` | MergeRequest | The merge request after mutation | +| `mergeRequest` | MergeRequest | The merge request after mutation. | ### MergeRequestUpdatePayload @@ -2225,7 +2303,7 @@ Autogenerated return type of MergeRequestUpdate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `mergeRequest` | MergeRequest | The merge request after mutation | +| `mergeRequest` | MergeRequest | The merge request after mutation. | ### Metadata @@ -2300,7 +2378,7 @@ Contains statistics about a milestone. | ----- | ---- | ----------- | | `actualRepositorySizeLimit` | Float | Size limit for repositories in the namespace in bytes | | `additionalPurchasedStorageSize` | Float | Additional storage purchased for the root namespace in bytes | -| `complianceFrameworks` | ComplianceFrameworkConnection | Compliance frameworks available to projects in this namespace Available only when feature flag `ff_custom_compliance_frameworks` is enabled. | +| `complianceFrameworks` | ComplianceFrameworkConnection | Compliance frameworks available to projects in this namespace. Available only when feature flag `ff_custom_compliance_frameworks` is enabled. | | `containsLockedProjects` | Boolean! | Includes at least one project where the repository size exceeds the limit | | `description` | String | Description of the namespace | | `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | @@ -2310,6 +2388,7 @@ Contains statistics about a milestone. | `isTemporaryStorageIncreaseEnabled` | Boolean! | Status of the temporary storage increase | | `lfsEnabled` | Boolean | Indicates if Large File Storage (LFS) is enabled for namespace | | `name` | String! | Name of the namespace | +| `packageSettings` | PackageSettings | The package settings for the namespace | | `path` | String! | Path of the namespace | | `projects` | ProjectConnection! | Projects within this namespace | | `repositorySizeExcessProjectCount` | Int! | Number of projects in the root namespace where the repository size exceeds the limit | @@ -2329,7 +2408,7 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `namespace` | Namespace | The namespace after mutation | +| `namespace` | Namespace | The namespace after mutation. | ### Note @@ -2351,6 +2430,7 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily. | `system` | Boolean! | Indicates whether this note was created by the system or by a user | | `systemNoteIconName` | String | Name of the icon corresponding to a system note | | `updatedAt` | Time! | Timestamp of the note's last activity | +| `url` | String | URL to view this Note in the Web UI | | `userPermissions` | NotePermissions! | Permissions for the current user on the resource | ### NotePermissions @@ -2364,6 +2444,27 @@ Autogenerated return type of NamespaceIncreaseStorageTemporarily. | `repositionNote` | Boolean! | Indicates the user can perform `reposition_note` on this resource | | `resolveNote` | Boolean! | Indicates the user can perform `resolve_note` on this resource | +### OncallParticipantType + +The rotation participant and color palette. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `colorPalette` | String | The color palette to assign to the on-call user. For example "blue". | +| `colorWeight` | String | The color weight to assign to for the on-call user, for example "500". Max 4 chars. For easy identification of the user. | +| `id` | IncidentManagementOncallParticipantID! | ID of the on-call participant. | +| `user` | User! | The user who is participating. | + +### OncallRotationCreatePayload + +Autogenerated return type of OncallRotationCreate. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `oncallRotation` | IncidentManagementOncallRotation | The on-call rotation. | + ### OncallScheduleCreatePayload Autogenerated return type of OncallScheduleCreate. @@ -2372,7 +2473,7 @@ Autogenerated return type of OncallScheduleCreate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule | +| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule. | ### OncallScheduleDestroyPayload @@ -2382,7 +2483,7 @@ Autogenerated return type of OncallScheduleDestroy. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule | +| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule. | ### OncallScheduleUpdatePayload @@ -2392,20 +2493,62 @@ Autogenerated return type of OncallScheduleUpdate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule | +| `oncallSchedule` | IncidentManagementOncallSchedule | The on-call schedule. | ### Package -Represents a package. +Represents a package in the Package Registry. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `createdAt` | Time! | The created date. | +| `id` | ID! | The ID of the package. | +| `name` | String! | The name of the package. | +| `packageType` | PackageTypeEnum! | The type of the package. | +| `pipelines` | PipelineConnection | Pipelines that built the package. | +| `project` | Project! | Project where the package is stored. | +| `tags` | PackageTagConnection | The package tags. | +| `updatedAt` | Time! | The updated date. | +| `version` | String | The version of the package. | +| `versions` | PackageConnection | The other versions of the package. | + +### PackageComposerDetails + +Details of a Composer package. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `composerMetadatum` | PackageComposerMetadatumType! | The Composer metadatum. | +| `createdAt` | Time! | The created date. | +| `id` | ID! | The ID of the package. | +| `name` | String! | The name of the package. | +| `packageType` | PackageTypeEnum! | The type of the package. | +| `pipelines` | PipelineConnection | Pipelines that built the package. | +| `project` | Project! | Project where the package is stored. | +| `tags` | PackageTagConnection | The package tags. | +| `updatedAt` | Time! | The updated date. | +| `version` | String | The version of the package. | +| `versions` | PackageConnection | The other versions of the package. | + +### PackageComposerJsonType + +Represents a composer JSON file. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `license` | String | The license set in the Composer JSON file. | +| `name` | String | The name set in the Composer JSON file. | +| `type` | String | The type set in the Composer JSON file. | +| `version` | String | The version set in the Composer JSON file. | + +### PackageComposerMetadatumType + +Composer metadatum. | Field | Type | Description | | ----- | ---- | ----------- | -| `createdAt` | Time! | The created date | -| `id` | ID! | The ID of the package | -| `name` | String! | The name of the package | -| `packageType` | PackageTypeEnum! | The type of the package | -| `updatedAt` | Time! | The update date | -| `version` | String | The version of the package | +| `composerJson` | PackageComposerJsonType! | Data of the Composer JSON file. | +| `targetSha` | String! | Target SHA of the package. | ### PackageFileRegistry @@ -2422,6 +2565,26 @@ Represents the Geo sync and verification state of a package file. | `retryCount` | Int | Number of consecutive failed sync attempts of the PackageFileRegistry | | `state` | RegistryState | Sync state of the PackageFileRegistry | +### PackageSettings + +Namespace-level Package Registry settings. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `mavenDuplicateExceptionRegex` | UntrustedRegexp | When maven_duplicates_allowed is false, you can publish duplicate packages with names that match this regex. Otherwise, this setting has no effect. | +| `mavenDuplicatesAllowed` | Boolean! | Indicates whether duplicate Maven packages are allowed for this namespace. | + +### PackageTag + +Represents a package tag. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `createdAt` | Time! | The created date. | +| `id` | ID! | The ID of the tag. | +| `name` | String! | The name of the tag. | +| `updatedAt` | Time! | The updated date. | + ### PageInfo Information about pagination in a connection.. @@ -2515,7 +2678,7 @@ Autogenerated return type of PipelineRetry. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `pipeline` | Pipeline | The pipeline after mutation | +| `pipeline` | Pipeline | The pipeline after mutation. | ### Project @@ -2545,7 +2708,6 @@ Autogenerated return type of PipelineRetry. | `dastScannerProfiles` | DastScannerProfileConnection | The DAST scanner profiles associated with the project | | `dastSiteProfile` | DastSiteProfile | DAST Site Profile associated with the project | | `dastSiteProfiles` | DastSiteProfileConnection | DAST Site Profiles associated with the project | -| `dastSiteValidation` | DastSiteValidation | DAST Site Validation associated with the project. Will always return `null` if `security_on_demand_scans_site_validation` is disabled | | `dastSiteValidations` | DastSiteValidationConnection | DAST Site Validations associated with the project. Will always return no nodes if `security_on_demand_scans_site_validation` is disabled | | `description` | String | Short description of the project | | `descriptionHtml` | String | The GitLab Flavored Markdown rendering of `description` | @@ -2617,7 +2779,6 @@ Autogenerated return type of PipelineRetry. | `suggestionCommitMessage` | String | The commit message used to apply merge request suggestions | | `tagList` | String | List of project topics (not Git tags) | | `terraformStates` | TerraformStateConnection | Terraform states associated with the project | -| `totalPipelineDuration` | Int | Total pipeline duration for all of the pipelines in a project | | `userPermissions` | ProjectPermissions! | Permissions for the current user on the resource | | `visibility` | String | Visibility of the project | | `vulnerabilities` | VulnerabilityConnection | Vulnerabilities reported on the project | @@ -2631,6 +2792,7 @@ Autogenerated return type of PipelineRetry. | Field | Type | Description | | ----- | ---- | ----------- | +| `keepLatestArtifact` | Boolean | Whether to keep the latest builds artifacts. | | `mergePipelinesEnabled` | Boolean | Whether merge pipelines are enabled. | | `mergeTrainsEnabled` | Boolean | Whether merge trains are enabled. | | `project` | Project | Project the CI/CD settings belong to. | @@ -2729,7 +2891,7 @@ Autogenerated return type of PrometheusIntegrationCreate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `integration` | AlertManagementPrometheusIntegration | The newly created integration | +| `integration` | AlertManagementPrometheusIntegration | The newly created integration. | ### PrometheusIntegrationResetTokenPayload @@ -2739,7 +2901,7 @@ Autogenerated return type of PrometheusIntegrationResetToken. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `integration` | AlertManagementPrometheusIntegration | The newly created integration | +| `integration` | AlertManagementPrometheusIntegration | The newly created integration. | ### PrometheusIntegrationUpdatePayload @@ -2749,7 +2911,7 @@ Autogenerated return type of PrometheusIntegrationUpdate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `integration` | AlertManagementPrometheusIntegration | The newly created integration | +| `integration` | AlertManagementPrometheusIntegration | The newly created integration. | ### PromoteToEpicPayload @@ -2758,9 +2920,9 @@ Autogenerated return type of PromoteToEpic. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `epic` | Epic | The epic after issue promotion | +| `epic` | Epic | The epic after issue promotion. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### Release @@ -2814,7 +2976,7 @@ Autogenerated return type of ReleaseCreate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `release` | Release | The release after mutation | +| `release` | Release | The release after mutation. | ### ReleaseDeletePayload @@ -2874,7 +3036,7 @@ Autogenerated return type of RemoveAwardEmoji. | Field | Type | Description | | ----- | ---- | ----------- | -| `awardEmoji` | AwardEmoji | The award emoji after mutation | +| `awardEmoji` | AwardEmoji | The award emoji after mutation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | @@ -2895,7 +3057,7 @@ Autogenerated return type of RepositionImageDiffNote. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `note` | Note | The note after mutation | +| `note` | Note | The note after mutation. | ### Repository @@ -2957,7 +3119,7 @@ Autogenerated return type of RevertVulnerabilityToDetected. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `vulnerability` | Vulnerability | The vulnerability after revert | +| `vulnerability` | Vulnerability | The vulnerability after revert. | ### RootStorageStatistics @@ -3468,7 +3630,7 @@ Autogenerated return type of TodoCreate. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `todo` | Todo | The to-do created | +| `todo` | Todo | The to-do created. | ### TodoMarkDonePayload @@ -3478,7 +3640,7 @@ Autogenerated return type of TodoMarkDone. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `todo` | Todo! | The requested todo | +| `todo` | Todo! | The requested todo. | ### TodoRestoreManyPayload @@ -3488,7 +3650,7 @@ Autogenerated return type of TodoRestoreMany. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `todos` | Todo! => Array | Updated todos | +| `todos` | Todo! => Array | Updated todos. | | `updatedIds` **{warning-solid}** | TodoID! => Array | **Deprecated:** Use todos. Deprecated in 13.2. | ### TodoRestorePayload @@ -3499,7 +3661,7 @@ Autogenerated return type of TodoRestore. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `todo` | Todo! | The requested todo | +| `todo` | Todo! | The requested todo. | ### TodosMarkAllDonePayload @@ -3509,7 +3671,7 @@ Autogenerated return type of TodosMarkAllDone. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `todos` | Todo! => Array | Updated todos | +| `todos` | Todo! => Array | Updated todos. | | `updatedIds` **{warning-solid}** | TodoID! => Array | **Deprecated:** Use todos. Deprecated in 13.2. | ### ToggleAwardEmojiPayload @@ -3518,7 +3680,7 @@ Autogenerated return type of ToggleAwardEmoji. | Field | Type | Description | | ----- | ---- | ----------- | -| `awardEmoji` | AwardEmoji | The award emoji after mutation | +| `awardEmoji` | AwardEmoji | The award emoji after mutation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | | `toggledOn` | Boolean! | Indicates the status of the emoji. True if the toggle awarded the emoji, and false if the toggle removed the emoji. | @@ -3553,11 +3715,11 @@ Autogenerated return type of UpdateAlertStatus. | Field | Type | Description | | ----- | ---- | ----------- | -| `alert` | AlertManagementAlert | The alert after mutation | +| `alert` | AlertManagementAlert | The alert after mutation. | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue created after mutation | -| `todo` | Todo | The todo after mutation | +| `issue` | Issue | The issue created after mutation. | +| `todo` | Todo | The todo after mutation. | ### UpdateBoardEpicUserPreferencesPayload @@ -3566,7 +3728,7 @@ Autogenerated return type of UpdateBoardEpicUserPreferences. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `epicUserPreferences` | BoardEpicUserPreferences | User preferences for the epic in the board after mutation | +| `epicUserPreferences` | BoardEpicUserPreferences | User preferences for the epic in the board after mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### UpdateBoardListPayload @@ -3577,7 +3739,7 @@ Autogenerated return type of UpdateBoardList. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `list` | BoardList | Mutated list | +| `list` | BoardList | Mutated list. | ### UpdateBoardPayload @@ -3596,7 +3758,7 @@ Autogenerated return type of UpdateComplianceFramework. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `complianceFramework` | ComplianceFramework | The compliance framework after mutation | +| `complianceFramework` | ComplianceFramework | The compliance framework after mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### UpdateContainerExpirationPolicyPayload @@ -3606,7 +3768,7 @@ Autogenerated return type of UpdateContainerExpirationPolicy. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `containerExpirationPolicy` | ContainerExpirationPolicy | The container expiration policy after mutation | +| `containerExpirationPolicy` | ContainerExpirationPolicy | The container expiration policy after mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### UpdateDevopsAdoptionSegmentPayload @@ -3617,7 +3779,7 @@ Autogenerated return type of UpdateDevopsAdoptionSegment. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `segment` | DevopsAdoptionSegment | The segment after mutation | +| `segment` | DevopsAdoptionSegment | The segment after mutation. | ### UpdateEpicPayload @@ -3626,7 +3788,7 @@ Autogenerated return type of UpdateEpic. | Field | Type | Description | | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | -| `epic` | Epic | The epic after mutation | +| `epic` | Epic | The epic after mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | ### UpdateImageDiffNotePayload @@ -3637,7 +3799,7 @@ Autogenerated return type of UpdateImageDiffNote. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `note` | Note | The note after mutation | +| `note` | Note | The note after mutation. | ### UpdateIssuePayload @@ -3647,7 +3809,7 @@ Autogenerated return type of UpdateIssue. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `issue` | Issue | The issue after mutation | +| `issue` | Issue | The issue after mutation. | ### UpdateIterationPayload @@ -3659,6 +3821,16 @@ Autogenerated return type of UpdateIteration. | `errors` | String! => Array | Errors encountered during execution of the mutation. | | `iteration` | Iteration | Updated iteration. | +### UpdateNamespacePackageSettingsPayload + +Autogenerated return type of UpdateNamespacePackageSettings. + +| Field | Type | Description | +| ----- | ---- | ----------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `packageSettings` | PackageSettings | The namespace package setting after mutation. | + ### UpdateNotePayload Autogenerated return type of UpdateNote. @@ -3667,7 +3839,7 @@ Autogenerated return type of UpdateNote. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `note` | Note | The note after mutation | +| `note` | Note | The note after mutation. | ### UpdateRequirementPayload @@ -3677,7 +3849,7 @@ Autogenerated return type of UpdateRequirement. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `requirement` | Requirement | Requirement after mutation | +| `requirement` | Requirement | Requirement after mutation. | ### UpdateSnippetPayload @@ -3687,8 +3859,8 @@ Autogenerated return type of UpdateSnippet. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `snippet` | Snippet | The snippet after mutation | -| `spam` | Boolean | Indicates whether the operation returns a record detected as spam | +| `snippet` | Snippet | The snippet after mutation. | +| `spam` | Boolean | Indicates whether the operation returns a record detected as spam. | ### User @@ -3763,10 +3935,12 @@ Represents a vulnerability. | Field | Type | Description | | ----- | ---- | ----------- | | `confirmedAt` | Time | Timestamp of when the vulnerability state was changed to confirmed | +| `confirmedBy` | User | The user that confirmed the vulnerability. | | `description` | String | Description of the vulnerability | | `detectedAt` | Time! | Timestamp of when the vulnerability was first detected | | `discussions` | DiscussionConnection! | All discussions on this noteable | | `dismissedAt` | Time | Timestamp of when the vulnerability state was changed to dismissed | +| `dismissedBy` | User | The user that dismissed the vulnerability. | | `externalIssueLinks` | VulnerabilityExternalIssueLinkConnection! | List of external issue links related to the vulnerability | | `hasSolutions` | Boolean | Indicates whether there is a solution available for this vulnerability. | | `id` | ID! | GraphQL ID of the vulnerability | @@ -3779,6 +3953,7 @@ Represents a vulnerability. | `project` | Project | The project on which the vulnerability was found | | `reportType` | VulnerabilityReportType | Type of the security report that found the vulnerability (SAST, DEPENDENCY_SCANNING, CONTAINER_SCANNING, DAST, SECRET_DETECTION, COVERAGE_FUZZING, API_FUZZING) | | `resolvedAt` | Time | Timestamp of when the vulnerability state was changed to resolved | +| `resolvedBy` | User | The user that resolved the vulnerability. | | `resolvedOnDefaultBranch` | Boolean! | Indicates whether the vulnerability is fixed on the default branch or not | | `scanner` | VulnerabilityScanner | Scanner metadata for the vulnerability. | | `severity` | VulnerabilitySeverity | Severity of the vulnerability (INFO, UNKNOWN, LOW, MEDIUM, HIGH, CRITICAL) | @@ -3796,7 +3971,7 @@ Autogenerated return type of VulnerabilityConfirm. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `vulnerability` | Vulnerability | The vulnerability after state change | +| `vulnerability` | Vulnerability | The vulnerability after state change. | ### VulnerabilityDismissPayload @@ -3806,7 +3981,7 @@ Autogenerated return type of VulnerabilityDismiss. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `vulnerability` | Vulnerability | The vulnerability after dismissal | +| `vulnerability` | Vulnerability | The vulnerability after dismissal. | ### VulnerabilityExternalIssueLink @@ -3948,7 +4123,7 @@ Autogenerated return type of VulnerabilityResolve. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `vulnerability` | Vulnerability | The vulnerability after state change | +| `vulnerability` | Vulnerability | The vulnerability after state change. | ### VulnerabilityRevertToDetectedPayload @@ -3958,7 +4133,7 @@ Autogenerated return type of VulnerabilityRevertToDetected. | ----- | ---- | ----------- | | `clientMutationId` | String | A unique identifier for the client performing the mutation. | | `errors` | String! => Array | Errors encountered during execution of the mutation. | -| `vulnerability` | Vulnerability | The vulnerability after revert | +| `vulnerability` | Vulnerability | The vulnerability after revert. | ### VulnerabilityScanner @@ -4068,7 +4243,7 @@ Filters the alerts based on given domain. | Value | Description | | ----- | ----------- | -| `operations` | Alerts for operations domain | +| `operations` | Alerts for operations domain | | `threat_monitoring` | Alerts for threat monitoring domain | ### AlertManagementIntegrationType @@ -4080,6 +4255,33 @@ Values of types of integrations. | `HTTP` | Integration with any monitoring tool | | `PROMETHEUS` | Prometheus integration | +### AlertManagementPayloadAlertFieldName + +Values for alert field names used in the custom mapping. + +| Value | Description | +| ----- | ----------- | +| `DESCRIPTION` | A high-level summary of the problem. | +| `END_TIME` | The resolved time of the incident. | +| `FINGERPRINT` | The unique identifier of the alert. This can be used to group occurrences of the same alert. | +| `GITLAB_ENVIRONMENT_NAME` | The name of the associated GitLab environment. | +| `HOSTS` | One or more hosts, as to where this incident occurred. | +| `MONITORING_TOOL` | The name of the associated monitoring tool. | +| `SERVICE` | The affected service. | +| `SEVERITY` | The severity of the alert. | +| `START_TIME` | The time of the incident. | +| `TITLE` | The title of the incident. | + +### AlertManagementPayloadAlertFieldType + +Values for alert field types used in the custom mapping. + +| Value | Description | +| ----- | ----------- | +| `ARRAY` | Array field type | +| `DATETIME` | DateTime field type | +| `STRING` | String field type | + ### AlertManagementSeverity Alert severity values. @@ -4225,6 +4427,36 @@ Status of a container repository. | `HEADER` | Header validation | | `TEXT_FILE` | Text file validation | +### DataVisualizationColorEnum + +Color of the data visualization palette. + +| Value | Description | +| ----- | ----------- | +| `AQUA` | Aqua color | +| `BLUE` | Blue color | +| `GREEN` | Green color | +| `MAGENTA` | Magenta color | +| `ORANGE` | Orange color | + +### DataVisualizationWeightEnum + +Weight of the data visualization palette. + +| Value | Description | +| ----- | ----------- | +| `WEIGHT_100` | 100 weight | +| `WEIGHT_200` | 200 weight | +| `WEIGHT_300` | 300 weight | +| `WEIGHT_400` | 400 weight | +| `WEIGHT_50` | 50 weight | +| `WEIGHT_500` | 500 weight | +| `WEIGHT_600` | 600 weight | +| `WEIGHT_700` | 700 weight | +| `WEIGHT_800` | 800 weight | +| `WEIGHT_900` | 900 weight | +| `WEIGHT_950` | 950 weight | + ### DesignCollectionCopyState Copy state of a DesignCollection. @@ -4560,6 +4792,16 @@ Values for sorting projects. | `SIMILARITY` | Most similar to the search query | | `STORAGE` | Sort by storage size | +### OncallRotationUnitEnum + +Rotation length unit of an on-call rotation. + +| Value | Description | +| ----- | ----------- | +| `DAYS` | Days | +| `HOURS` | Hours | +| `WEEKS` | Weeks | + ### PackageTypeEnum | Value | Description | @@ -4707,7 +4949,6 @@ State of a Sentry error. | Value | Description | | ----- | ----------- | -| `ALERTS_SERVICE` | | | `ASANA_SERVICE` | | | `ASSEMBLA_SERVICE` | | | `BAMBOO_SERVICE` | | @@ -4843,6 +5084,18 @@ Possible states of a user. | `private` | | | `public` | | +### VulnerabilityDismissalReason + +The dismissal reason of the Vulnerability. + +| Value | Description | +| ----- | ----------- | +| `ACCEPTABLE_RISK` | The likelihood of the Vulnerability occurring and its impact are deemed acceptable | +| `FALSE_POSITIVE` | The Vulnerability was incorrectly identified as being present | +| `MITIGATING_CONTROL` | There is a mitigating control that eliminates the Vulnerability or makes its risk acceptable | +| `NOT_APPLICABLE` | Other reasons for dismissal | +| `USED_IN_TESTS` | The Vulnerability is used in tests and does not pose an actual risk | + ### VulnerabilityExternalIssueLinkExternalTracker The external tracker of the external issue link related to a vulnerability. diff --git a/doc/api/graphql/users_example.md b/doc/api/graphql/users_example.md new file mode 100644 index 00000000000..e4a697d11fd --- /dev/null +++ b/doc/api/graphql/users_example.md @@ -0,0 +1,109 @@ +--- +stage: none +group: unassigned +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Query users with GraphQL + +This page describes how you can use the GraphiQL explorer to query users. + +You can run the same query directly via a HTTP endpoint, using `cURL`. For more information, see our +guidance on getting started from the [command line](getting_started.md#command-line). + +The [example users query](#set-up-the-graphiql-explorer) looks for a subset of users in +o +a GitLab instance either by username or +[Global ID](../../development/api_graphql_styleguide.md#global-ids). +The query includes: + +- [`pageInfo`](#pageinfo) +- [`nodes`](#nodes) + +## pageInfo + +This contains the data needed to implement pagination. GitLab uses cursor-based +[pagination](getting_started.md#pagination). For more information, see +[Pagination](https://graphql.org/learn/pagination/) in the GraphQL documentation. + +## nodes + +In a GraphQL query, `nodes` is used to represent a collection of [`nodes` on a graph](https://en.wikipedia.org/wiki/Vertex_(graph_theory)). +In this case, the collection of nodes is a collection of `User` objects. For each one, +we output: + +- Their user's `id`. +- The `membership` fragment, which represents a Project or Group membership belonging + to that user. Outputting a fragment is denoted with the `...memberships` notation. + +The GitLab GraphQL API is extensive and a large amount of data for a wide variety of entities can be output. +See the official [reference documentation](reference/index.md) for the most up-to-date information. + +## Set up the GraphiQL explorer + +This procedure presents a substantive example that you can copy and paste into GraphiQL +explorer. GraphiQL explorer is available for: + +- GitLab.com users at [https://gitlab.com/-/graphql-explorer](https://gitlab.com/-/graphql-explorer). +- Self-managed users at `https://gitlab.example.com/-/graphql-explorer`. + +1. Copy the following code excerpt: + + ```graphql + { + users(usernames: ["user1", "user3", "user4"]) { + pageInfo { + endCursor + startCursor + hasNextPage + } + nodes { + id + username, + publicEmail + location + webUrl + userPermissions { + createSnippet + } + } + } + } + ``` + +1. Open the [GraphiQL explorer tool](https://gitlab.com/-/graphql-explorer). +1. Paste the `query` listed above into the left window of your GraphiQL explorer tool. +1. Click Play to get the result shown here: + +![GraphiQL explorer search for boards](img/users_query_example_v13_8.png) + +NOTE: +[The GraphQL API returns a GlobalID, rather than a standard ID.](getting_started.md#queries-and-mutations) It also expects a GlobalID as an input rather than +a single integer. + +This GraphQL query returns the specified information for the three users with the listed username. Since the GraphiQL explorer uses the session token to authorize access to resources, +the output is limited to the projects and groups accessible to the currently signed-in user. + +If you've signed in as an instance administrator, you would have access to all records, regardless of ownership. + +If you are signed in as an administrator, you can show just the matching administrators on the instance by adding the `admins: true` parameter to the query changing the second line to: + +```graphql + users(usernames: ["user1", "user3", "user4"], admins: true) { + ... + } +``` + +Or you can just get all of the administrators: + +```graphql + users(admins: true) { + ... + } +``` + +For more information on: + +- GraphQL specific entities, such as Fragments and Interfaces, see the official + [GraphQL documentation](https://graphql.org/learn/). +- Individual attributes, see the [GraphQL API Resources](reference/index.md). diff --git a/doc/api/group_boards.md b/doc/api/group_boards.md index f982dad7962..722f3a76267 100644 --- a/doc/api/group_boards.md +++ b/doc/api/group_boards.md @@ -279,7 +279,7 @@ Example response: } ``` -## Update a group issue board **(PREMIUM)** +## Update a group issue board > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5954) in GitLab 11.1. @@ -289,15 +289,17 @@ Updates a Group Issue Board. PUT /groups/:id/boards/:board_id ``` -| Attribute | Type | Required | Description | -| ------------------- | -------------- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user | -| `board_id` | integer | yes | The ID of a board | -| `name` | string | no | The new name of the board | -| `assignee_id` | integer | no | The assignee the board should be scoped to | -| `milestone_id` | integer | no | The milestone the board should be scoped to | -| `labels` | string | no | Comma-separated list of label names which the board should be scoped to | -| `weight` | integer | no | The weight range from 0 to 9, to which the board should be scoped to | +| Attribute | Type | Required | Description | +| ---------------------------- | -------------- | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user | +| `board_id` | integer | yes | The ID of a board | +| `name` | string | no | The new name of the board | +| `hide_backlog_list` | boolean | no | Hide the Open list | +| `hide_closed_list` | boolean | no | Hide the Closed list | +| `assignee_id` **(PREMIUM)** | integer | no | The assignee the board should be scoped to | +| `milestone_id` **(PREMIUM)** | integer | no | The milestone the board should be scoped to | +| `labels` **(PREMIUM)** | string | no | Comma-separated list of label names which the board should be scoped to | +| `weight` **(PREMIUM)** | integer | no | The weight range from 0 to 9, to which the board should be scoped to | ```shell curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/5/boards/1?name=new_name&milestone_id=44&assignee_id=1&labels=GroupLabel&weight=4" diff --git a/doc/api/group_import_export.md b/doc/api/group_import_export.md index bf8c889b031..57670eff1ea 100644 --- a/doc/api/group_import_export.md +++ b/doc/api/group_import_export.md @@ -93,7 +93,7 @@ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --form "name=i ``` NOTE: -The maximum import file size can be set by the Administrator, default is 50MB. +The maximum import file size can be set by the Administrator, default is `0` (unlimited). As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](settings.md#change-application-settings) or the [Admin UI](../user/admin_area/settings/account_and_limit_settings.md). ## Important notes diff --git a/doc/api/groups.md b/doc/api/groups.md index b4d36b568b8..eb255f8de00 100644 --- a/doc/api/groups.md +++ b/doc/api/groups.md @@ -1,6 +1,6 @@ --- -stage: none -group: unassigned +stage: Manage +group: Access info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- @@ -766,7 +766,6 @@ Parameters: | `default_branch_protection` | integer | no | See [Options for `default_branch_protection`](#options-for-default_branch_protection). Default to the global level default branch protection setting. | | `shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` | | `extra_shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). | -| `shared_runners_setting` | string | no | See [Options for `shared_runners_setting`](#options-for-shared_runners_setting). Enable or disable shared runners for a group's subgroups and projects. | ### Options for `default_branch_protection` @@ -778,16 +777,6 @@ The `default_branch_protection` attribute determines whether developers and main | `1` | Partial protection. Developers and maintainers can: <br>- Push new commits | | `2` | Full protection. Only maintainers can: <br>- Push new commits | -### Options for `shared_runners_setting` - -The `shared_runners_setting` attribute determines whether shared runners are enabled for a group's subgroups and projects. - -| Value | Description | -|-------|-------------------------------------------------------------------------------------------------------------| -| `enabled` | Enables shared runners for all projects and subgroups in this group. | -| `disabled_with_override` | Disables shared runners for all projects and subgroups in this group, but allows subgroups to override this setting. | -| `disabled_and_unoverridable` | Disables shared runners for all projects and subgroups in this group, and prevents subgroups from overriding this setting. | - ## New Subgroup This is similar to creating a [New group](#new-group). You need the `parent_id` from the [List groups](#list-groups) call. You can then enter the desired: @@ -852,6 +841,7 @@ PUT /groups/:id | `shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Pipeline minutes quota for this group (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` | | `extra_shared_runners_minutes_limit` | integer | no | **(STARTER ONLY)** Extra pipeline minutes quota for this group (purchased in addition to the minutes included in the plan). | | `prevent_forking_outside_group` | boolean | no | **(PREMIUM)** When enabled, users can **not** fork projects from this group to external namespaces +| `shared_runners_setting` | string | no | See [Options for `shared_runners_setting`](#options-for-shared_runners_setting). Enable or disable shared runners for a group's subgroups and projects. | NOTE: The `projects` and `shared_projects` attributes in the response are deprecated and [scheduled for removal in API v5](https://gitlab.com/gitlab-org/gitlab/-/issues/213797). @@ -941,6 +931,16 @@ with Rails console access to run the following command: Feature.disable(:limit_projects_in_groups_api) ``` +### Options for `shared_runners_setting` + +The `shared_runners_setting` attribute determines whether shared runners are enabled for a group's subgroups and projects. + +| Value | Description | +|-------|-------------------------------------------------------------------------------------------------------------| +| `enabled` | Enables shared runners for all projects and subgroups in this group. | +| `disabled_with_override` | Disables shared runners for all projects and subgroups in this group, but allows subgroups to override this setting. | +| `disabled_and_unoverridable` | Disables shared runners for all projects and subgroups in this group, and prevents subgroups from overriding this setting. | + ## Remove group Only available to group owners and administrators. diff --git a/doc/api/import.md b/doc/api/import.md index 3a1edcb732d..2d978b7b6dd 100644 --- a/doc/api/import.md +++ b/doc/api/import.md @@ -73,7 +73,7 @@ POST /import/bitbucket_server curl --request POST \ --url "https://gitlab.example.com/api/v4/import/bitbucket_server" \ --header "content-type: application/json" \ - --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" \ + --header "PRIVATE-TOKEN: <your_access_token>" \ --data '{ "bitbucket_server_url": "http://bitbucket.example.com", "bitbucket_server_username": "root", diff --git a/doc/api/invitations.md b/doc/api/invitations.md index 0891a343cce..7259dddec8c 100644 --- a/doc/api/invitations.md +++ b/doc/api/invitations.md @@ -106,3 +106,27 @@ Example response: }, ] ``` + +## Delete an invitation to a group or project + +Deletes a pending invitation by email address. + +```plaintext +DELETE /groups/:id/invitations/:email +DELETE /projects/:id/invitations/:email +``` + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](README.md#namespaced-path-encoding) owned by the authenticated user | +| `email` | string | yes | The email address to which the invitation was previously sent | + +```shell +curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/55/invitations/email@example.org" +curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/55/invitations/email@example.org" +``` + +- Returns `204` and no content on success. +- Returns `403` forbidden if unauthorized to delete the invitation. +- Returns `404` not found if authorized and no invitation is found for that email address. +- Returns `409` if the request was valid but the invitation could not be deleted. diff --git a/doc/api/issues.md b/doc/api/issues.md index f6bab9ce676..1abb4fe3b4a 100644 --- a/doc/api/issues.md +++ b/doc/api/issues.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Issues API -If a user is not a member of a project and the project is private, a `GET` +If a user is not a member of a private project, a `GET` request on that project results in a `404` status code. ## Issues pagination @@ -22,8 +22,8 @@ Introduced in [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_request NOTE: The `references.relative` attribute is relative to the group or project of the issue being requested. -When an issue is fetched from its project, the `relative` format is the same as the `short` format, -and when requested across groups or projects it's expected to be the same as the `full` format. +When an issue is fetched from its project, the `relative` format is the same as the `short` format. +When requested across groups or projects, it's expected to be the same as the `full` format. ## List issues @@ -57,7 +57,7 @@ GET /issues?state=opened | `confidential` | boolean | no | Filter confidential or public issues. | | `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | -| `due_date` | string | no | Return issues that have no due date (`0`) or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _(Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ | +| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _(Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ | | `iids[]` | integer array | no | Return only the issues having the given `iid` | | `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` | | `iteration_id` **(STARTER)** | integer | no | Return issues assigned to the given iteration ID. `None` returns issues that do not belong to an iteration. `Any` returns issues that belong to an iteration. Mutually exclusive with `iteration_title`. _([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6)_ | @@ -239,7 +239,7 @@ GET /groups/:id/issues?state=opened | `confidential` | boolean | no | Filter confidential or public issues. | | `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | -| `due_date` | string | no | Return issues that have no due date (`0`) or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _(Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ | +| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _(Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ | | `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user | | `iids[]` | integer array | no | Return only the issues having the given `iid` | | `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. | @@ -416,7 +416,7 @@ GET /projects/:id/issues?state=opened | `confidential` | boolean | no | Filter confidential or public issues. | | `created_after` | datetime | no | Return issues created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `created_before` | datetime | no | Return issues created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | -| `due_date` | string | no | Return issues that have no due date (`0`) or whose due date is this week, this month, between two weeks ago and next month, or which are overdue. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _(Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ | +| `due_date` | string | no | Return issues that have no due date, are overdue, or whose due date is this week, this month, or between two weeks ago and next month. Accepts: `0` (no due date), `overdue`, `week`, `month`, `next_month_and_previous_two_weeks`. _(Introduced in [GitLab 13.3](https://gitlab.com/gitlab-org/gitlab/-/issues/233420))_ | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `iids[]` | integer array | no | Return only the issues having the given `iid` | | `labels` | string | no | Comma-separated list of label names, issues must have all labels to be returned. `None` lists all issues with no labels. `Any` lists all issues with at least one label. `No+Label` (Deprecated) lists all issues with no labels. Predefined names are case-insensitive. | @@ -424,7 +424,7 @@ GET /projects/:id/issues?state=opened | `my_reaction_emoji` | string | no | Return issues reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0)_ | | `not` | Hash | no | Return issues that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `my_reaction_emoji`, `search`, `in` | | `order_by` | string | no | Return issues ordered by `created_at`, `updated_at`, `priority`, `due_date`, `relative_position`, `label_priority`, `milestone_due`, `popularity`, `weight` fields. Default is `created_at` | -| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5. [Changed to snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) in GitLab 11.0)_ | +| `scope` | string | no | Return issues for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13004) in GitLab 9.5. [Changed to snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) in GitLab 11.0)_ | | `search` | string | no | Search project issues against their `title` and `description` | | `sort` | string | no | Return issues sorted in `asc` or `desc` order. Default is `desc` | | `state` | string | no | Return all issues or just those that are `opened` or `closed` | @@ -721,7 +721,7 @@ The `assignee` column is deprecated. We now show it as a single-sized array `ass to the GitLab EE API. WARNING: -The `epic_iid` attribute is deprecated, and [will be removed in version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157). +The `epic_iid` attribute is deprecated, and [scheduled for removal in API version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157). Please use `iid` of the `epic` attribute instead. NOTE: @@ -882,7 +882,7 @@ WARNING: The `assignee` column is deprecated. We now show it as a single-sized array `assignees` to conform to the GitLab EE API. WARNING: -The `epic_iid` attribute is deprecated and [will be removed in version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157). +The `epic_iid` attribute is deprecated and [scheduled for removal in API version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157). Please use `iid` of the `epic` attribute instead. NOTE: @@ -904,9 +904,9 @@ POST /projects/:id/issues | `created_at` | string | no | When the issue was created. Date time string, ISO 8601 formatted, for example `2016-03-11T03:45:40Z`. Requires administrator or project/group owner rights. | | `description` | string | no | The description of an issue. Limited to 1,048,576 characters. | | `discussion_to_resolve` | string | no | The ID of a discussion to resolve. This fills out the issue with a default description and mark the discussion as resolved. Use in combination with `merge_request_to_resolve_discussions_of`. | -| `due_date` | string | no | The due date. Date time string in the format YEAR-MONTH-DAY, for example `2016-03-11` | +| `due_date` | string | no | The due date. Date time string in the format `YYYY-MM-DD`, for example `2016-03-11` | | `epic_id` **(PREMIUM)** | integer | no | ID of the epic to add the issue to. Valid values are greater than or equal to 0. | -| `epic_iid` **(PREMIUM)** | integer | no | IID of the epic to add the issue to. Valid values are greater than or equal to 0. (deprecated, [will be removed in version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157)) | +| `epic_iid` **(PREMIUM)** | integer | no | IID of the epic to add the issue to. Valid values are greater than or equal to 0. (deprecated, [scheduled for removal in API version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157)) | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `iid` | integer/string | no | The internal ID of the project's issue (requires administrator or project owner rights) | | `labels` | string | no | Comma-separated label names for an issue | @@ -1048,9 +1048,9 @@ PUT /projects/:id/issues/:issue_iid | `confidential` | boolean | no | Updates an issue to be confidential | | `description` | string | no | The description of an issue. Limited to 1,048,576 characters. | | `discussion_locked` | boolean | no | Flag indicating if the issue's discussion is locked. If the discussion is locked only project members can add or edit comments. | -| `due_date` | string | no | The due date. Date time string in the format YEAR-MONTH-DAY, for example `2016-03-11` | +| `due_date` | string | no | The due date. Date time string in the format `YYYY-MM-DD`, for example `2016-03-11` | | `epic_id` **(PREMIUM)** | integer | no | ID of the epic to add the issue to. Valid values are greater than or equal to 0. | -| `epic_iid` **(PREMIUM)** | integer | no | IID of the epic to add the issue to. Valid values are greater than or equal to 0. (deprecated, [will be removed in version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157)) | +| `epic_iid` **(PREMIUM)** | integer | no | IID of the epic to add the issue to. Valid values are greater than or equal to 0. (deprecated, [scheduled for removal in API version 5](https://gitlab.com/gitlab-org/gitlab/-/issues/35157)) | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | | `issue_iid` | integer | yes | The internal ID of a project's issue | | `labels` | string | no | Comma-separated label names for an issue. Set to an empty string to unassign all labels. | @@ -1168,7 +1168,7 @@ WARNING: ## Delete an issue -Only for admins and project owners. Deletes the issue in question. +Only for administrators and project owners. Deletes an issue. ```plaintext DELETE /projects/:id/issues/:issue_iid @@ -1207,8 +1207,8 @@ curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab ## Move an issue Moves an issue to a different project. If the target project -equals the source project or the user has insufficient permissions to move an -issue, status code `400` and an error message is returned. +is the source project or the user has insufficient permissions, +an error message with status code `400` is returned. If a given label or milestone with the same name also exists in the target project, it's then assigned to the issue being moved. @@ -1987,9 +1987,9 @@ Example response: ] ``` -## List merge requests that will close issue on merge +## List merge requests that close a particular issue on merge -Get all the merge requests that will close an issue when merged. +Get all merge requests that close a particular issue when merged. If the project is private or the issue is confidential, you need to provide credentials to authorize. The preferred way to do this, is by using [personal access tokens](../user/profile/personal_access_tokens.md). @@ -2112,7 +2112,7 @@ Comments are done via the [notes](notes.md) resource. ## Get user agent details -Available only for admins. +Available only for administrators. ```plaintext GET /projects/:id/issues/:issue_iid/user_agent_detail @@ -2211,3 +2211,26 @@ Example response: } ] ``` + +## Delete metric image + +Available only for Incident issues. + +```plaintext +DELETE /projects/:id/issues/:issue_iid/metric_images/:image_id +``` + +| Attribute | Type | Required | Description | +|-------------|---------|----------|--------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | +| `issue_iid` | integer | yes | The internal ID of a project's issue | +| `image_id` | integer | yes | The ID of the image | + +```shell +curl --header "PRIVATE-TOKEN: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/5/issues/93/metric_images/1" +``` + +Can return the following status codes: + +- `204 No Content`, if the image was deleted successfully. +- `400 Bad Request`, if the image could not be deleted. diff --git a/doc/api/job_artifacts.md b/doc/api/job_artifacts.md index 229b90282f0..a6b5e9e4711 100644 --- a/doc/api/job_artifacts.md +++ b/doc/api/job_artifacts.md @@ -33,7 +33,7 @@ To use this in a [`script` definition](../ci/yaml/README.md#script) inside - The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable. For example, the following job downloads the artifacts of the job with ID - `42`. Note that the command is wrapped into single quotes since it contains a + `42`. Note that the command is wrapped into single quotes because it contains a colon (`:`): ```yaml @@ -99,7 +99,7 @@ To use this in a [`script` definition](../ci/yaml/README.md#script) inside - The `JOB-TOKEN` header with the GitLab-provided `CI_JOB_TOKEN` variable. For example, the following job downloads the artifacts of the `test` job of the `master` branch. Note that the command is wrapped into single quotes - since it contains a colon (`:`): + because it contains a colon (`:`): ```yaml artifact_download: @@ -130,7 +130,7 @@ Possible response status codes: > Introduced in GitLab 10.0 -Download a single artifact file from a job with a specified ID from within +Download a single artifact file from a job with a specified ID from inside the job's artifacts zipped archive. The file is extracted from the archive and streamed to the client. @@ -165,7 +165,7 @@ Possible response status codes: > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/23538) in GitLab 11.5. Download a single artifact file for a specific job of the latest successful -pipeline for the given reference name from within the job's artifacts archive. +pipeline for the given reference name from inside the job's artifacts archive. The file is extracted from the archive and streamed to the client. In [GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/201784) and later, artifacts diff --git a/doc/api/members.md b/doc/api/members.md index 05914b50cd7..47b686d9275 100644 --- a/doc/api/members.md +++ b/doc/api/members.md @@ -398,7 +398,7 @@ POST /groups/:id/members/:user_id/override | `user_id` | integer | yes | The user ID of the member | ```shell -curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/override" +curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/override" ``` Example response: @@ -435,7 +435,7 @@ DELETE /groups/:id/members/:user_id/override | `user_id` | integer | yes | The user ID of the member | ```shell -curl --request PUT --header "PRIVATE-TOKEN: 9koXpg98eAheJpvBs5tK" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/override" +curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id/override" ``` Example response: @@ -468,7 +468,7 @@ DELETE /projects/:id/members/:user_id | --------- | ---- | -------- | ----------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project or group](README.md#namespaced-path-encoding) owned by the authenticated user | | `user_id` | integer | yes | The user ID of the member | -| `unassign_issuables` | boolean | false | Flag indicating if the removed member should be unassigned from any issues or merge requests within given group or project | +| `unassign_issuables` | boolean | false | Flag indicating if the removed member should be unassigned from any issues or merge requests inside a given group or project | ```shell curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/members/:user_id" diff --git a/doc/api/merge_requests.md b/doc/api/merge_requests.md index d2144a2c0c5..c43ac96a42f 100644 --- a/doc/api/merge_requests.md +++ b/doc/api/merge_requests.md @@ -7,15 +7,43 @@ type: reference, api # Merge requests API -Every API call to merge requests must be authenticated. +> - `author_id`, `author_username`, and `assignee_id` were [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5. +> - `my_reaction_emoji` was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0. +> - For the `scope` attribute, `created-by-me` and `assigned-to-me` were [deprecated](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) in favor of `created_by_me` and `assigned_to_me` in GitLab 11.0. +> - `with_labels_details` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) in GitLab 12.7. +> - `author_username` and `author_username` were [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10. +> - `reference` was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354) in GitLab 12.10 in favour of `references`. +> - `with_merge_status_recheck` was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0. +> - `reviewer_username` and `reviewer_id` were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49341) in GitLab 13.8. -WARNING: -> `reference` attribute in response is deprecated in favour of `references`. -> Introduced [GitLab 12.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/20354) +Every API call to merge requests must be authenticated. -NOTE: -> `references.relative` is relative to the group / project that the merge request is being requested. When merge request is fetched from its project -> `relative` format would be the same as `short` format and when requested across groups / projects it is expected to be the same as `full` format. +**Important notes:** + +- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/29984) in GitLab 12.8, the mergeability (`merge_status`) +of each merge request is checked asynchronously when a request is made to this endpoint. Poll this API endpoint +to get updated status. This affects the `has_conflicts` property as it is dependent on the `merge_status`. It returns +`false` unless `merge_status` is `cannot_be_merged`. +- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) in GitLab 13.0, listing merge requests may +not proactively update `merge_status` (which also affects the `has_conflicts`), as this can be an expensive operation. +If you need the value of these fields from this endpoint, set the `with_merge_status_recheck` parameter to +`true` in the query. +- `references.relative` is relative to the group or project that the merge request is being requested. When the merge request +is fetched from its project, `relative` format would be the same as `short` format, and when requested across groups or projects, it is expected to be the same as `full` format. +- If `approvals_before_merge` **(STARTER)** is not provided, it inherits the value from the target project. If provided, the following conditions must hold for it to take effect: + + - The target project's `approvals_before_merge` must be greater than zero. A + value of zero disables approvals for that project. + - The provided value of `approvals_before_merge` must be greater than the + target project's `approvals_before_merge`. + + This API returns `HTTP 201 Created` for a successful response. + +- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46190) in GitLab 13.6, +diffs associated with the set of changes have the same size limitations applied as other diffs +returned by the API or viewed via the UI. When these limits impact the results, the `overflow` +field contains a value of `true`. Diff data without these limits applied can be retrieved by +adding the `access_raw_diffs` parameter, but it is slower and more resource-intensive. ## List merge requests @@ -26,7 +54,7 @@ default it returns only merge requests created by the current user. To get all merge requests, use parameter `scope=all`. The `state` parameter can be used to get only merge requests with a -given state (`opened`, `closed`, `locked`, or `merged`) or all of them (`all`). It should be noted that when searching by `locked` it will mostly return no results as it is a short-lived, transitional state. +given state (`opened`, `closed`, `locked`, or `merged`) or all of them (`all`). It should be noted that when searching by `locked` it mostly returns no results as it is a short-lived, transitional state. The pagination parameters `page` and `per_page` can be used to restrict the list of merge requests. @@ -47,50 +75,37 @@ Parameters: | Attribute | Type | Required | Description | | ------------------------------- | -------------- | -------- | ---------------------------------------------------------------------------------------------------------------------- | -| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged` | -| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` | -| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` | +| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`. | +| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`. | +| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc`. | | `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. | -| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request | +| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. | | `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. | -| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) | -| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) | +| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. | +| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. | | `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `created_before` | datetime | no | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `updated_after` | datetime | no | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `updated_before` | datetime | no | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`. Defaults to `created_by_me`<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead. | -| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me` -| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10)_ | | +| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. Combine with `scope=all` or `scope=assigned_to_me`. | +| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. | | `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. | | `approver_ids` **(STARTER)** | integer array | no | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. | | `approved_by_ids` **(STARTER)** | integer array | no | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. | -| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0)_ | -| `source_branch` | string | no | Return merge requests with the given source branch | -| `target_branch` | string | no | Return merge requests with the given target branch | -| `search` | string | no | Search merge requests against their `title` and `description` | -| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description` | -| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests | -| `not` | Hash | no | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `my_reaction_emoji` | +| `reviewer_id` | integer | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`. | +| `reviewer_username` | string | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. | +| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. | +| `source_branch` | string | no | Return merge requests with the given source branch. | +| `target_branch` | string | no | Return merge requests with the given target branch. | +| `search` | string | no | Search merge requests against their `title` and `description`. | +| `in` | string | no | Modify the scope of the `search` attribute. `title`, `description`, or a string joining them with comma. Default is `title,description`. | +| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests. | +| `not` | Hash | no | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. | | `environment` | string | no | Returns merge requests deployed to the given environment. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `deployed_before` | datetime | no | Return merge requests deployed before the given date/time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `deployed_after` | datetime | no | Return merge requests deployed after the given date/time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | -NOTE: -[Starting in GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890), -listing merge requests may not proactively update the `merge_status` field -(which also affects the `has_conflicts` field), as this can be an expensive -operation. If you are interested in the value of these fields from this -endpoint, set the `with_merge_status_recheck` parameter to `true` in the query. - -NOTE: -[Starting in GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/29984), -the mergeability (`merge_status`) of each merge request will be checked -asynchronously when a request is made to this endpoint. Poll this API endpoint -to get updated status. This affects the `has_conflicts` property as it is -dependent on the `merge_status`. It'll return `false` unless `merge_status` is -`cannot_be_merged`. - ```json [ { @@ -141,6 +156,14 @@ dependent on the `merge_status`. It'll return `false` unless `merge_status` is "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], + "reviewers": [{ + "id": 2, + "name": "Sam Bauch", + "username": "kenyatta_oconnell", + "state": "active", + "avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon", + "web_url": "http://gitlab.example.com//kenyatta_oconnell" + }], "source_project_id": 2, "target_project_id": 3, "labels": [ @@ -193,7 +216,7 @@ dependent on the `merge_status`. It'll return `false` unless `merge_status` is ] ``` -Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see +Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see the `approvals_before_merge` parameter: ```json @@ -224,43 +247,47 @@ GET /projects/:id/merge_requests?my_reaction_emoji=star ``` `project_id` represents the ID of the project where the MR resides. -`project_id` will always equal `target_project_id`. +`project_id` always equals `target_project_id`. In the case of a merge request from the same project, `source_project_id`, `target_project_id` and `project_id` -will be the same. In the case of a merge request from a fork, -`target_project_id` and `project_id` will be the same and -`source_project_id` will be the fork project's ID. +are the same. In the case of a merge request from a fork, +`target_project_id` and `project_id` are the same and +`source_project_id` is the fork project's ID. Parameters: | Attribute | Type | Required | Description | | ------------------------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ | -| `id` | integer | yes | The ID of a project | -| `iids[]` | integer array | no | Return the request having the given `iid` | -| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged` | -| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at` | -| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc` | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `iids[]` | integer array | no | Return the request having the given `iid`. | +| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`. | +| `order_by` | string | no | Return requests ordered by `created_at` or `updated_at` fields. Default is `created_at`. | +| `sort` | string | no | Return requests sorted in `asc` or `desc` order. Default is `desc`. | | `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. | -| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request | +| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. | | `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. | -| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413) | -| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) | +| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. | +| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. | | `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `created_before` | datetime | no | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `updated_after` | datetime | no | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | | `updated_before` | datetime | no | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | -| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> For versions before 11.0, use the now deprecated `created-by-me` or `assigned-to-me` scopes instead.<br> _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5. [Changed to snake_case](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18935) in GitLab 11.0)_ | -| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5)_ -| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10)_ | | -| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5)_ | +| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me`, or `all`. | +| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. | +| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`.| +| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. | | `approver_ids` **(STARTER)** | integer array | no | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. | | `approved_by_ids` **(STARTER)** | integer array | no | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. | -| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0)_ | -| `source_branch` | string | no | Return merge requests with the given source branch | -| `target_branch` | string | no | Return merge requests with the given target branch | -| `search` | string | no | Search merge requests against their `title` and `description` | -| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests | +| `reviewer_id` | integer | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`. | +| `reviewer_username` | string | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#reviewer) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. | + +| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. | +| `source_branch` | string | no | Return merge requests with the given source branch. | +| `target_branch` | string | no | Return merge requests with the given target branch. | +| `search` | string | no | Search merge requests against their `title` and `description`. | +| `wip` | string | no | Filter merge requests against their `wip` status. `yes` to return *only* WIP merge requests, `no` to return *non* WIP merge requests. | +| `not` | Hash | no | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. | ```json [ @@ -312,6 +339,14 @@ Parameters: "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], + "reviewers": [{ + "id": 2, + "name": "Sam Bauch", + "username": "kenyatta_oconnell", + "state": "active", + "avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon", + "web_url": "http://gitlab.example.com//kenyatta_oconnell" + }], "source_project_id": 2, "target_project_id": 3, "labels": [ @@ -366,7 +401,7 @@ Parameters: ] ``` -Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see +Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see the `approvals_before_merge` parameter: ```json @@ -401,30 +436,33 @@ Parameters: | Attribute | Type | Required | Description | | ------------------------------- | -------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------ | -| `id` | integer | yes | The ID of a group | -| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged` | -| `order_by` | string | no | Return merge requests ordered by `created_at` or `updated_at` fields. Default is `created_at` | -| `sort` | string | no | Return merge requests sorted in `asc` or `desc` order. Default is `desc` | +| `id` | integer/string | yes | The ID or [URL-encoded path of the group](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `state` | string | no | Return all merge requests or just those that are `opened`, `closed`, `locked`, or `merged`. | +| `order_by` | string | no | Return merge requests ordered by `created_at` or `updated_at` fields. Default is `created_at`. | +| `sort` | string | no | Return merge requests sorted in `asc` or `desc` order. Default is `desc`. | | `milestone` | string | no | Return merge requests for a specific milestone. `None` returns merge requests with no milestone. `Any` returns merge requests that have an assigned milestone. | -| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request | +| `view` | string | no | If `simple`, returns the `iid`, URL, title, description, and basic state of merge request. | | `labels` | string | no | Return merge requests matching a comma separated list of labels. `None` lists all merge requests with no labels. `Any` lists all merge requests with at least one label. `No+Label` (Deprecated) lists all merge requests with no labels. Predefined names are case-insensitive. | -| `with_labels_details` | boolean | no | If `true`, response will return more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413)| -| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890) | -| `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | -| `created_before` | datetime | no | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | -| `updated_after` | datetime | no | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | -| `updated_before` | datetime | no | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`) | -| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`.<br> | -| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5)_ -| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10)_ | | -| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5)_ | +| `with_labels_details` | boolean | no | If `true`, response returns more details for each label in labels field: `:name`, `:color`, `:description`, `:description_html`, `:text_color`. Default is `false`. Introduced in [GitLab 12.7](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21413).| +| `with_merge_status_recheck` | boolean | no | If `true`, this projection requests (but does not guarantee) that the `merge_status` field be recalculated asynchronously. Default is `false`. Introduced in [GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/31890). | +| `created_after` | datetime | no | Return merge requests created on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | +| `created_before` | datetime | no | Return merge requests created on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | +| `updated_after` | datetime | no | Return merge requests updated on or after the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | +| `updated_before` | datetime | no | Return merge requests updated on or before the given time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | +| `scope` | string | no | Return merge requests for the given scope: `created_by_me`, `assigned_to_me` or `all`. | +| `author_id` | integer | no | Returns merge requests created by the given user `id`. Mutually exclusive with `author_username`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5)_. | +| `author_username` | string | no | Returns merge requests created by the given `username`. Mutually exclusive with `author_id`. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 12.10)_. | +| `assignee_id` | integer | no | Returns merge requests assigned to the given user `id`. `None` returns unassigned merge requests. `Any` returns merge requests with an assignee. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/13060) in GitLab 9.5)_. | | `approver_ids` **(STARTER)** | integer array | no | Returns merge requests which have specified all the users with the given `id`s as individual approvers. `None` returns merge requests without approvers. `Any` returns merge requests with an approver. | | `approved_by_ids` **(STARTER)** | integer array | no | Returns merge requests which have been approved by all the users with the given `id`s (Max: 5). `None` returns merge requests with no approvals. `Any` returns merge requests with an approval. | -| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0)_ | -| `source_branch` | string | no | Return merge requests with the given source branch | -| `target_branch` | string | no | Return merge requests with the given target branch | -| `search` | string | no | Search merge requests against their `title` and `description` | -| `non_archived` | boolean | no | Return merge requests from non archived projects only. Default is true. _(Introduced in [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23809))_ | +| `reviewer_id` | integer | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#enable-or-disable-merge-request-reviewers) with the given user `id`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_username`. | +| `reviewer_username` | string | no | Returns merge requests which have the user as a [reviewer](../user/project/merge_requests/getting_started.md#enable-or-disable-merge-request-reviewers) with the given `username`. `None` returns merge requests with no reviewers. `Any` returns merge requests with any reviewer. Mutually exclusive with `reviewer_id`. | +| `my_reaction_emoji` | string | no | Return merge requests reacted by the authenticated user by the given `emoji`. `None` returns issues not given a reaction. `Any` returns issues given at least one reaction. _([Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/14016) in GitLab 10.0)_. | +| `source_branch` | string | no | Return merge requests with the given source branch. | +| `target_branch` | string | no | Return merge requests with the given target branch. | +| `search` | string | no | Search merge requests against their `title` and `description`. | +| `non_archived` | boolean | no | Return merge requests from non archived projects only. Default is true. _(Introduced in [GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23809))_. | +| `not` | Hash | no | Return merge requests that do not match the parameters supplied. Accepts: `labels`, `milestone`, `author_id`, `author_username`, `assignee_id`, `assignee_username`, `reviewer_id`, `reviewer_username`, `my_reaction_emoji`. | ```json [ @@ -476,6 +514,14 @@ Parameters: "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], + "reviewers": [{ + "id": 2, + "name": "Sam Bauch", + "username": "kenyatta_oconnell", + "state": "active", + "avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon", + "web_url": "http://gitlab.example.com//kenyatta_oconnell" + }], "source_project_id": 2, "target_project_id": 3, "labels": [ @@ -528,7 +574,7 @@ Parameters: ] ``` -Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see +Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see the `approvals_before_merge` parameter: ```json @@ -548,7 +594,7 @@ Shows information about a single merge request. **Note**: the `changes_count` value in the response is a string, not an integer. This is because when an MR has too many changes to display and store, -it will be capped at 1,000. In that case, the API will return the string +it is capped at 1,000. In that case, the API returns the string `"1000+"` for the changes count. ```plaintext @@ -557,19 +603,13 @@ GET /projects/:id/merge_requests/:merge_request_iid Parameters: -- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user -- `merge_request_iid` (required) - The internal ID of the merge request -- `render_html` (optional) - If `true` response includes rendered HTML for title and description -- `include_diverged_commits_count` (optional) - If `true` response includes the commits behind the target branch -- `include_rebase_in_progress` (optional) - If `true` response includes whether a rebase operation is in progress - -NOTE: -[Starting in GitLab 12.8](https://gitlab.com/gitlab-org/gitlab/-/issues/29984), -the mergeability (`merge_status`) of a merge request will be checked -asynchronously when a request is made to this endpoint. Poll this API endpoint -to get updated status. This affects the `has_conflicts` property as it is -dependent on the `merge_status`. It'll return `false` unless `merge_status` is -`cannot_be_merged`. +| Attribute | Type | Required | Description | +|----------------------------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | +| `render_html` | integer | no | If `true` response includes rendered HTML for title and description. | +| `include_diverged_commits_count` | boolean | no | If `true` response includes the commits behind the target branch. | +| `include_rebase_in_progress` | boolean | no | If `true` response includes whether a rebase operation is in progress. | ```json { @@ -612,6 +652,14 @@ dependent on the `merge_status`. It'll return `false` unless `merge_status` is "avatar_url": "http://www.gravatar.com/avatar/46f6f7dc858ada7be1853f7fb96e81da?s=80&d=identicon", "web_url": "https://gitlab.example.com/axel.block" }], + "reviewers": [{ + "id": 2, + "name": "Sam Bauch", + "username": "kenyatta_oconnell", + "state": "active", + "avatar_url": "https://www.gravatar.com/avatar/956c92487c6f6f7616b536927e22c9a0?s=80&d=identicon", + "web_url": "http://gitlab.example.com//kenyatta_oconnell" + }], "source_project_id": 2, "target_project_id": 3, "labels": [ @@ -697,7 +745,7 @@ dependent on the `merge_status`. It'll return `false` unless `merge_status` is } ``` -Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see +Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see the `approvals_before_merge` parameter: ```json @@ -719,8 +767,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/participants Parameters: -- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user -- `merge_request_iid` (required) - The internal ID of the merge request +| Attribute | Type | Required | Description | +|----------------------------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```json [ @@ -753,8 +803,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/commits Parameters: -- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user -- `merge_request_iid` (required) - The internal ID of the merge request +| Attribute | Type | Required | Description | +|----------------------------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```json [ @@ -787,17 +839,13 @@ Shows information about the merge request including its files and changes. GET /projects/:id/merge_requests/:merge_request_iid/changes ``` -[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46190) in GitLab 13.6, -diffs associated with the set of changes will have the same size limitations applied as other diffs -returned by the API or viewed via the UI. When these limits impact the results, the `overflow` -field will contain a value of `true`. Diff data without these limits applied can be retrieved by -adding the `access_raw_diffs` parameter, however, it will be slower and more resource-intensive. - Parameters: -- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. -- `merge_request_iid` (required) - The internal ID of the merge request. -- `access_raw_diffs` (optional) - Retrieve change diffs without size limitations. +| Attribute | Type | Required | Description | +|----------------------------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | +| `access_raw_diffs` | boolean | no | Retrieve change diffs without size limitations. | ```json { @@ -898,7 +946,7 @@ Parameters: ## List MR pipelines -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15454) in GitLab 10.5.0. +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/15454) in GitLab 10.5. Get a list of merge request pipelines. @@ -908,8 +956,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/pipelines Parameters: -- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user -- `merge_request_iid` (required) - The internal ID of the merge request +| Attribute | Type | Required | Description | +|----------------------------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```json [ @@ -926,7 +976,9 @@ Parameters: > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/31722) in GitLab 12.3. -Create a new [pipeline for a merge request](../ci/merge_request_pipelines/index.md). A pipeline created via this endpoint will not run a regular branch/tag pipeline, it requires `.gitlab-ci.yml` to be configured with `only: [merge_requests]` to create jobs. +Create a new [pipeline for a merge request](../ci/merge_request_pipelines/index.md). +A pipeline created via this endpoint doesn't run a regular branch/tag pipeline. +It requires `.gitlab-ci.yml` to be configured with `only: [merge_requests]` to create jobs. The new pipeline can be: @@ -940,8 +992,10 @@ POST /projects/:id/merge_requests/:merge_request_iid/pipelines Parameters: -- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) -- `merge_request_iid` (required) - The internal ID of the merge request +| Attribute | Type | Required | Description | +|----------------------------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```json { @@ -993,29 +1047,19 @@ POST /projects/:id/merge_requests | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `source_branch` | string | yes | The source branch | -| `target_branch` | string | yes | The target branch | -| `title` | string | yes | Title of MR | -| `assignee_id` | integer | no | Assignee user ID | +| `source_branch` | string | yes | The source branch. | +| `target_branch` | string | yes | The target branch. | +| `title` | string | yes | Title of MR. | +| `assignee_id` | integer | no | Assignee user ID. | | `assignee_ids` | integer array | no | The ID of the user(s) to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. | | `description` | string | no | Description of MR. Limited to 1,048,576 characters. | -| `target_project_id` | integer | no | The target project (numeric ID) | -| `labels` | string | no | Labels for MR as a comma-separated list | -| `milestone_id` | integer | no | The global ID of a milestone | -| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging | -| `allow_collaboration` | boolean | no | Allow commits from members who can merge to the target branch | -| `allow_maintainer_to_push` | boolean | no | Deprecated, see allow_collaboration | -| `squash` | boolean | no | Squash commits into a single commit when merging | - -If `approvals_before_merge` **(STARTER)** is not provided, it inherits the value from the -target project. If it is provided, then the following conditions must hold in -order for it to take effect: - -1. The target project's `approvals_before_merge` must be greater than zero. A - value of zero disables approvals for that project. -1. The provided value of `approvals_before_merge` must be greater than the - target project's `approvals_before_merge`. -1. This API returns 201 (created) for a successful response. +| `target_project_id` | integer | no | The target project (numeric ID). | +| `labels` | string | no | Labels for MR as a comma-separated list. | +| `milestone_id` | integer | no | The global ID of a milestone. | +| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging. | +| `allow_collaboration` | boolean | no | Allow commits from members who can merge to the target branch. | +| `allow_maintainer_to_push` | boolean | no | Deprecated, see `allow_collaboration`. | +| `squash` | boolean | no | Squash commits into a single commit when merging. | ```json { @@ -1128,7 +1172,7 @@ order for it to take effect: } ``` -Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see +Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see the `approvals_before_merge` parameter: ```json @@ -1150,10 +1194,10 @@ PUT /projects/:id/merge_requests/:merge_request_iid | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `merge_request_iid` | integer | yes | The ID of a merge request | -| `target_branch` | string | no | The target branch | -| `title` | string | no | Title of MR | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The ID of a merge request. | +| `target_branch` | string | no | The target branch. | +| `title` | string | no | Title of MR. | | `assignee_id` | integer | no | The ID of the user to assign the merge request to. Set to `0` or provide an empty value to unassign all assignees. | | `assignee_ids` | integer array | no | The ID of the user(s) to assign the MR to. Set to `0` or provide an empty value to unassign all assignees. | | `milestone_id` | integer | no | The global ID of a milestone to assign the merge request to. Set to `0` or provide an empty value to unassign a milestone.| @@ -1161,12 +1205,12 @@ PUT /projects/:id/merge_requests/:merge_request_iid | `add_labels` | string | no | Comma-separated label names to add to a merge request. | | `remove_labels` | string | no | Comma-separated label names to remove from a merge request. | | `description` | string | no | Description of MR. Limited to 1,048,576 characters. | -| `state_event` | string | no | New state (close/reopen) | -| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging | -| `squash` | boolean | no | Squash commits into a single commit when merging | +| `state_event` | string | no | New state (close/reopen). | +| `remove_source_branch` | boolean | no | Flag indicating if a merge request should remove the source branch when merging. | +| `squash` | boolean | no | Squash commits into a single commit when merging. | | `discussion_locked` | boolean | no | Flag indicating if the merge request's discussion is locked. If the discussion is locked only project members can add, edit or resolve comments. | -| `allow_collaboration` | boolean | no | Allow commits from members who can merge to the target branch | -| `allow_maintainer_to_push` | boolean | no | Deprecated, see allow_collaboration | +| `allow_collaboration` | boolean | no | Allow commits from members who can merge to the target branch. | +| `allow_maintainer_to_push` | boolean | no | Deprecated, see `allow_collaboration`. | Must include at least one non-required attribute from above. @@ -1289,7 +1333,7 @@ Must include at least one non-required attribute from above. } ``` -Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see +Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see the `approvals_before_merge` parameter: ```json @@ -1303,7 +1347,7 @@ the `approvals_before_merge` parameter: ## Delete a merge request -Only for admins and project owners. Deletes the merge request in question. +Only for administrators and project owners. Deletes the merge request in question. ```plaintext DELETE /projects/:id/merge_requests/:merge_request_iid @@ -1311,8 +1355,8 @@ DELETE /projects/:id/merge_requests/:merge_request_iid | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `merge_request_iid` | integer | yes | The internal ID of the merge request | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```shell curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/4/merge_requests/85" @@ -1322,13 +1366,13 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git Merge changes submitted with MR using this API. -If merge request is unable to be accepted (such as Draft, Closed, Pipeline Pending Completion, or Failed while requiring Success) - you'll get a `405` and the error message 'Method Not Allowed' +If a merge request is unable to be accepted (such as Draft, Closed, Pipeline Pending Completion, or Failed while requiring Success) - you receive a `405` and the error message 'Method Not Allowed' -If it has some conflicts and can not be merged - you'll get a `406` and the error message 'Branch cannot be merged' +If it has some conflicts and can not be merged - you receive a `406` and the error message 'Branch cannot be merged' -If the `sha` parameter is passed and does not match the HEAD of the source - you'll get a `409` and the error message 'SHA does not match HEAD of source branch' +If the `sha` parameter is passed and does not match the HEAD of the source - you receive a `409` and the error message 'SHA does not match HEAD of source branch' -If you don't have permissions to accept this merge request - you'll get a `401` +If you don't have permissions to accept this merge request - you receive a `401` ```plaintext PUT /projects/:id/merge_requests/:merge_request_iid/merge @@ -1336,14 +1380,16 @@ PUT /projects/:id/merge_requests/:merge_request_iid/merge Parameters: -- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user -- `merge_request_iid` (required) - Internal ID of MR -- `merge_commit_message` (optional) - Custom merge commit message -- `squash_commit_message` (optional) - Custom squash commit message -- `squash` (optional) - if `true` the commits will be squashed into a single commit on merge -- `should_remove_source_branch` (optional) - if `true` removes the source branch -- `merge_when_pipeline_succeeds` (optional) - if `true` the MR is merged when the pipeline succeeds -- `sha` (optional) - if present, then this SHA must match the HEAD of the source branch, otherwise the merge will fail +| Attribute | Type | Required | Description | +|--------------------------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | +| `merge_commit_message` | string | no | Custom merge commit message. | +| `squash_commit_message` | string | no | Custom squash commit message. | +| `squash` | boolean | no | If `true` the commits the commits are squashed into a single commit on merge. | +| `should_remove_source_branch` | boolean | no | If `true` removes the source branch. | +| `merge_when_pipeline_succeeds` | boolean | no | If `true` the MR is merged when the pipeline succeeds. | +| `sha` | string | no | If present, then this SHA must match the HEAD of the source branch, otherwise the merge fails. | ```json { @@ -1464,7 +1510,7 @@ Parameters: } ``` -Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see +Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see the `approvals_before_merge` parameter: ```json @@ -1479,15 +1525,15 @@ the `approvals_before_merge` parameter: ## Merge to default merge ref path Merge the changes between the merge request source and target branches into `refs/merge-requests/:iid/merge` -ref, of the target project repository, if possible. This ref will have the state the target branch would have if +ref, of the target project repository, if possible. This ref has the state the target branch would have if a regular merge action was taken. This is not a regular merge action given it doesn't change the merge request target branch state in any manner. This ref (`refs/merge-requests/:iid/merge`) isn't necessarily overwritten when submitting -requests to this API, though it'll make sure the ref has the latest possible state. +requests to this API, though it makes sure the ref has the latest possible state. -If the merge request has conflicts, is empty or already merged, you'll get a `400` and a descriptive error message. +If the merge request has conflicts, is empty or already merged, you receive a `400` and a descriptive error message. It returns the HEAD commit of `refs/merge-requests/:iid/merge` in the response body in case of `200`. @@ -1497,8 +1543,10 @@ GET /projects/:id/merge_requests/:merge_request_iid/merge_ref Parameters: -- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user -- `merge_request_iid` (required) - Internal ID of MR +| Attribute | Type | Required | Description | +|--------------------------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```json { @@ -1508,11 +1556,9 @@ Parameters: ## Cancel Merge When Pipeline Succeeds -If you don't have permissions to accept this merge request - you'll get a `401` - -If the merge request is already merged or closed - you get `405` and error message 'Method Not Allowed' - -In case the merge request is not set to be merged when the pipeline succeeds, you'll also get a `406` error. +- If you don't have permissions to accept this merge request - you receive a `HTTP 401 Unauthorized`. +- If the merge request is already merged or closed - you receive a `HTTP 405 Method Not Allowed` and the error message 'Method Not Allowed'. +- In case the merge request is not set to be merged when the pipeline succeeds, you also receive a `HTTP 406 Not Acceptable` error. ```plaintext POST /projects/:id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_succeeds @@ -1520,8 +1566,10 @@ POST /projects/:id/merge_requests/:merge_request_iid/cancel_merge_when_pipeline_ Parameters: -- `id` (required) - The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user -- `merge_request_iid` (required) - Internal ID of MR +| Attribute | Type | Required | Description | +|--------------------------------|----------------|----------|------------------------------------------------------------------------------------------------------------------| +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```json { @@ -1642,7 +1690,7 @@ Parameters: } ``` -Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see +Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see the `approvals_before_merge` parameter: ```json @@ -1660,7 +1708,7 @@ Automatically rebase the `source_branch` of the merge request against its `target_branch`. If you don't have permissions to push to the merge request's source branch - -you'll get a `403 Forbidden` response. +you receive a `403 Forbidden` response. ```plaintext PUT /projects/:id/merge_requests/:merge_request_iid/rebase @@ -1668,15 +1716,15 @@ PUT /projects/:id/merge_requests/:merge_request_iid/rebase | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `merge_request_iid` | integer | yes | The internal ID of the merge request | -| `skip_ci` | boolean | no | Set to `true` to skip creating a CI pipeline | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | +| `skip_ci` | boolean | no | Set to `true` to skip creating a CI pipeline. | ```shell curl --request PUT --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/76/merge_requests/1/rebase" ``` -This is an asynchronous request. The API will return a `202 Accepted` response +This is an asynchronous request. The API returns a `HTTP 202 Accepted` response if the request is enqueued successfully, with a response containing: ```json @@ -1689,7 +1737,7 @@ You can poll the [Get single MR](#get-single-mr) endpoint with the `include_rebase_in_progress` parameter to check the status of the asynchronous request. -If the rebase operation is ongoing, the response will include the following: +If the rebase operation is ongoing, the response includes the following: ```json { @@ -1698,7 +1746,7 @@ If the rebase operation is ongoing, the response will include the following: } ``` -Once the rebase operation has completed successfully, the response will include +After the rebase operation has completed successfully, the response includes the following: ```json @@ -1708,7 +1756,7 @@ the following: } ``` -If the rebase operation fails, the response will include the following: +If the rebase operation fails, the response includes the following: ```json { @@ -1721,7 +1769,7 @@ If the rebase operation fails, the response will include the following: Comments are done via the [notes](notes.md) resource. -## List issues that will close on merge +## List issues that close on merge Get all the issues that would be closed by merging the provided merge request. @@ -1731,8 +1779,8 @@ GET /projects/:id/merge_requests/:merge_request_iid/closes_issues | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `merge_request_iid` | integer | yes | The internal ID of the merge request | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/76/merge_requests/1/closes_issues" @@ -1785,7 +1833,7 @@ Example response when the GitLab issue tracker is used: ] ``` -Example response when an external issue tracker (e.g. Jira) is used: +Example response when an external issue tracker (for example, Jira) is used: ```json [ @@ -1799,7 +1847,7 @@ Example response when an external issue tracker (e.g. Jira) is used: ## Subscribe to a merge request Subscribes the authenticated user to a merge request to receive notification. If the user is already subscribed to the merge request, the -status code `304` is returned. +status code `HTTP 304 Not Modified` is returned. ```plaintext POST /projects/:id/merge_requests/:merge_request_iid/subscribe @@ -1807,8 +1855,8 @@ POST /projects/:id/merge_requests/:merge_request_iid/subscribe | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `merge_request_iid` | integer | yes | The internal ID of the merge request | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```shell curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/17/subscribe" @@ -1934,7 +1982,7 @@ Example response: } ``` -Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see +Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see the `approvals_before_merge` parameter: ```json @@ -1950,7 +1998,7 @@ the `approvals_before_merge` parameter: Unsubscribes the authenticated user from a merge request to not receive notifications from that merge request. If the user is -not subscribed to the merge request, the status code `304` is returned. +not subscribed to the merge request, the status code `HTTP 304 Not Modified` is returned. ```plaintext POST /projects/:id/merge_requests/:merge_request_iid/unsubscribe @@ -1958,8 +2006,8 @@ POST /projects/:id/merge_requests/:merge_request_iid/unsubscribe | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `merge_request_iid` | integer | yes | The internal ID of the merge request | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```shell curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/17/unsubscribe" @@ -2085,7 +2133,7 @@ Example response: } ``` -Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) will also see +Users on GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) also see the `approvals_before_merge` parameter: ```json @@ -2101,7 +2149,7 @@ the `approvals_before_merge` parameter: Manually creates a to-do item for the current user on a merge request. If there already exists a to-do item for the user on that merge request, -status code `304` is returned. +status code `HTTP 304 Not Modified` is returned. ```plaintext POST /projects/:id/merge_requests/:merge_request_iid/todo @@ -2109,8 +2157,8 @@ POST /projects/:id/merge_requests/:merge_request_iid/todo | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `merge_request_iid` | integer | yes | The internal ID of the merge request | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```shell curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/27/todo" @@ -2226,8 +2274,8 @@ GET /projects/:id/merge_requests/:merge_request_iid/versions | Attribute | Type | Required | Description | | --------- | ------- | -------- | --------------------- | -| `id` | String | yes | The ID of the project | -| `merge_request_iid` | integer | yes | The internal ID of the merge request | +| `id` | String | yes | The ID of the project. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions" @@ -2267,9 +2315,9 @@ GET /projects/:id/merge_requests/:merge_request_iid/versions/:version_id | Attribute | Type | Required | Description | | --------- | ------- | -------- | --------------------- | -| `id` | String | yes | The ID of the project | -| `merge_request_iid` | integer | yes | The internal ID of the merge request | -| `version_id` | integer | yes | The ID of the merge request diff version | +| `id` | String | yes | The ID of the project. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | +| `version_id` | integer | yes | The ID of the merge request diff version. | ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/merge_requests/1/versions/1" @@ -2335,9 +2383,9 @@ POST /projects/:id/merge_requests/:merge_request_iid/time_estimate | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `merge_request_iid` | integer | yes | The internal ID of the merge request | -| `duration` | string | yes | The duration in human format. e.g: 3h30m | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | +| `duration` | string | yes | The duration in human format, such as `3h30m`. | ```shell curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_estimate?duration=3h30m" @@ -2364,8 +2412,8 @@ POST /projects/:id/merge_requests/:merge_request_iid/reset_time_estimate | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `merge_request_iid` | integer | yes | The internal ID of a project's merge_request | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of a project's merge_request. | ```shell curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_time_estimate" @@ -2384,7 +2432,7 @@ Example response: ## Add spent time for a merge request -Adds spent time for this merge request +Adds spent time for this merge request. ```plaintext POST /projects/:id/merge_requests/:merge_request_iid/add_spent_time @@ -2392,9 +2440,9 @@ POST /projects/:id/merge_requests/:merge_request_iid/add_spent_time | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `merge_request_iid` | integer | yes | The internal ID of the merge request | -| `duration` | string | yes | The duration in human format. e.g: 3h30m | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | +| `duration` | string | yes | The duration in human format, such as `3h30m` | ```shell curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/add_spent_time?duration=1h" @@ -2421,8 +2469,8 @@ POST /projects/:id/merge_requests/:merge_request_iid/reset_spent_time | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `merge_request_iid` | integer | yes | The internal ID of a project's merge_request | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of a project's merge_request. | ```shell curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/reset_spent_time" @@ -2447,8 +2495,8 @@ GET /projects/:id/merge_requests/:merge_request_iid/time_stats | Attribute | Type | Required | Description | | --------- | ---- | -------- | ----------- | -| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user | -| `merge_request_iid` | integer | yes | The internal ID of the merge request | +| `id` | integer/string | yes | The ID or [URL-encoded path of the project](README.md#namespaced-path-encoding) owned by the authenticated user. | +| `merge_request_iid` | integer | yes | The internal ID of the merge request. | ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/5/merge_requests/93/time_stats" diff --git a/doc/api/notes.md b/doc/api/notes.md index 621d8179d98..fe20d5ab353 100644 --- a/doc/api/notes.md +++ b/doc/api/notes.md @@ -11,7 +11,7 @@ Notes are comments on: - Snippets - Issues - Merge requests -- Epics **(ULTIMATE)** +- Epics **(PREMIUM)** This includes system notes, which are notes about changes to the object (for example, when an assignee changes, GitLab posts a system note). @@ -185,6 +185,8 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git ## Snippets +The Snippets Notes API is intended for project-level snippets, and not for personal snippets. + ### List all snippet notes Gets a list of all notes for a single snippet. Snippet notes are comments users can post to a snippet. diff --git a/doc/api/oauth2.md b/doc/api/oauth2.md index 50d063bdf71..a80a97890ba 100644 --- a/doc/api/oauth2.md +++ b/doc/api/oauth2.md @@ -2,7 +2,7 @@ type: reference, howto stage: Manage group: Access -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technica l-writing/#designated-technical-writers +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers --- # GitLab as an OAuth2 provider @@ -19,17 +19,26 @@ documentation. This functionality is based on the GitLab currently supports the following authorization flows: -- **Web application flow:** Most secure and common type of flow, designed for - applications with secure server-side. -- **Implicit grant flow:** This flow is designed for user-agent only apps (e.g., single - page web application running on GitLab Pages). -- **Resource owner password credentials flow:** To be used **only** for securely - hosted, first-party services. +- **Authorization code with [Proof Key for Code Exchange (PKCE)](https://tools.ietf.org/html/rfc7636):** + Most secure. Without PKCE, you'd have to include client secrets on mobile clients, + and is recommended for both client and server aoos. +- **Authorization code:** Secure and common flow. Recommended option for secure + server-side apps. +- **Implicit grant:** Originally designed for user-agent only apps, such as + single page web apps running on GitLab Pages). + The [IETF](https://tools.ietf.org/html/draft-ietf-oauth-security-topics-09#section-2.1.2) + recommends against Implicit grant flow. +- **Resource owner password credentials:** To be used **only** for securely + hosted, first-party services. GitLab recommends against use of this flow. + +The draft specification for [OAuth 2.1](https://oauth.net/2.1/) specifically omits both the +Implicit grant and Resource Owner Password Credentials flows. + it will be deprecated in the next OAuth specification version. Refer to the [OAuth RFC](https://tools.ietf.org/html/rfc6749) to find out how all those flows work and pick the right one for your use case. -Both **web application** and **implicit grant** flows require `application` to be +Both **authorization code** (with or without PKCE) and **implicit grant** flows require `application` to be registered first via the `/profile/applications` page in your user's account. During registration, by enabling proper scopes, you can limit the range of resources which the `application` can access. Upon creation, you'll obtain the @@ -57,19 +66,84 @@ These factors are particularly important when using the In the following sections you will find detailed instructions on how to obtain authorization with each flow. -### Web application flow +### Authorization code with Proof Key for Code Exchange (PKCE) + +The [PKCE RFC](https://tools.ietf.org/html/rfc7636#section-1.1) includes a +detailed flow description, from authorization request through access token. +The following steps describe our implementation of the flow. + +The Authorization code with PKCE flow, PKCE for short, makes it possible to securely perform +the OAuth exchange of client credentials for access tokens on public clients. + +Before starting the flow, generate the `STATE`, the `CODE_VERIFIER` and the `CODE_CHALLENGE`. + +- The `STATE` a value that can't be predicted used by the client to maintain + state between the request and callback. It should also be used as a CSRF token. +- The `CODE_VERIFIER` is a random string, between 43 and 128 characters in length, + which use the characters `A-Z`, `a-z`, `0-9`, `-`, `.`, `_`, and `~`. +- The `CODE_CHALLENGE` is an URL-safe base64-encoded string of the SHA256 hash of the + `CODE_VERIFIER` + - In Ruby, you can set that up with `Base64.urlsafe_encode64(Digest::SHA256.digest(CODE_VERIFIER))`. + +1. Request authorization code. To do that, you should redirect the user to the + `/oauth/authorize` page with the following query parameters: + + ```plaintext + https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=YOUR_UNIQUE_STATE_HASH&scope=REQUESTED_SCOPES&code_challenge=CODE_CHALLENGE&code_challenge_method=S256 + ``` + + This page asks the user to approve the request from the app to access their + account based on the scopes specified in `REQUESTED_SCOPES`. The user is then + redirected back to the specified `REDIRECT_URI`. The [scope parameter](https://github.com/doorkeeper-gem/doorkeeper/wiki/Using-Scopes#requesting-particular-scopes) + is a space separated list of scopes associated with the user. + For example,`scope=read_user+profile` requests the `read_user` and `profile` scopes. + The redirect includes the authorization `code`, for example: + + ```plaintext + https://example.com/oauth/redirect?code=1234567890&state=YOUR_UNIQUE_STATE_HASH + ``` + +1. With the authorization `code` returned from the previous request (denoted as + `RETURNED_CODE` in the following example), you can request an `access_token`, with + any HTTP client. The following example uses Ruby's `rest-client`: + + ```ruby + parameters = 'client_id=APP_ID&client_secret=APP_SECRET&code=RETURNED_CODE&grant_type=authorization_code&redirect_uri=REDIRECT_URI&code_verifier=CODE_VERIFIER' + RestClient.post 'https://gitlab.example.com/oauth/token', parameters + ``` + + Example response: + + ```json + { + "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54", + "token_type": "bearer", + "expires_in": 7200, + "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1", + "created_at": 1607635748 + } + ``` + +NOTE: +The `redirect_uri` must match the `redirect_uri` used in the original +authorization request. + +You can now make requests to the API with the access token. + +### Authorization code flow NOTE: Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.1) for a detailed flow description. -The web application flow is: +The authorization code flow is essentially the same as +[authorization code flow with PKCE](#authorization-code-with-proof-key-for-code-exchange-pkce), 1. Request authorization code. To do that, you should redirect the user to the `/oauth/authorize` endpoint with the following GET parameters: ```plaintext - https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=YOUR_UNIQUE_STATE_HASH&scope=REQUESTED_SCOPES + https://gitlab.example.com/oauth/authorize?client_id=APP_ID&redirect_uri=REDIRECT_URI&response_type=code&state=STATE&scope=REQUESTED_SCOPES ``` This will ask the user to approve the applications access to their account @@ -80,12 +154,12 @@ The web application flow is: include the GET `code` parameter, for example: ```plaintext - https://example.com/oauth/redirect?code=1234567890&state=YOUR_UNIQUE_STATE_HASH + https://example.com/oauth/redirect?code=1234567890&state=STATE ``` You should then use `code` to request an access token. -1. Once you have the authorization code you can request an `access_token` using the +1. After you have the authorization code you can request an `access_token` using the code. You can do that by using any HTTP client. In the following example, we are using Ruby's `rest-client`: @@ -101,7 +175,8 @@ The web application flow is: "access_token": "de6780bc506a0446309bd9362820ba8aed28aa506c71eedbe1c5c4f9dd350e54", "token_type": "bearer", "expires_in": 7200, - "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1" + "refresh_token": "8257e65c97202ed1726cf9571600918f3bffb2544b26e00a61df9897668c33a1", + "created_at": 1607635748 } ``` @@ -114,19 +189,20 @@ You can now make requests to the API with the access token returned. ### Implicit grant flow NOTE: -Check the [RFC spec](https://tools.ietf.org/html/rfc6749#section-4.2) for a -detailed flow description. +For a detailed flow diagram, see the [RFC specification](https://tools.ietf.org/html/rfc6749#section-4.2). WARNING: -Avoid using this flow for applications that store data outside of the GitLab -instance. If you do, make sure to verify `application id` associated with the -access token before granting access to the data -(see [`/oauth/token/info`](#retrieving-the-token-information)). - -Unlike the web flow, the client receives an `access token` immediately as a -result of the authorization request. The flow does not use the client secret -or the authorization code because all of the application code and storage is -easily accessible, therefore secrets can leak easily. +The Implicit grant flow is inherently insecure. The IETF plans to remove it in +[OAuth 2.1](https://oauth.net/2.1/). + +We recommend that you use [Authorization code with PKCE](#authorization-code-with-proof-key-for-code-exchange-pkce) instead. If you choose to use Implicit flow, be sure to verify the +`application id` (or `client_id`) associated with the access token before granting +access to the data, as described in [Retrieving the token information](#retrieving-the-token-information)). + +Unlike the authorization code flow, the client receives an `access token` +immediately as a result of the authorization request. The flow does not use +the client secret or the authorization code because all of the application code +and storage is easily accessible on client browsers and mobile devices. To request the access token, you should redirect the user to the `/oauth/authorize` endpoint using `token` response type: diff --git a/doc/api/openapi/openapi.yaml b/doc/api/openapi/openapi.yaml index 8c46804d86f..1a80daf304c 100644 --- a/doc/api/openapi/openapi.yaml +++ b/doc/api/openapi/openapi.yaml @@ -1,8 +1,13 @@ -openapi: "3.0.0" +openapi: 3.0.0 +tags: + - name: version + description: Version + - name: access_requests + description: Access requests for projects and groups info: description: | An OpenAPI definition for the GitLab REST API. - Only one API resource/endpoint is currently included. + Few API resources or endpoints are currently included. The intent is to expand this to match the entire Markdown documentation of the API: <https://docs.gitlab.com/ee/api/>. Contributions are welcome. @@ -12,15 +17,46 @@ info: so each request is made using your account. Read more at <https://docs.gitlab.com/ee/development/documentation/restful_api_styleguide.html>. - version: "v4" - title: "GitLab API" - termsOfService: "https://about.gitlab.com/terms/" + version: v4 + title: GitLab API + termsOfService: 'https://about.gitlab.com/terms/' license: - name: "CC BY-SA 4.0" - url: "https://gitlab.com/gitlab-org/gitlab/-/blob/master/LICENSE" + name: CC BY-SA 4.0 + url: 'https://gitlab.com/gitlab-org/gitlab/-/blob/master/LICENSE' servers: - - url: "https://gitlab.com/api/" + - url: 'https://gitlab.com/api/' +security: + - ApiKeyAuth: [] + +components: + securitySchemes: + ApiKeyAuth: + type: apiKey + in: header + name: Private-Token paths: + # VERSION /v4/version: - $ref: "v4/version.yaml" + $ref: 'v4/version.yaml' + + # ACCESS REQUESTS (PROJECTS) + /v4/projects/{id}/access_requests: + $ref: 'v4/access_requests.yaml#/accessRequestsProjects' + + /v4/projects/{id}/access_requests/{user_id}/approve: + $ref: 'v4/access_requests.yaml#/accessRequestsProjectsApprove' + + /v4/projects/{id}/access_requests/{user_id}: + $ref: 'v4/access_requests.yaml#/accessRequestsProjectsDeny' + + # ACCESS REQUESTS (GROUPS) + /v4/groups/{id}/access_requests: + $ref: 'v4/access_requests.yaml#/accessRequestsGroups' + + /v4/groups/{id}/access_requests/{user_id}/approve: + $ref: 'v4/access_requests.yaml#/accessRequestsGroupsApprove' + + /v4/groupss/{id}/access_requests/{user_id}: + $ref: 'v4/access_requests.yaml#/accessRequestsGroupsDeny' + diff --git a/doc/api/openapi/v4/access_requests.yaml b/doc/api/openapi/v4/access_requests.yaml new file mode 100644 index 00000000000..157a0973e1e --- /dev/null +++ b/doc/api/openapi/v4/access_requests.yaml @@ -0,0 +1,381 @@ +# Markdown documentation: https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/api/access_requests.md + +#/v4/projects/{id}/access_requests +accessRequestsProjects: + get: + description: Lists access requests for a project + summary: List access requests for a project + operationId: accessRequestsProjects_get + tags: + - access_requests + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated user. + required: true + schema: + oneOf: + - type: integer + - type: string + responses: + '401': + description: Unauthorized operation + '200': + description: Successful operation + content: + application/json: + schema: + title: ProjectAccessResponse + type: object + properties: + id: + type: integer + usename: + type: string + name: + type: string + state: + type: string + created_at: + type: string + requested_at: + type: string + example: + - "id": 1 + "username": "raymond_smith" + "name": "Raymond Smith" + "state": "active" + "created_at": "2012-10-22T14:13:35Z" + "requested_at": "2012-10-22T14:13:35Z" + - "id": 2 + "username": "john_doe" + "name": "John Doe" + "state": "active" + "created_at": "2012-10-22T14:13:35Z" + "requested_at": "2012-10-22T14:13:35Z" + post: + description: Requests access for the authenticated user to a project + summary: Requests access for the authenticated user to a project + operationId: accessRequestsProjects_post + tags: + - access_requests + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated user. + required: true + schema: + oneOf: + - type: integer + - type: string + responses: + '401': + description: Unauthorized operation + '200': + description: Successful operation + content: + application/json: + schema: + title: ProjectAccessRequest + type: object + properties: + id: + type: integer + usename: + type: string + name: + type: string + state: + type: string + created_at: + type: string + requested_at: + type: string + example: + "id": 1 + "username": "raymond_smith" + "name": "Raymond Smith" + "state": "active" + "created_at": "2012-10-22T14:13:35Z" + "requested_at": "2012-10-22T14:13:35Z" + +#/v4/projects/{id}/access_requests/{user_id}/approve +accessRequestsProjectsApprove: + put: + description: Approves access for the authenticated user to a project + summary: Approves access for the authenticated user to a project + operationId: accessRequestsProjectsApprove_put + tags: + - access_requests + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated user. + required: true + schema: + oneOf: + - type: integer + - type: string + - name: user_id + in: path + description: The userID of the access requester + required: true + schema: + type: integer + - name: access_level + in: query + description: A valid project access level. 0 = no access , 10 = guest, 20 = reporter, 30 = developer, 40 = Maintainer. Default is 30.' + required: false + schema: + enum: [0, 10, 20, 30, 40] + default: 30 + type: integer + responses: + '401': + description: Unauthorized operation + '200': + description: Successful operation + content: + application/json: + schema: + title: ProjectAccessApprove + type: object + properties: + id: + type: integer + usename: + type: string + name: + type: string + state: + type: string + created_at: + type: string + access_level: + type: integer + example: + "id": 1 + "username": "raymond_smith" + "name": "Raymond Smith" + "state": "active" + "created_at": "2012-10-22T14:13:35Z" + "access_level": 20 + +#/v4/projects/{id}/access_requests/{user_id} +accessRequestsProjectsDeny: + delete: + description: Denies a project access request for the given user + summary: Denies a project access request for the given user + operationId: accessRequestProjectsDeny_delete + tags: + - access_requests + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the project owned by the authenticated user. + required: true + schema: + oneOf: + - type: integer + - type: string + - name: user_id + in: path + description: The user ID of the access requester + required: true + schema: + type: integer + responses: # Does anything go here? Markdown doc does not list a response. + '401': + description: Unauthorized operation + '200': + description: Successful operation + +#/v4/groups/{id}/access_requests +accessRequestsGroups: + get: + description: List access requests for a group + summary: List access requests for a group + operationId: accessRequestsGroups_get + tags: + - access_requests + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated user. + required: true + schema: + oneOf: + - type: integer + - type: string + responses: + '401': + description: Unauthorized operation + '200': + description: Successful operation + content: + application/json: + schema: + title: GroupAccessResponse + type: object + properties: + id: + type: integer + usename: + type: string + name: + type: string + state: + type: string + created_at: + type: string + requested_at: + type: string + example: + - "id": 1 + "username": "raymond_smith" + "name": "Raymond Smith" + "state": "active" + "created_at": "2012-10-22T14:13:35Z" + "requested_at": "2012-10-22T14:13:35Z" + - "id": 2 + "username": "john_doe" + "name": "John Doe" + "state": "active" + "created_at": "2012-10-22T14:13:35Z" + "requested_at": "2012-10-22T14:13:35Z" + post: + description: Requests access for the authenticated user to a group + summary: Requests access for the authenticated user to a group + operationId: accessRequestsGroups_post + tags: + - access_requests + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated user. + required: true + schema: + oneOf: + - type: integer + - type: string + responses: + '401': + description: Unauthorized operation + '200': + description: Successful operation + content: + application/json: + schema: + title: GroupAccessRequest + type: object + properties: + id: + type: integer + usename: + type: string + name: + type: string + state: + type: string + created_at: + type: string + requested_at: + type: string + example: + "id": 1 + "username": "raymond_smith" + "name": "Raymond Smith" + "state": "active" + "created_at": "2012-10-22T14:13:35Z" + "requested_at": "2012-10-22T14:13:35Z" + +#/v4/groups/{id}/access_requests/{user_id}/approve +accessRequestsGroupsApprove: + put: + description: Approves access for the authenticated user to a group + summary: Approves access for the authenticated user to a group + operationId: accessRequestsGroupsApprove_put + tags: + - access_requests + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated user. + required: true + schema: + oneOf: + - type: integer + - type: string + - name: user_id + in: path + description: The userID of the access requester + required: true + schema: + type: integer + - name: access_level + in: query + description: A valid group access level. 0 = no access , 10 = Guest, 20 = Reporter, 30 = Developer, 40 = Maintainer, 50 = Owner. Default is 30. + required: false + schema: + enum: [0, 10, 20, 30, 40, 50] + default: 30 + type: integer + responses: + '401': + description: Unauthorized operation + '200': + description: Successful operation + content: + application/json: + schema: + title: GroupAccessApprove + type: object + properties: + id: + type: integer + usename: + type: string + name: + type: string + state: + type: string + created_at: + type: string + access_level: + type: integer + example: + "id": 1 + "username": "raymond_smith" + "name": "Raymond Smith" + "state": "active" + "created_at": "2012-10-22T14:13:35Z" + "access_level": 20 + +#/v4/groups/{id}/access_requests/{user_id} +accessRequestsGroupsDeny: + delete: + description: Denies a group access request for the given user + summary: Denies a group access request for the given user + operationId: accessRequestsGroupsDeny_delete + tags: + - access_requests + parameters: + - name: id + in: path + description: The ID or URL-encoded path of the group owned by the authenticated user. + required: true + schema: + oneOf: + - type: integer + - type: string + - name: user_id + in: path + description: The userID of the access requester + required: true + schema: + type: integer + responses: # Does anything go here? Markdown doc does not list a response. + '401': + description: Unauthorized operation + '200': + description: Successful operation diff --git a/doc/api/packages.md b/doc/api/packages.md index a52487e35a3..a0d966fdd88 100644 --- a/doc/api/packages.md +++ b/doc/api/packages.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Packages API -This is the API docs of [GitLab Packages](../administration/packages/index.md). +This is the API documentation of [GitLab Packages](../administration/packages/index.md). ## List packages @@ -28,6 +28,7 @@ GET /projects/:id/packages | `sort` | string | no | The direction of the order, either `asc` (default) for ascending order or `desc` for descending order. | | `package_type` | string | no | Filter the returned packages by type. One of `conan`, `maven`, `npm`, `pypi`, `composer`, `nuget`, or `golang`. (_Introduced in GitLab 12.9_) | `package_name` | string | no | Filter the project packages with a fuzzy search by name. (_Introduced in GitLab 12.9_) +| `include_versionless` | boolean | no | When set to true, versionless packages are included in the response. (_Introduced in GitLab 13.8_) ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/:id/packages" @@ -67,7 +68,7 @@ Example response: ] ``` -By default, the `GET` request returns 20 results, since the API is [paginated](README.md#pagination). +By default, the `GET` request returns 20 results, because the API is [paginated](README.md#pagination). ### Within a group @@ -88,6 +89,7 @@ GET /groups/:id/packages | `sort` | string | no | The direction of the order, either `asc` (default) for ascending order or `desc` for descending order. | | `package_type` | string | no | Filter the returned packages by type. One of `conan`, `maven`, `npm`, `pypi`, `composer`, `nuget`, or `golang`. (_Introduced in GitLab 12.9_) | | `package_name` | string | no | Filter the project packages with a fuzzy search by name. (_[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30980) in GitLab 13.0_) +| `include_versionless` | boolean | no | When set to true, versionless packages are included in the response. (_Introduced in GitLab 13.8_) ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/groups/:id/packages?exclude_subgroups=true" @@ -157,7 +159,7 @@ Example response: ] ``` -By default, the `GET` request returns 20 results, since the API is [paginated](README.md#pagination). +By default, the `GET` request returns 20 results, because the API is [paginated](README.md#pagination). The `_links` object contains the following properties: @@ -314,7 +316,7 @@ Example response: ] ``` -By default, the `GET` request returns 20 results, since the API is [paginated](README.md#pagination). +By default, the `GET` request returns 20 results, because the API is [paginated](README.md#pagination). ## Delete a project package diff --git a/doc/api/personal_access_tokens.md b/doc/api/personal_access_tokens.md index b3e007308ba..ca0ac3522c3 100644 --- a/doc/api/personal_access_tokens.md +++ b/doc/api/personal_access_tokens.md @@ -70,7 +70,8 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/a ## Revoke a personal access token -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216004) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216004) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.3. +> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/270200) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.6. Revoke a personal access token. @@ -96,4 +97,4 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git ## Create a personal access token (admin only) -See the [Users API documentation](users.md#create-a-personal-access-token-admin-only) for information on creating a personal access token. +See the [Users API documentation](users.md#create-a-personal-access-token) for information on creating a personal access token. diff --git a/doc/api/project_import_export.md b/doc/api/project_import_export.md index c5799a63c5c..0711cc8abd6 100644 --- a/doc/api/project_import_export.md +++ b/doc/api/project_import_export.md @@ -193,7 +193,7 @@ requests.post(url, headers=headers, data=data, files=files) ``` NOTE: -The maximum import file size can be set by the Administrator, default is 50MB. +The maximum import file size can be set by the Administrator, default is `0` (unlimited).. As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](settings.md#change-application-settings) or the [Admin UI](../user/admin_area/settings/account_and_limit_settings.md). ## Import status diff --git a/doc/api/project_level_variables.md b/doc/api/project_level_variables.md index 8f6b9b83ca3..413d89950cd 100644 --- a/doc/api/project_level_variables.md +++ b/doc/api/project_level_variables.md @@ -80,9 +80,9 @@ POST /projects/:id/variables | `key` | string | yes | The `key` of a variable; must have no more than 255 characters; only `A-Z`, `a-z`, `0-9`, and `_` are allowed | | `value` | string | yes | The `value` of a variable | | `variable_type` | string | no | The type of a variable. Available types are: `env_var` (default) and `file` | -| `protected` | boolean | no | Whether the variable is protected | -| `masked` | boolean | no | Whether the variable is masked | -| `environment_scope` | string | no | The `environment_scope` of the variable | +| `protected` | boolean | no | Whether the variable is protected. Default: `false` | +| `masked` | boolean | no | Whether the variable is masked. Default: `false` | +| `environment_scope` | string | no | The `environment_scope` of the variable. Default: `*` | ```shell curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/1/variables" --form "key=NEW_VARIABLE" --form "value=new value" diff --git a/doc/api/project_repository_storage_moves.md b/doc/api/project_repository_storage_moves.md index 07743a48654..52c357ca32a 100644 --- a/doc/api/project_repository_storage_moves.md +++ b/doc/api/project_repository_storage_moves.md @@ -30,9 +30,10 @@ read-only. Please try again later.` message if they try to push new commits. This API requires you to [authenticate yourself](README.md#authentication) as an administrator. +Snippet repositories can be moved using the [Snippet repository storage moves API](snippet_repository_storage_moves.md). + ## Limitations -- The repositories associated with snippets [can't be moved with the API](https://gitlab.com/groups/gitlab-org/-/epics/3393). - Group-level wikis [can't be moved with the API](https://gitlab.com/gitlab-org/gitlab/-/issues/219003). ## Retrieve all project repository storage moves diff --git a/doc/api/projects.md b/doc/api/projects.md index b9f6448085d..f9a4b3ba55e 100644 --- a/doc/api/projects.md +++ b/doc/api/projects.md @@ -160,6 +160,7 @@ When the user is authenticated and `simple` is not set this returns something li "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, + "restrict_user_defined_variables": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, @@ -253,6 +254,7 @@ When the user is authenticated and `simple` is not set this returns something li "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, + "restrict_user_defined_variables": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, @@ -297,7 +299,7 @@ When the user is authenticated and `simple` is not set this returns something li NOTE: For users of GitLab [Silver, Premium, or higher](https://about.gitlab.com/pricing/), -the `marked_for_deletion_at` attribute has been deprecated, and will be removed +the `marked_for_deletion_at` attribute has been deprecated, and is removed in API v5 in favor of the `marked_for_deletion_on` attribute. Users of GitLab [Starter, Bronze, or higher](https://about.gitlab.com/pricing/) @@ -418,6 +420,7 @@ GET /users/:user_id/projects "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, + "restrict_user_defined_variables": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, @@ -511,6 +514,7 @@ GET /users/:user_id/projects "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, + "restrict_user_defined_variables": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, @@ -640,6 +644,7 @@ Example response: "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, + "restrict_user_defined_variables": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, @@ -726,6 +731,7 @@ Example response: "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, + "restrict_user_defined_variables": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, @@ -881,6 +887,7 @@ GET /projects/:id "repository_storage": "default", "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, + "restrict_user_defined_variables": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "printing_merge_requests_link_enabled": true, @@ -1057,7 +1064,7 @@ POST /projects | `build_timeout` | integer | **{dotted-circle}** No | The maximum amount of time in minutes that a job is able run (in seconds). | | `builds_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, or `enabled`. | | `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. | -| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (string), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). | +| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (integer), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). | | `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. | | `default_branch` | string | **{dotted-circle}** No | `master` by default. | | `description` | string | **{dotted-circle}** No | Short project description. | @@ -1206,7 +1213,7 @@ PUT /projects/:id | `ci_config_path` | string | **{dotted-circle}** No | The path to CI configuration file. | | `ci_default_git_depth` | integer | **{dotted-circle}** No | Default number of revisions for [shallow cloning](../ci/pipelines/settings.md#git-shallow-clone). | | `ci_forward_deployment_enabled` | boolean | **{dotted-circle}** No | When a new deployment job starts, [skip older deployment jobs](../ci/pipelines/settings.md#skip-outdated-deployment-jobs) that are still pending | -| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (string), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). | +| `container_expiration_policy_attributes` | hash | **{dotted-circle}** No | Update the image cleanup policy for this project. Accepts: `cadence` (string), `keep_n` (integer), `older_than` (string), `name_regex` (string), `name_regex_delete` (string), `name_regex_keep` (string), `enabled` (boolean). | | `container_registry_enabled` | boolean | **{dotted-circle}** No | Enable container registry for this project. | | `default_branch` | string | **{dotted-circle}** No | `master` by default. | | `description` | string | **{dotted-circle}** No | Short project description. | @@ -1234,6 +1241,7 @@ PUT /projects/:id | `packages_enabled` | boolean | **{dotted-circle}** No | Enable or disable packages repository feature. | | `pages_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled`, or `public`. | | `requirements_access_level` | string | **{dotted-circle}** No | One of `disabled`, `private`, `enabled` or `public` | +| `restrict_user_defined_variables` | boolean | **{dotted-circle}** No | Allow only maintainers to pass user-defined variables when triggering a pipeline. For example when the pipeline is triggered in the UI, with the API, or by a trigger token. | | `path` | string | **{dotted-circle}** No | Custom repository name for the project. By default generated based on name. | | `public_builds` | boolean | **{dotted-circle}** No | If `true`, jobs can be viewed by non-project members. | | `remove_source_branch_after_merge` | boolean | **{dotted-circle}** No | Enable `Delete source branch` option by default for all new merge requests. | @@ -1356,6 +1364,7 @@ Example responses: "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, + "restrict_user_defined_variables": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, @@ -1449,6 +1458,7 @@ Example response: "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, + "restrict_user_defined_variables": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, @@ -1540,6 +1550,7 @@ Example response: "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, + "restrict_user_defined_variables": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, @@ -1725,6 +1736,7 @@ Example response: "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, + "restrict_user_defined_variables": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, @@ -1837,6 +1849,7 @@ Example response: "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": false, + "restrict_user_defined_variables": false, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": false, "request_access_enabled": false, @@ -2184,7 +2197,7 @@ POST /projects/:id/housekeeping ## Push Rules **(STARTER)** -### Get project push rules +### Get project push rules **(STARTER)** Get the [push rules](../push_rules/push_rules.md#enabling-push-rules) of a project. @@ -2230,7 +2243,7 @@ parameters: } ``` -### Add project push rule +### Add project push rule **(STARTER)** Adds a push rule to a specified project. @@ -2238,22 +2251,22 @@ Adds a push rule to a specified project. POST /projects/:id/push_rule ``` -| Attribute | Type | Required | Description | -|-----------------------------------------------|----------------|------------------------|-------------| -| `author_email_regex` **(STARTER)** | string | **{dotted-circle}** No | All commit author emails must match this, for example `@my-company.com$`. | -| `branch_name_regex` **(STARTER)** | string | **{dotted-circle}** No | All branch names must match this, for example `(feature|hotfix)\/*`. | -| `commit_committer_check` **(PREMIUM)** | boolean | **{dotted-circle}** No | Users can only push commits to this repository that were committed with one of their own verified emails. | -| `commit_message_negative_regex` **(STARTER)** | string | **{dotted-circle}** No | No commit message is allowed to match this, for example `ssh\:\/\/`. | -| `commit_message_regex` **(STARTER)** | string | **{dotted-circle}** No | All commit messages must match this, for example `Fixed \d+\..*`. | -| `deny_delete_tag` **(STARTER)** | boolean | **{dotted-circle}** No | Deny deleting a tag. | -| `file_name_regex` **(STARTER)** | string | **{dotted-circle}** No | All committed filenames must **not** match this, for example `(jar|exe)$`. | -| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. | -| `max_file_size` **(STARTER)** | integer | **{dotted-circle}** No | Maximum file size (MB). | -| `member_check` **(STARTER)** | boolean | **{dotted-circle}** No | Restrict commits by author (email) to existing GitLab users. | -| `prevent_secrets` **(STARTER)** | boolean | **{dotted-circle}** No | GitLab will reject any files that are likely to contain secrets. | -| `reject_unsigned_commits` **(PREMIUM)** | boolean | **{dotted-circle}** No | Reject commit when it's not signed through GPG. | +| Attribute | Type | Required | Description | +|-----------------------------------------|----------------|------------------------|-------------| +| `author_email_regex` | string | **{dotted-circle}** No | All commit author emails must match this, for example `@my-company.com$`. | +| `branch_name_regex` | string | **{dotted-circle}** No | All branch names must match this, for example `(feature|hotfix)\/*`. | +| `commit_committer_check` **(PREMIUM)** | boolean | **{dotted-circle}** No | Users can only push commits to this repository that were committed with one of their own verified emails. | +| `commit_message_negative_regex` | string | **{dotted-circle}** No | No commit message is allowed to match this, for example `ssh\:\/\/`. | +| `commit_message_regex` | string | **{dotted-circle}** No | All commit messages must match this, for example `Fixed \d+\..*`. | +| `deny_delete_tag` | boolean | **{dotted-circle}** No | Deny deleting a tag. | +| `file_name_regex` | string | **{dotted-circle}** No | All committed filenames must **not** match this, for example `(jar|exe)$`. | +| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. | +| `max_file_size` | integer | **{dotted-circle}** No | Maximum file size (MB). | +| `member_check` | boolean | **{dotted-circle}** No | Restrict commits by author (email) to existing GitLab users. | +| `prevent_secrets` | boolean | **{dotted-circle}** No | GitLab rejects any files that are likely to contain secrets. | +| `reject_unsigned_commits` **(PREMIUM)** | boolean | **{dotted-circle}** No | Reject commit when it's not signed through GPG. | -### Edit project push rule +### Edit project push rule **(STARTER)** Edits a push rule for a specified project. @@ -2261,20 +2274,20 @@ Edits a push rule for a specified project. PUT /projects/:id/push_rule ``` -| Attribute | Type | Required | Description | -|-----------------------------------------------|----------------|------------------------|-------------| -| `author_email_regex` **(STARTER)** | string | **{dotted-circle}** No | All commit author emails must match this, for example `@my-company.com$`. | -| `branch_name_regex` **(STARTER)** | string | **{dotted-circle}** No | All branch names must match this, for example `(feature|hotfix)\/*`. | -| `commit_committer_check` **(PREMIUM)** | boolean | **{dotted-circle}** No | Users can only push commits to this repository that were committed with one of their own verified emails. | -| `commit_message_negative_regex` **(STARTER)** | string | **{dotted-circle}** No | No commit message is allowed to match this, for example `ssh\:\/\/`. | -| `commit_message_regex` **(STARTER)** | string | **{dotted-circle}** No | All commit messages must match this, for example `Fixed \d+\..*`. | -| `deny_delete_tag` **(STARTER)** | boolean | **{dotted-circle}** No | Deny deleting a tag. | -| `file_name_regex` **(STARTER)** | string | **{dotted-circle}** No | All committed filenames must **not** match this, for example `(jar|exe)$`. | -| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. | -| `max_file_size` **(STARTER)** | integer | **{dotted-circle}** No | Maximum file size (MB). | -| `member_check` **(STARTER)** | boolean | **{dotted-circle}** No | Restrict commits by author (email) to existing GitLab users. | -| `prevent_secrets` **(STARTER)** | boolean | **{dotted-circle}** No | GitLab will reject any files that are likely to contain secrets. | -| `reject_unsigned_commits` **(PREMIUM)** | boolean | **{dotted-circle}** No | Reject commits when they are not GPG signed. | +| Attribute | Type | Required | Description | +|-----------------------------------------|----------------|------------------------|-------------| +| `author_email_regex` | string | **{dotted-circle}** No | All commit author emails must match this, for example `@my-company.com$`. | +| `branch_name_regex` | string | **{dotted-circle}** No | All branch names must match this, for example `(feature|hotfix)\/*`. | +| `commit_committer_check` **(PREMIUM)** | boolean | **{dotted-circle}** No | Users can only push commits to this repository that were committed with one of their own verified emails. | +| `commit_message_negative_regex` | string | **{dotted-circle}** No | No commit message is allowed to match this, for example `ssh\:\/\/`. | +| `commit_message_regex` | string | **{dotted-circle}** No | All commit messages must match this, for example `Fixed \d+\..*`. | +| `deny_delete_tag` | boolean | **{dotted-circle}** No | Deny deleting a tag. | +| `file_name_regex` | string | **{dotted-circle}** No | All committed filenames must **not** match this, for example `(jar|exe)$`. | +| `id` | integer/string | **{check-circle}** Yes | The ID of the project or NAMESPACE/PROJECT_NAME. | +| `max_file_size` | integer | **{dotted-circle}** No | Maximum file size (MB). | +| `member_check` | boolean | **{dotted-circle}** No | Restrict commits by author (email) to existing GitLab users. | +| `prevent_secrets` | boolean | **{dotted-circle}** No | GitLab rejects any files that are likely to contain secrets. | +| `reject_unsigned_commits` **(PREMIUM)** | boolean | **{dotted-circle}** No | Reject commits when they are not GPG signed. | ### Delete project push rule @@ -2397,6 +2410,7 @@ Example response: "shared_with_groups": [], "only_allow_merge_if_pipeline_succeeds": false, "allow_merge_on_skipped_pipeline": null, + "restrict_user_defined_variables": false, "request_access_enabled": true, "only_allow_merge_if_all_discussions_are_resolved": false, "remove_source_branch_after_merge": true, diff --git a/doc/api/releases/index.md b/doc/api/releases/index.md index 0cb11a2b586..a58d6246a63 100644 --- a/doc/api/releases/index.md +++ b/doc/api/releases/index.md @@ -28,7 +28,7 @@ GET /projects/:id/releases Example request: ```shell -curl --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases" +curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases" ``` Example response: @@ -233,7 +233,7 @@ GET /projects/:id/releases/:tag_name Example request: ```shell -curl --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" +curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" ``` Example response: @@ -360,21 +360,21 @@ POST /projects/:id/releases | -------------------| --------------- | -------- | -------------------------------------------------------------------------------------------------------------------------------- | | `id` | integer/string | yes | The ID or [URL-encoded path of the project](../README.md#namespaced-path-encoding). | | `name` | string | no | The release name. | -| `tag_name` | string | yes | The tag where the release will be created from. | +| `tag_name` | string | yes | The tag where the release is created from. | | `description` | string | no | The description of the release. You can use [Markdown](../../user/markdown.md). | -| `ref` | string | yes, if `tag_name` doesn't exist | If a tag specified in `tag_name` doesn't exist, the release will be created from `ref` and tagged with `tag_name`. It can be a commit SHA, another tag name, or a branch name. | +| `ref` | string | yes, if `tag_name` doesn't exist | If a tag specified in `tag_name` doesn't exist, the release is created from `ref` and tagged with `tag_name`. It can be a commit SHA, another tag name, or a branch name. | | `milestones` | array of string | no | The title of each milestone the release is associated with. [GitLab Premium](https://about.gitlab.com/pricing/) customers can specify group milestones. | | `assets:links` | array of hash | no | An array of assets links. | | `assets:links:name`| string | required by: `assets:links` | The name of the link. Link names must be unique within the release. | | `assets:links:url` | string | required by: `assets:links` | The URL of the link. Link URLs must be unique within the release. | | `assets:links:filepath` | string | no | Optional path for a [Direct Asset link](../../user/project/releases/index.md#permanent-links-to-release-assets). | `assets:links:link_type` | string | no | The type of the link: `other`, `runbook`, `image`, `package`. Defaults to `other`. -| `released_at` | datetime | no | The date when the release will be/was ready. Defaults to the current time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | +| `released_at` | datetime | no | The date when the release is/was ready. Defaults to the current time. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | Example request: ```shell -curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" \ +curl --header 'Content-Type: application/json' --header "PRIVATE-TOKEN: <your_access_token>" \ --data '{ "name": "New release", "tag_name": "v0.3", "description": "Super nice release", "milestones": ["v1.0", "v1.0-rc"], "assets": { "links": [{ "name": "hoge", "url": "https://google.com", "filepath": "/binaries/linux-amd64", "link_type":"other" }] } }' \ --request POST "https://gitlab.example.com/api/v4/projects/24/releases" ``` @@ -493,7 +493,7 @@ Example response: Group milestones associated with the project may be specified in the `milestones` array for [Create a release](#create-a-release) and [Update a release](#update-a-release) API calls. Only milestones associated with the project's group may be specified, and -adding milestones for ancestor groups will raise an error. +adding milestones for ancestor groups raises an error. ## Collect release evidence **(PREMIUM ONLY)** @@ -513,7 +513,7 @@ POST /projects/:id/releases/:tag_name/evidence Example request: ```shell -curl --request POST --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/evidence" +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/evidence" ``` Example response: @@ -537,12 +537,12 @@ PUT /projects/:id/releases/:tag_name | `name` | string | no | The release name. | | `description` | string | no | The description of the release. You can use [Markdown](../../user/markdown.md). | | `milestones` | array of string | no | The title of each milestone to associate with the release. [GitLab Premium](https://about.gitlab.com/pricing/) customers can specify group milestones. To remove all milestones from the release, specify `[]`. | -| `released_at` | datetime | no | The date when the release will be/was ready. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | +| `released_at` | datetime | no | The date when the release is/was ready. Expected in ISO 8601 format (`2019-03-15T08:00:00Z`). | Example request: ```shell -curl --header 'Content-Type: application/json' --request PUT --data '{"name": "new name", "milestones": ["v1.2"]}' --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" +curl --header 'Content-Type: application/json' --request PUT --data '{"name": "new name", "milestones": ["v1.2"]}' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" ``` Example response: @@ -631,7 +631,7 @@ Example response: ## Delete a Release -Delete a Release. Deleting a Release will not delete the associated tag. +Delete a Release. Deleting a Release doesn't delete the associated tag. ```plaintext DELETE /projects/:id/releases/:tag_name @@ -645,7 +645,7 @@ DELETE /projects/:id/releases/:tag_name Example request: ```shell -curl --request DELETE --header "PRIVATE-TOKEN: gDybLx3yrUK_HLp3qPjS" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" +curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1" ``` Example response: @@ -717,6 +717,6 @@ Example response: > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/38105) in GitLab 12.1. -A release with a `released_at` attribute set to a future date will be labeled an **Upcoming Release** in the UI: +A release with a `released_at` attribute set to a future date is labeled an **Upcoming Release** in the UI: ![Upcoming release](img/upcoming_release_v12_1.png) diff --git a/doc/api/releases/links.md b/doc/api/releases/links.md index 88ce3f6ccb4..911aa8bbbd0 100644 --- a/doc/api/releases/links.md +++ b/doc/api/releases/links.md @@ -27,7 +27,7 @@ GET /projects/:id/releases/:tag_name/assets/links Example request: ```shell -curl --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links" +curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links" ``` Example response: @@ -68,7 +68,7 @@ GET /projects/:id/releases/:tag_name/assets/links/:link_id Example request: ```shell -curl --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1" +curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1" ``` Example response: @@ -104,7 +104,7 @@ Example request: ```shell curl --request POST \ - --header "PRIVATE-TOKEN: tkhfG7HgG-LiZd3zfdDC" \ + --header "PRIVATE-TOKEN: <your_access_token>" \ --data name="hellodarwin-amd64" \ --data url="https://gitlab.example.com/mynamespace/hello/-/jobs/688/artifacts/raw/bin/hello-darwin-amd64" \ --data filepath="/bin/hellodarwin-amd64" \ @@ -148,7 +148,7 @@ You have to specify at least one of `name` or `url` Example request: ```shell -curl --request PUT --data name="new name" --data link_type="runbook" --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1" +curl --request PUT --data name="new name" --data link_type="runbook" --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1" ``` Example response: @@ -180,7 +180,7 @@ DELETE /projects/:id/releases/:tag_name/assets/links/:link_id Example request: ```shell -curl --request DELETE --header "PRIVATE-TOKEN: n671WNGecHugsdEDPsyo" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1" +curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/24/releases/v0.1/assets/links/1" ``` Example response: diff --git a/doc/api/scim.md b/doc/api/scim.md index a9622525478..6e67b6fbc2d 100644 --- a/doc/api/scim.md +++ b/doc/api/scim.md @@ -15,7 +15,7 @@ The SCIM API implements the [RFC7644 protocol](https://tools.ietf.org/html/rfc76 To use this API, [Group SSO](../user/group/saml_sso/index.md) must be enabled for the group. This API is only in use where [SCIM for Group SSO](../user/group/saml_sso/scim_setup.md) is enabled. It's a prerequisite to the creation of SCIM identities. -## Get a list of SAML users +## Get a list of SCIM provisioned users This endpoint is used as part of the SCIM syncing mechanism. It only returns a single user based on a unique ID which should match the `extern_uid` of the user. @@ -74,7 +74,7 @@ Example response: } ``` -## Get a single SAML user +## Get a single SCIM provisioned user ```plaintext GET /api/scim/v2/groups/:group_path/Users/:id @@ -115,7 +115,7 @@ Example response: } ``` -## Create a SAML user +## Create a SCIM provisioned user ```plaintext POST /api/scim/v2/groups/:group_path/Users/ @@ -161,7 +161,7 @@ Example response: Returns a `201` status code if successful. -## Update a single SAML user +## Update a single SCIM provisioned user Fields that can be updated are: @@ -193,7 +193,7 @@ curl --verbose --request PATCH "https://gitlab.example.com/api/scim/v2/groups/te Returns an empty response with a `204` status code if successful. -## Remove a single SAML user +## Remove a single SCIM provisioned user Removes the user's SSO identity and group membership. diff --git a/doc/api/search.md b/doc/api/search.md index bfa5eb576dc..584b2cbb837 100644 --- a/doc/api/search.md +++ b/doc/api/search.md @@ -998,7 +998,9 @@ Example response: ] ``` -### Scope: notes +### Scope: notes **(STARTER)** + +This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled. ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/6/search?scope=notes&search=maxime" @@ -1030,7 +1032,9 @@ Example response: ] ``` -### Scope: wiki_blobs +### Scope: wiki_blobs **(STARTER)** + +This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled. Filters are available for this scope: @@ -1074,7 +1078,9 @@ Example response: NOTE: `filename` is deprecated in favor of `path`. Both return the full path of the file inside the repository, but in the future `filename` will be only the filename and not the full path. For details, see [issue 34521](https://gitlab.com/gitlab-org/gitlab/-/issues/34521). -### Scope: commits +### Scope: commits **(STARTER)** + +This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled. ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/projects/6/search?scope=commits&search=bye" @@ -1105,7 +1111,9 @@ Example response: ] ``` -### Scope: blobs +### Scope: blobs **(STARTER)** + +This scope is available only if [Elasticsearch](../integration/elasticsearch.md) is enabled. Filters are available for this scope: diff --git a/doc/api/services.md b/doc/api/services.md index 68485d23557..d00ddb07a05 100644 --- a/doc/api/services.md +++ b/doc/api/services.md @@ -1,6 +1,6 @@ --- -stage: none -group: unassigned +stage: Create +group: Ecosystem info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- @@ -645,7 +645,7 @@ GET /projects/:id/services/github > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/20290) in GitLab 11.2. -Google GSuite team collaboration tool. +Google Workspace team collaboration tool. ### Create/Edit Hangouts Chat service diff --git a/doc/api/settings.md b/doc/api/settings.md index 5680687e87e..264021b3a2d 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -83,7 +83,8 @@ Example response: "raw_blob_request_limit": 300, "wiki_page_max_content_bytes": 52428800, "require_admin_approval_after_user_signup": false, - "personal_access_token_prefix": "GL-" + "personal_access_token_prefix": "GL-", + "rate_limiting_response_text": null } ``` @@ -176,7 +177,8 @@ Example response: "raw_blob_request_limit": 300, "wiki_page_max_content_bytes": 52428800, "require_admin_approval_after_user_signup": false, - "personal_access_token_prefix": "GL-" + "personal_access_token_prefix": "GL-", + "rate_limiting_response_text": null } ``` @@ -298,13 +300,14 @@ listed in the descriptions of the relevant settings. | `housekeeping_incremental_repack_period` | integer | required by: `housekeeping_enabled` | Number of Git pushes after which an incremental `git repack` is run. | | `html_emails_enabled` | boolean | no | Enable HTML emails. | | `import_sources` | array of strings | no | Sources to allow project import from, possible values: `github`, `bitbucket`, `bitbucket_server`, `gitlab`, `fogbugz`, `git`, `gitlab_project`, `gitea`, `manifest`, and `phabricator`. | +| `invisible_captcha_enabled` | boolean | no | Enable Invisible Captcha spam detection during signup. Disabled by default. | | `issues_create_limit` | integer | no | Max number of issue creation requests per minute per user. Disabled by default.| | `local_markdown_version` | integer | no | Increase this value when any cached Markdown should be invalidated. | | `maintenance_mode_message` | string | no | **(PREMIUM)** Message displayed when instance is in maintenance mode | | `maintenance_mode` | boolean | no | **(PREMIUM)** When instance is in maintenance mode, non-admin users can sign in with read-only access and make read-only API requests | | `max_artifacts_size` | integer | no | Maximum artifacts size in MB | | `max_attachment_size` | integer | no | Limit attachment size in MB | -| `max_import_size` | integer | no | Maximum import size in MB. 0 for unlimited. Default = 50 | +| `max_import_size` | integer | no | Maximum import size in MB. 0 for unlimited. Default = 0 (unlimited) | | `max_pages_size` | integer | no | Maximum size of pages repositories in MB | | `max_personal_access_token_lifetime` | integer | no | **(ULTIMATE ONLY)** Maximum allowable lifetime for personal access tokens in days | | `metrics_method_call_threshold` | integer | no | A method call is only tracked when it takes longer than the given amount of milliseconds. | @@ -330,6 +333,7 @@ listed in the descriptions of the relevant settings. | `pseudonymizer_enabled` | boolean | no | **(PREMIUM)** When enabled, GitLab runs a background job that produces pseudonymized CSVs of the GitLab database to upload to your configured object storage directory. | `push_event_activities_limit` | integer | no | Number of changes (branches or tags) in a single push to determine whether individual push events or bulk push events are created. [Bulk push events are created](../user/admin_area/settings/push_event_activities_limit.md) if it surpasses that value. | | `push_event_hooks_limit` | integer | no | Number of changes (branches or tags) in a single push to determine whether webhooks and services fire or not. Webhooks and services aren't submitted if it surpasses that value. | +| `rate_limiting_response_text` | string | no | When rate limiting is enabled via the `throttle_*` settings, send this plain text response when a rate limit is exceeded. 'Retry later' is sent if this is blank. | | `raw_blob_request_limit` | integer | no | Max number of requests per minute for each raw path. Default: 300. To disable throttling set to 0.| | `recaptcha_enabled` | boolean | no | (**If enabled, requires:** `recaptcha_private_key` and `recaptcha_site_key`) Enable reCAPTCHA. | | `recaptcha_private_key` | string | required by: `recaptcha_enabled` | Private key for reCAPTCHA. | diff --git a/doc/api/snippet_repository_storage_moves.md b/doc/api/snippet_repository_storage_moves.md new file mode 100644 index 00000000000..f60b1dfb449 --- /dev/null +++ b/doc/api/snippet_repository_storage_moves.md @@ -0,0 +1,293 @@ +--- +stage: Create +group: Editor +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +type: reference +--- + +# Snippet repository storage moves API **(CORE ONLY)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49228) in GitLab 13.8. + +Snippet repositories can be moved between storages. This can be useful when +[migrating to Gitaly Cluster](../administration/gitaly/praefect.md#migrate-existing-repositories-to-gitaly-cluster), +for example. + +As snippet repository storage moves are processed, they transition through different states. Values +of `state` are: + +- `initial` +- `scheduled` +- `started` +- `finished` +- `failed` +- `replicated` +- `cleanup failed` + +To ensure data integrity, snippets are put in a temporary read-only state for the +duration of the move. During this time, users receive a `The repository is temporarily +read-only. Please try again later.` message if they try to push new commits. + +This API requires you to [authenticate yourself](README.md#authentication) as an administrator. + +Project repositories can be moved using the [Project repository storage moves API](project_repository_storage_moves.md). + +## Limitations + +- Group-level wikis [can't be moved with the API](https://gitlab.com/gitlab-org/gitlab/-/issues/219003). + +## Retrieve all snippet repository storage moves + +```plaintext +GET /snippet_repository_storage_moves +``` + +By default, `GET` requests return 20 results at a time because the API results +are [paginated](README.md#pagination). + +Example request: + +```shell +curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/snippet_repository_storage_moves" +``` + +Example response: + +```json +[ + { + "id": 1, + "created_at": "2020-05-07T04:27:17.234Z", + "state": "scheduled", + "source_storage_name": "default", + "destination_storage_name": "storage2", + "snippet": { + "id": 65, + "title": "Test Snippet", + "description": null, + "visibility": "internal", + "updated_at": "2020-12-01T11:15:50.385Z", + "created_at": "2020-12-01T11:15:50.385Z", + "project_id": null, + "web_url": "https://gitlab.example.com/-/snippets/65", + "raw_url": "https://gitlab.example.com/-/snippets/65/raw", + "ssh_url_to_repo": "ssh://user@gitlab.example.com/snippets/65.git", + "http_url_to_repo": "https://gitlab.example.com/snippets/65.git" + } + } +] +``` + +## Retrieve all repository storage moves for a snippet + +```plaintext +GET /snippets/:snippet_id/repository_storage_moves +``` + +By default, `GET` requests return 20 results at a time because the API results +are [paginated](README.md#pagination). + +Supported attributes: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `snippet_id` | integer | yes | ID of the snippet. | + +Example request: + +```shell +curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/snippets/1/repository_storage_moves" +``` + +Example response: + +```json +[ + { + "id": 1, + "created_at": "2020-05-07T04:27:17.234Z", + "state": "scheduled", + "source_storage_name": "default", + "destination_storage_name": "storage2", + "snippet": { + "id": 65, + "title": "Test Snippet", + "description": null, + "visibility": "internal", + "updated_at": "2020-12-01T11:15:50.385Z", + "created_at": "2020-12-01T11:15:50.385Z", + "project_id": null, + "web_url": "https://gitlab.example.com/-/snippets/65", + "raw_url": "https://gitlab.example.com/-/snippets/65/raw", + "ssh_url_to_repo": "ssh://user@gitlab.example.com/snippets/65.git", + "http_url_to_repo": "https://gitlab.example.com/snippets/65.git" + } + } +] +``` + +## Get a single snippet repository storage move + +```plaintext +GET /snippet_repository_storage_moves/:repository_storage_id +``` + +Supported attributes: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `repository_storage_id` | integer | yes | ID of the snippet repository storage move. | + +Example request: + +```shell +curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/snippet_repository_storage_moves/1" +``` + +Example response: + +```json +{ + "id": 1, + "created_at": "2020-05-07T04:27:17.234Z", + "state": "scheduled", + "source_storage_name": "default", + "destination_storage_name": "storage2", + "snippet": { + "id": 65, + "title": "Test Snippet", + "description": null, + "visibility": "internal", + "updated_at": "2020-12-01T11:15:50.385Z", + "created_at": "2020-12-01T11:15:50.385Z", + "project_id": null, + "web_url": "https://gitlab.example.com/-/snippets/65", + "raw_url": "https://gitlab.example.com/-/snippets/65/raw", + "ssh_url_to_repo": "ssh://user@gitlab.example.com/snippets/65.git", + "http_url_to_repo": "https://gitlab.example.com/snippets/65.git" + } +} +``` + +## Get a single repository storage move for a snippet + +```plaintext +GET /snippets/:snippet_id/repository_storage_moves/:repository_storage_id +``` + +Supported attributes: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `snippet_id` | integer | yes | ID of the snippet. | +| `repository_storage_id` | integer | yes | ID of the snippet repository storage move. | + +Example request: + +```shell +curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/snippets/1/repository_storage_moves/1" +``` + +Example response: + +```json +{ + "id": 1, + "created_at": "2020-05-07T04:27:17.234Z", + "state": "scheduled", + "source_storage_name": "default", + "destination_storage_name": "storage2", + "snippet": { + "id": 65, + "title": "Test Snippet", + "description": null, + "visibility": "internal", + "updated_at": "2020-12-01T11:15:50.385Z", + "created_at": "2020-12-01T11:15:50.385Z", + "project_id": null, + "web_url": "https://gitlab.example.com/-/snippets/65", + "raw_url": "https://gitlab.example.com/-/snippets/65/raw", + "ssh_url_to_repo": "ssh://user@gitlab.example.com/snippets/65.git", + "http_url_to_repo": "https://gitlab.example.com/snippets/65.git" + } +} +``` + +## Schedule a repository storage move for a snippet + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49228) in GitLab 13.8. + +```plaintext +POST /snippets/:snippet_id/repository_storage_moves +``` + +Supported attributes: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `snippet_id` | integer | yes | ID of the snippet. | +| `destination_storage_name` | string | no | Name of the destination storage shard. In [GitLab 13.5 and later](https://gitlab.com/gitlab-org/gitaly/-/issues/3209), the storage is selected automatically if not provided. | + +Example request: + +```shell +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \ +--data '{"destination_storage_name":"storage2"}' "https://gitlab.example.com/api/v4/snippets/1/repository_storage_moves" +``` + +Example response: + +```json +{ + "id": 1, + "created_at": "2020-05-07T04:27:17.234Z", + "state": "scheduled", + "source_storage_name": "default", + "destination_storage_name": "storage2", + "snippet": { + "id": 65, + "title": "Test Snippet", + "description": null, + "visibility": "internal", + "updated_at": "2020-12-01T11:15:50.385Z", + "created_at": "2020-12-01T11:15:50.385Z", + "project_id": null, + "web_url": "https://gitlab.example.com/-/snippets/65", + "raw_url": "https://gitlab.example.com/-/snippets/65/raw", + "ssh_url_to_repo": "ssh://user@gitlab.example.com/snippets/65.git", + "http_url_to_repo": "https://gitlab.example.com/snippets/65.git" + } +} +``` + +## Schedule repository storage moves for all snippets on a storage shard + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49228) in GitLab 13.8. + +Schedules repository storage moves for each snippet repository stored on the source storage shard. + +```plaintext +POST /snippet_repository_storage_moves +``` + +Supported attributes: + +| Attribute | Type | Required | Description | +| --------- | ---- | -------- | ----------- | +| `source_storage_name` | string | yes | Name of the source storage shard. | +| `destination_storage_name` | string | no | Name of the destination storage shard. The storage is selected automatically if not provided. | + +Example request: + +```shell +curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --header "Content-Type: application/json" \ +--data '{"source_storage_name":"default"}' "https://gitlab.example.com/api/v4/snippet_repository_storage_moves" +``` + +Example response: + +```json +{ + "message": "202 Accepted" +} +``` diff --git a/doc/api/users.md b/doc/api/users.md index f73e1829024..ecfd8e26626 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -89,6 +89,7 @@ GET /users | `sort` | string | no | Return users sorted in `asc` or `desc` order. Default is `desc` | | `two_factor` | string | no | Filter users by Two-factor authentication. Filter values are `enabled` or `disabled`. By default it returns all users | | `without_projects` | boolean | no | Filter users without projects. Default is `false` | +| `admins` | boolean | no | Return only admin users. Default is `false` | ```json [ @@ -1480,19 +1481,14 @@ Parameters: | `user_id` | integer | yes | The ID of the user | | `impersonation_token_id` | integer | yes | The ID of the impersonation token | -## Create a personal access token (admin only) +## Create a personal access token **(CORE ONLY)** > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/17176) in GitLab 13.6. -> - It's [deployed behind a feature flag](../user/feature_flags.md), disabled by default. -> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-an-administrators-ability-to-use-the-api-to-create-personal-access-tokens). **(CORE)** +> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/267553) in GitLab 13.8. -WARNING: -This feature might not be available to you. Check the **version history** note above for details. - -> Requires admin permissions. -> Token values are returned once. Make sure you save it - you can't access it again. - -It creates a new personal access token. +Use this API to create a new personal access token. Token values are returned once so, +make sure you save it as you can't access it again. This API can only be used by +GitLab administrators. ```plaintext POST /users/:user_id/personal_access_tokens @@ -1632,22 +1628,3 @@ Example response: }, ] ``` - -## Enable or disable an administrator's ability to use the API to create personal access tokens **(CORE)** - -An administrator's ability to create personal access tokens through the API is -deployed behind a feature flag that is **disabled by default**. -[GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md) -can enable it. - -To enable it: - -```ruby -Feature.enable(:pat_creation_api_for_admin) -``` - -To disable it: - -```ruby -Feature.disable(:pat_creation_api_for_admin) -``` diff --git a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md index 95ffcdd0b39..60ddfe8ce02 100644 --- a/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md +++ b/doc/architecture/blueprints/cloud_native_gitlab_pages/index.md @@ -121,9 +121,9 @@ DRIs: | Role | Who |------------------------------|------------------------| -| Product | Jackie Porter | +| Product | Orit Golowinski | | Leadership | Daniel Croft | -| Engineering | Kamil Trzciński | +| Engineering | Vladimir Shushlin | Domain Experts: diff --git a/doc/architecture/blueprints/feature_flags_development/index.md b/doc/architecture/blueprints/feature_flags_development/index.md index c92b4113465..6be582bb8af 100644 --- a/doc/architecture/blueprints/feature_flags_development/index.md +++ b/doc/architecture/blueprints/feature_flags_development/index.md @@ -119,9 +119,7 @@ This work is being done as part of dedicated epic: [Improve internal usage of Feature Flags](https://gitlab.com/groups/gitlab-org/-/epics/3551). This epic describes a meta reasons for making these changes. -## [Who](#who) - -### Blueprint +## Who Proposal: @@ -142,24 +140,4 @@ DRIs: | Leadership | Craig Gomes | | Engineering | Kamil Trzciński | -### [Stakeholders](#stakeholders) - -| Role | Person | Title -|--------------------|-----------------------|--------------------------------------------------------------------| -| Executive Sponsor | Christopher Lefelhocz | Senior Director of Development | -| Facilitator | Darby Frey | Senior Engineering Manager, Verify | -| DRI / Leadership | Craig Gomes | Backend Engineering Manager, Memory and Database | -| DRI / Engineering | Kamil Trzciński | Distinguished Engineer, Ops and Enablement | -| DRI / Product | Kenny Johnston | Senior Director of Product Management, Ops | -| Functional Lead | Ricky Wiens | Backend Engineering Manager, Verify:Testing | -| Functional Lead | Anthony Sandoval | Engineering Manager, Reliability | -| Functional Lead | James Heimbuck | Senior Product Manager, Verify:Testing | -| Member | Grzegorz Bizon | Staff Backend Engineer, Verify | -| Member | Michelle Gill | Engineering Manager, Create:Source Code | -| Member | Wayne Haber | Director of Engineering, Threat Management | -| Member | Doug Stull | Senior Fullstack Engineer, Growth:Expansion | -| Member | Andrew Fontaine | Senior Frontend Engineer, Release | -| Member | Rémy Coutable | Staff Backend Engineer, Engineering Productivity | -| Member | Marin Jankovski | Senior Engineering Manager, Infrastructure, Delivery & Scalability | - <!-- vale gitlab.Spelling = YES --> diff --git a/doc/ci/README.md b/doc/ci/README.md index 0bd97bcb425..740be7d1dbd 100644 --- a/doc/ci/README.md +++ b/doc/ci/README.md @@ -73,7 +73,7 @@ to your needs: ![Use a `.gitlab-ci.yml` template](img/add_file_template_11_10.png) -While building your `.gitlab-ci.yml`, you can use the [CI/CD configuration visualization](yaml/visualization.md) to facilitate your writing experience. +While building your `.gitlab-ci.yml`, you can use the [CI/CD configuration visualization](pipeline_editor/index.md#visualize-ci-configuration) to facilitate your writing experience. For a broader overview, see the [CI/CD getting started](quick_start/README.md) guide. @@ -141,8 +141,8 @@ Its feature set is listed on the table below according to DevOps stages. | **Release** | | | [Auto Deploy](../topics/autodevops/stages.md#auto-deploy) | Deploy your application to a production environment in a Kubernetes cluster. | | [Building Docker images](docker/using_docker_build.md) | Maintain Docker-based projects using GitLab CI/CD. | -| [Canary Deployments](../user/project/canary_deployments.md) **(PREMIUM)** | Ship features to only a portion of your pods and let a percentage of your user base to visit the temporarily deployed feature. | -| [Deploy Boards](../user/project/deploy_boards.md) **(PREMIUM)** | Check the current health and status of each CI/CD environment running on Kubernetes. | +| [Canary Deployments](../user/project/canary_deployments.md) | Ship features to only a portion of your pods and let a percentage of your user base to visit the temporarily deployed feature. | +| [Deploy Boards](../user/project/deploy_boards.md) | Check the current health and status of each CI/CD environment running on Kubernetes. | | [Feature Flags](../operations/feature_flags.md) **(PREMIUM)** | Deploy your features behind Feature Flags. | | [GitLab Pages](../user/project/pages/index.md) | Deploy static websites. | | [GitLab Releases](../user/project/releases/index.md) | Add release notes to Git tags. | @@ -221,11 +221,3 @@ been necessary. These are: #### 10.0 - No breaking changes. - -#### 9.0 - -- [CI variables renaming for GitLab 9.0](variables/deprecated_variables.md#gitlab-90-renamed-variables). Read about the - deprecated CI variables and what you should use for GitLab 9.0+. -- [New CI job permissions model](../user/project/new_ci_build_permissions_model.md). - See what changed in GitLab 8.12 and how that affects your jobs. - There's a new way to access your Git submodules and LFS objects in jobs. diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md index e8b22a24017..08a45714de3 100644 --- a/doc/ci/caching/index.md +++ b/doc/ci/caching/index.md @@ -316,6 +316,37 @@ rspec: - rspec spec ``` +If you have jobs that each need a different selection of gems, use the `prefix` +keyword in the global `cache` definition. This configuration generates a different +cache for each job. + +For example, a testing job might not need the same gems as a job that deploys to +production: + +```yaml +cache: + key: + files: + - Gemfile.lock + prefix: ${CI_JOB_NAME} + paths: + - vendor/ruby + +test_job: + stage: test + before_script: + - bundle install --without production --path vendor/ruby + script: + - bundle exec rspec + +deploy_job: + stage: production + before_script: + - bundle install --without test --path vendor/ruby + script: + - bundle exec deploy +``` + ### Caching Go dependencies Assuming your project is using [Go Modules](https://github.com/golang/go/wiki/Modules) to install diff --git a/doc/ci/cloud_deployment/index.md b/doc/ci/cloud_deployment/index.md index 4706180688a..0be86527cb5 100644 --- a/doc/ci/cloud_deployment/index.md +++ b/doc/ci/cloud_deployment/index.md @@ -11,10 +11,9 @@ Interacting with a major cloud provider may have become a much needed task that' part of your delivery process. With GitLab you can [deploy your application anywhere](https://about.gitlab.com/stages-devops-lifecycle/deploy-targets/). -For some specific deployment targets, GitLab makes this process less painful by providing Docker images -that come with the needed libraries and tools pre-installed. -By referencing them in your CI/CD pipeline, you'll be able to interact with your chosen -cloud provider more easily. +For some specific deployment targets, GitLab makes this process less painful by providing Docker +images with the needed libraries and tools pre-installed. By referencing them in your +CI/CD pipeline, you can interact with your chosen cloud provider more easily. ## AWS @@ -36,7 +35,7 @@ Some credentials are required to be able to run `aws` commands: 1. Select your newly created user to access its details. Navigate to **Security credentials > Create a new access key**. NOTE: - A new **Access key ID** and **Secret access key** pair will be generated. Please take a note of them right away. + A new **Access key ID** and **Secret access key** are generated. Please take a note of them right away. 1. In your GitLab project, go to **Settings > CI / CD**. Set the following as [environment variables](../variables/README.md#gitlab-cicd-environment-variables) @@ -170,14 +169,14 @@ After you have these prerequisites ready, follow these steps: 1. Commit and push your updated `.gitlab-ci.yml` to your project's repository, and you're done! - Your application Docker image will be rebuilt and pushed to the GitLab registry. + Your application Docker image is rebuilt and pushed to the GitLab registry. If your image is located in a private registry, make sure your task definition is [configured with a `repositoryCredentials` attribute](https://docs.aws.amazon.com/AmazonECS/latest/developerguide/private-auth.html). - Then the targeted task definition will be updated with the location of the new - Docker image, and a new revision will be created in ECS as result. + Then the targeted task definition is updated with the location of the new + Docker image, and a new revision is created in ECS as result. - Finally, your AWS ECS service will be updated with the new revision of the + Finally, your AWS ECS service is updated with the new revision of the task definition, making the cluster pull the newest version of your application. @@ -190,7 +189,7 @@ and [`Jobs/Deploy/ECS.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/-/blo used along with the main template. They may move or change unexpectedly causing your pipeline to fail if you didn't include the main template. Also, the job names within these templates may change. Do not override these jobs names in your own pipeline, -as the override will stop working when the name changes. +as the override stops working when the name changes. Alternatively, if you don't wish to use the `AWS/Deploy-ECS.gitlab-ci.yml` template to deploy to AWS ECS, you can always use our diff --git a/doc/ci/docker/using_docker_build.md b/doc/ci/docker/using_docker_build.md index 8e5ce2fb359..af88a006156 100644 --- a/doc/ci/docker/using_docker_build.md +++ b/doc/ci/docker/using_docker_build.md @@ -7,17 +7,17 @@ type: concepts, howto # Building Docker images with GitLab CI/CD -GitLab CI/CD allows you to use Docker Engine to build and test Docker-based projects. +You can use GitLab CI/CD with Docker Engine to build and test Docker-based projects. -One of the new trends in Continuous Integration/Deployment is to: +For example, you might want to: 1. Create an application image. 1. Run tests against the created image. 1. Push image to a remote registry. 1. Deploy to a server from the pushed image. -It's also useful when your application already has the `Dockerfile` that can be -used to create and test an image: +Or, if your application already has a `Dockerfile`, you can +use it to create and test an image: ```shell docker build -t my-image dockerfiles/ @@ -26,29 +26,37 @@ docker tag my-image my-registry:5000/my-image docker push my-registry:5000/my-image ``` -This requires special configuration of GitLab Runner to enable `docker` support -during jobs. +To run Docker commands in your CI/CD jobs, you must configure +GitLab Runner to enable `docker` support. -## Runner Configuration +## Enable Docker commands in your CI/CD jobs -There are three methods to enable the use of `docker build` and `docker run` -during jobs, each with their own tradeoffs. +There are three ways to enable the use of `docker build` and `docker run` +during jobs, each with their own tradeoffs. You can use: -An alternative to using `docker build` is to [use kaniko](using_kaniko.md). -This avoids having to execute a runner in privileged mode. +- [The shell executor](#use-the-shell-executor) +- [The Docker executor with the Docker image (Docker-in-Docker)](#use-the-docker-executor-with-the-docker-image-docker-in-docker) +- [Docker socket binding](#use-docker-socket-binding) -NOTE: -To see how Docker and GitLab Runner are configured for shared runners on -GitLab.com, see [GitLab.com shared -runners](../../user/gitlab_com/index.md#shared-runners). +If you don't want to execute a runner in privileged mode, +but want to use `docker build`, you can also [use kaniko](using_kaniko.md). + +If you are using shared runners on GitLab.com, see +[GitLab.com shared runners](../../user/gitlab_com/index.md#shared-runners) +to learn more about how these runners are configured. -### Use shell executor +### Use the shell executor -The simplest approach is to install GitLab Runner in `shell` execution mode. -GitLab Runner then executes job scripts as the `gitlab-runner` user. +One way to configure GitLab Runner for `docker` support is to use the +`shell` executor. -1. Install [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner/#installation). -1. During GitLab Runner installation select `shell` as method of executing job scripts or use command: +After you register a runner and select the `shell` executor, +your job scripts are executed as the `gitlab-runner` user. +This user needs permission to run Docker commands. + +1. [Install](https://gitlab.com/gitlab-org/gitlab-runner/#installation) GitLab Runner. +1. [Register](https://docs.gitlab.com/runner/register/) a runner. + Select the `shell` executor. For example: ```shell sudo gitlab-runner register -n \ @@ -58,12 +66,10 @@ GitLab Runner then executes job scripts as the `gitlab-runner` user. --description "My Runner" ``` -1. Install Docker Engine on server. - - For more information how to install Docker Engine on different systems, - check out the [Supported installations](https://docs.docker.com/engine/installation/). +1. On the server where GitLab Runner is installed, install Docker Engine. + View a list of [supported platforms](https://docs.docker.com/engine/installation/). -1. Add `gitlab-runner` user to `docker` group: +1. Add the `gitlab-runner` user to the `docker` group: ```shell sudo usermod -aG docker gitlab-runner @@ -75,7 +81,7 @@ GitLab Runner then executes job scripts as the `gitlab-runner` user. sudo -u gitlab-runner -H docker info ``` - You can now verify that everything works by adding `docker info` to `.gitlab-ci.yml`: +1. In GitLab, to verify that everything works, add `docker info` to `.gitlab-ci.yml`: ```yaml before_script: @@ -87,28 +93,30 @@ GitLab Runner then executes job scripts as the `gitlab-runner` user. - docker run my-docker-image /script/to/run/tests ``` -1. You can now use `docker` command (and **install** `docker-compose` if needed). +You can now use `docker` commands (and install `docker-compose` if needed). + +When you add `gitlab-runner` to the `docker` group, you are effectively granting `gitlab-runner` full root permissions. +Learn more about the [security of the `docker` group](https://blog.zopyx.com/on-docker-security-docker-group-considered-harmful/). -By adding `gitlab-runner` to the `docker` group you are effectively granting `gitlab-runner` full root permissions. -For more information please read [On Docker security: `docker` group considered harmful](https://blog.zopyx.com/on-docker-security-docker-group-considered-harmful/). +### Use the Docker executor with the Docker image (Docker-in-Docker) -### Use Docker-in-Docker workflow with Docker executor +Another way to configure GitLab Runner for `docker` support is to +register a runner with the Docker executor and use the [Docker image](https://hub.docker.com/_/docker/) +to run your job scripts. This configuration is referred to as "Docker-in-Docker." -The second approach is to use the special Docker-in-Docker (dind) -[Docker image](https://hub.docker.com/_/docker/) with all tools installed -(`docker`) and run the job script in context of that -image in privileged mode. +The Docker image has all of the `docker` tools installed +and can run the job script in context of the image in privileged mode. -`docker-compose` is not part of Docker-in-Docker (dind). To use `docker-compose` in your -CI builds, follow the `docker-compose` +The `docker-compose` command is not available in this configuration by default. +To use `docker-compose` in your job scripts, follow the `docker-compose` [installation instructions](https://docs.docker.com/compose/install/). WARNING: -By enabling `--docker-privileged`, you are effectively disabling all of +When you enable `--docker-privileged`, you are effectively disabling all of the security mechanisms of containers and exposing your host to privilege escalation which can lead to container breakout. For more information, check out the official Docker documentation on -[Runtime privilege and Linux capabilities](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities). +[runtime privilege and Linux capabilities](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities). Docker-in-Docker works well, and is the recommended configuration, but it is not without its own challenges: @@ -363,10 +371,11 @@ build: - docker run my-docker-image /script/to/run/tests ``` -#### Use Docker socket binding +### Use Docker socket binding -The third approach is to bind-mount `/var/run/docker.sock` into the -container so that Docker is available in the context of that image. +Another way to configure GitLab Runner for `docker` support is to +bind-mount `/var/run/docker.sock` into the +container so that Docker is available in the context of the image. NOTE: If you bind the Docker socket and you are @@ -395,7 +404,7 @@ To make Docker available in the context of the image: commands are siblings of the runner rather than children of the runner.** This may have complications and limitations that are unsuitable for your workflow. - Your `config.toml` file should not have an entry like this: + Your `config.toml` file should now have an entry like this: ```toml [[runners]] @@ -854,13 +863,13 @@ After you've built a Docker image, you can push it up to the built-in ### `docker: Cannot connect to the Docker daemon at tcp://docker:2375. Is the docker daemon running?` This is a common error when you are using -[Docker in Docker](#use-docker-in-docker-workflow-with-docker-executor) +[Docker in Docker](#use-the-docker-executor-with-the-docker-image-docker-in-docker) v19.03 or higher. This occurs because Docker starts on TLS automatically, so you need to do some setup. If: - This is the first time setting it up, carefully read - [using Docker in Docker workflow](#use-docker-in-docker-workflow-with-docker-executor). + [using Docker in Docker workflow](#use-the-docker-executor-with-the-docker-image-docker-in-docker). - You are upgrading from v18.09 or earlier, read our [upgrade guide](https://about.gitlab.com/releases/2019/07/31/docker-in-docker-with-docker-19-dot-03/). diff --git a/doc/ci/docker/using_docker_images.md b/doc/ci/docker/using_docker_images.md index 7171269cf2d..630e106b72c 100644 --- a/doc/ci/docker/using_docker_images.md +++ b/doc/ci/docker/using_docker_images.md @@ -10,18 +10,18 @@ type: concepts, howto GitLab CI/CD in conjunction with [GitLab Runner](../runners/README.md) can use [Docker Engine](https://www.docker.com/) to test and build any application. -Docker is an open-source project that allows you to use predefined images to -run applications in independent "containers" that are run within a single Linux -instance. [Docker Hub](https://hub.docker.com/) has a rich database of pre-built images that can be -used to test and build your applications. - -When used with GitLab CI/CD, Docker runs each job in a separate and isolated -container using the predefined image that's set up in -[`.gitlab-ci.yml`](../yaml/README.md). - -This makes it easier to have a simple and reproducible build environment that -can also run on your workstation. The added benefit is that you can test all -the commands that we explore later from your shell, rather than having to +Docker is an open-source project that has predefined images you can use to +run applications in independent "containers." These containers run in a single Linux +instance. [Docker Hub](https://hub.docker.com/) is a database of pre-built images you can +use to test and build your applications. + +When you use Docker with GitLab CI/CD, Docker runs each job in a separate and isolated +container. You specify the container image in the project's +[`.gitlab-ci.yml`](../yaml/README.md) file. + +Docker containers provide a reproducible build environment that +can run on your workstation. When a Docker container is running, you can test +commands from your shell, rather than having to test them on a dedicated CI server. ## Register Docker Runner @@ -29,7 +29,7 @@ test them on a dedicated CI server. To use GitLab Runner with Docker you need to [register a new runner](https://docs.gitlab.com/runner/register/) to use the `docker` executor. -An example can be seen below. First we set up a temporary template to supply the services: +In this example, we first set up a temporary template to supply the services: ```shell cat > /tmp/test-config.template.toml << EOF @@ -42,7 +42,7 @@ name = "mysql:latest" EOF ``` -Then we register the runner using the template that was just created: +Then use this template to register the runner: ```shell sudo gitlab-runner register \ @@ -63,25 +63,26 @@ accessible during the build process. The `image` keyword is the name of the Docker image the Docker executor runs to perform the CI tasks. -By default, the executor only pulls images from [Docker Hub](https://hub.docker.com/), -however this can be configured in the `gitlab-runner/config.toml` by setting -the [Docker pull policy](https://docs.gitlab.com/runner/executors/docker.html#how-pull-policies-work) to allow using local images. +By default, the executor pulls images only from [Docker Hub](https://hub.docker.com/). +However, you can configure the location in the `gitlab-runner/config.toml` file. For example, +you can set the [Docker pull policy](https://docs.gitlab.com/runner/executors/docker.html#how-pull-policies-work) +to use local images. -For more information about images and Docker Hub, please read +For more information about images and Docker Hub, read the [Docker Fundamentals](https://docs.docker.com/engine/understanding-docker/) documentation. ## What is a service -The `services` keyword defines just another Docker image that's run during -your job and is linked to the Docker image that the `image` keyword defines. -This allows you to access the service image during build time. +The `services` keyword defines another Docker image that's run during +your job. It's linked to the Docker image that the `image` keyword defines, +which allows you to access the service image during build time. The service image can run any application, but the most common use case is to run a database container, for example, `mysql`. It's easier and faster to use an -existing image and run it as an additional container than install `mysql` every +existing image and run it as an additional container than to install `mysql` every time the project is built. -You're not limited to have only database services. You can add as many +You're not limited to only database services. You can add as many services you need to `.gitlab-ci.yml` or manually modify `config.toml`. Any image found at [Docker Hub](https://hub.docker.com/) or your private Container Registry can be used as a service. @@ -94,56 +95,57 @@ You can see some widely used services examples in the relevant documentation of ### How services are linked to the job -To better understand how the container linking works, read +To better understand how container linking works, read [Linking containers together](https://docs.docker.com/engine/userguide/networking/default_network/dockerlinks/). -To summarize, if you add `mysql` as service to your application, the image is -then used to create a container that's linked to the job container. +If you add `mysql` as service to your application, the image is +used to create a container that's linked to the job container. The service container for MySQL is accessible under the hostname `mysql`. -So, in order to access your database service you have to connect to the host -named `mysql` instead of a socket or `localhost`. Read more in [accessing the -services](#accessing-the-services). +To access your database service, connect to the host named `mysql` instead of a +socket or `localhost`. Read more in [accessing the services](#accessing-the-services). ### How the health check of services works -Services are designed to provide additional functionality which is **network accessible**. -It may be a database like MySQL, or Redis, and even `docker:stable-dind` which -allows you to use Docker in Docker. It can be practically anything that's -required for the CI/CD job to proceed and is accessed by network. +Services are designed to provide additional features which are **network accessible**. +They may be a database like MySQL, or Redis, and even `docker:stable-dind` which +allows you to use Docker-in-Docker. It can be practically anything that's +required for the CI/CD job to proceed, and is accessed by network. To make sure this works, the runner: 1. Checks which ports are exposed from the container by default. 1. Starts a special container that waits for these ports to be accessible. -When the second stage of the check fails, either because there is no opened port in the -service, or the service was not started properly before the timeout and the port is not -responding, it prints the warning: `*** WARNING: Service XYZ probably didn't start properly`. +If the second stage of the check fails, it prints the warning: `*** WARNING: Service XYZ probably didn't start properly`. +This issue can occur because: + +- There is no opened port in the service. +- The service was not started properly before the timeout, and the port is not + responding. In most cases it affects the job, but there may be situations when the job still succeeds even if that warning was printed. For example: -- The service was started a little after the warning was raised, and the job is +- The service was started shortly after the warning was raised, and the job is not using the linked service from the beginning. In that case, when the job needed to access the service, it may have been already there waiting for connections. - The service container is not providing any networking service, but it's doing something with the job's directory (all services have the job directory mounted as a volume under `/builds`). In that case, the service does its job, and - since the job is not trying to connect to it, it does not fail. + because the job is not trying to connect to it, it does not fail. ### What services are not for -As it was mentioned before, this feature is designed to provide **network accessible** +As mentioned before, this feature is designed to provide **network accessible** services. A database is the simplest example of such a service. -The services feature is not designed to, and does not add any software from the +The services feature is not designed to, and does not, add any software from the defined `services` image(s) to the job's container. For example, if you have the following `services` defined in your job, the `php`, -`node` or `go` commands are **not** available for your script, and thus -the job fails: +`node` or `go` commands are **not** available for your script, and the job fails: ```yaml job: @@ -162,16 +164,15 @@ If you need to have `php`, `node` and `go` available for your script, you should either: - Choose an existing Docker image that contains all required tools. -- Create your own Docker image, with all the required tools included +- Create your own Docker image, with all the required tools included, and use that in your job. ### Accessing the services Let's say that you need a Wordpress instance to test some API integration with -your application. - -You can then use for example the [tutum/wordpress](https://hub.docker.com/r/tutum/wordpress/) image in your -`.gitlab-ci.yml`: +your application. You can then use for example the +[`tutum/wordpress`](https://hub.docker.com/r/tutum/wordpress/) image in your +`.gitlab-ci.yml` file: ```yaml services: @@ -179,13 +180,13 @@ services: ``` If you don't [specify a service alias](#available-settings-for-services), -when the job is run, `tutum/wordpress` is started and you have -access to it from your build container under two hostnames to choose from: +when the job runs, `tutum/wordpress` is started. You have +access to it from your build container under two hostnames: - `tutum-wordpress` - `tutum__wordpress` -Hostnames with underscores are not RFC valid and may cause problems in 3rd party +Hostnames with underscores are not RFC valid and may cause problems in third-party applications. The default aliases for the service's hostname are created from its image name @@ -202,7 +203,7 @@ To override the default behavior, you can ## Define `image` and `services` from `.gitlab-ci.yml` -You can simply define an image that's used for all jobs and a list of +You can define an image that's used for all jobs, and a list of services that you want to use during build time: ```yaml @@ -275,7 +276,7 @@ test: You can also pass custom environment [variables](../variables/README.md) to fine tune your Docker `images` and `services` directly in the `.gitlab-ci.yml` file. -For more information, see [custom environment variables](../variables/README.md#gitlab-ciyml-defined-variables) +For more information, read [custom environment variables](../variables/README.md#gitlab-ciyml-defined-variables) ```yaml # The following variables are automatically passed down to the Postgres container @@ -314,11 +315,11 @@ test: When configuring the `image` or `services` entries, you can use a string or a map as options: -- when using a string as an option, it must be the full name of the image to use +- When using a string as an option, it must be the full name of the image to use (including the Registry part if you want to download the image from a Registry - other than Docker Hub) -- when using a map as an option, then it must contain at least the `name` - option, which is the same name of the image as used for the string setting + other than Docker Hub). +- When using a map as an option, then it must contain at least the `name` + option, which is the same name of the image as used for the string setting. For example, the following two definitions are equal: @@ -350,8 +351,8 @@ For example, the following two definitions are equal: | Setting | Required | GitLab version | Description | |------------|----------|----------------| ----------- | -| `name` | yes, when used with any other option | 9.4 |Full name of the image that should be used. It should contain the Registry part if needed. | -| `entrypoint` | no | 9.4 |Command or script that should be executed as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. | +| `name` | yes, when used with any other option | 9.4 |Full name of the image to use. It should contain the Registry part if needed. | +| `entrypoint` | no | 9.4 |Command or script to execute as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. | ### Available settings for `services` @@ -359,8 +360,8 @@ For example, the following two definitions are equal: | Setting | Required | GitLab version | Description | |------------|----------|----------------| ----------- | -| `name` | yes, when used with any other option | 9.4 | Full name of the image that should be used. It should contain the Registry part if needed. | -| `entrypoint` | no | 9.4 |Command or script that should be executed as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. | +| `name` | yes, when used with any other option | 9.4 | Full name of the image to use. It should contain the Registry part if needed. | +| `entrypoint` | no | 9.4 |Command or script to execute as the container's entrypoint. It's translated to Docker's `--entrypoint` option while creating the container. The syntax is similar to [`Dockerfile`'s `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint) directive, where each shell token is a separate string in the array. | | `command` | no | 9.4 |Command or script that should be used as the container's command. It's translated to arguments passed to Docker after the image's name. The syntax is similar to [`Dockerfile`'s `CMD`](https://docs.docker.com/engine/reference/builder/#cmd) directive, where each shell token is a separate string in the array. | | `alias` (1) | no | 9.4 |Additional alias that can be used to access the service from the job's container. Read [Accessing the services](#accessing-the-services) for more information. | @@ -379,8 +380,8 @@ services: - mysql:latest ``` -The runner would start two containers using the `mysql:latest` image, but both -of them would be added to the job's container with the `mysql` alias based on +The runner would start two containers, each that uses the `mysql:latest` image. +However, both of them would be added to the job's container with the `mysql` alias, based on the [default hostname naming](#accessing-the-services). This would end with one of the services not being accessible. @@ -404,31 +405,33 @@ in `.gitlab-ci.yml` file. > Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](#extended-docker-configuration-options). Let's assume you have a `super/sql:latest` image with some SQL database -inside it and you would like to use it as a service for your job. Let's also +in it. You would like to use it as a service for your job. Let's also assume that this image does not start the database process while starting -the container and the user needs to manually use `/usr/bin/super-sql run` as +the container. The user needs to manually use `/usr/bin/super-sql run` as a command to start the database. -Before the new extended Docker configuration options, you would need to create -your own image based on the `super/sql:latest` image, add the default command, -and then use it in job's configuration, like: +Before the new extended Docker configuration options, you would need to: -```dockerfile -# my-super-sql:latest image's Dockerfile +- Create your own image based on the `super/sql:latest` image. +- Add the default command. +- Use the image in the job's configuration: -FROM super/sql:latest -CMD ["/usr/bin/super-sql", "run"] -``` + ```dockerfile + # my-super-sql:latest image's Dockerfile -```yaml -# .gitlab-ci.yml + FROM super/sql:latest + CMD ["/usr/bin/super-sql", "run"] + ``` -services: - - my-super-sql:latest -``` + ```yaml + # .gitlab-ci.yml + + services: + - my-super-sql:latest + ``` -After the new extended Docker configuration options, you can now simply -set a `command` in `.gitlab-ci.yml`, like: +After the new extended Docker configuration options, you can +set a `command` in the `.gitlab-ci.yml` file instead: ```yaml # .gitlab-ci.yml @@ -438,15 +441,15 @@ services: command: ["/usr/bin/super-sql", "run"] ``` -As you can see, the syntax of `command` is similar to [Dockerfile's `CMD`](https://docs.docker.com/engine/reference/builder/#cmd). +The syntax of `command` is similar to [Dockerfile's `CMD`](https://docs.docker.com/engine/reference/builder/#cmd). ### Overriding the entrypoint of an image > Introduced in GitLab and GitLab Runner 9.4. Read more about the [extended configuration options](#extended-docker-configuration-options). -Before showing the available entrypoint override methods, let's describe shortly -how the runner starts and uses a Docker image for the containers used in the -CI jobs: +Before showing the available entrypoint override methods, let's describe +how the runner starts. It uses a Docker image for the containers used in the +CI/CD jobs: 1. The runner starts a Docker container using the defined entrypoint (default from `Dockerfile` that may be overridden in `.gitlab-ci.yml`) @@ -455,32 +458,35 @@ CI jobs: [`before_script`](../yaml/README.md#before_script), [`script`](../yaml/README.md#script), and [`after_script`](../yaml/README.md#after_script)). -1. The runner sends the script to the container's shell STDIN and receives the +1. The runner sends the script to the container's shell `stdin` and receives the output. -To override the entrypoint of a Docker image, the recommended solution is to +To override the entrypoint of a Docker image, you should define an empty `entrypoint` in `.gitlab-ci.yml`, so the runner does not start a useless shell layer. However, that does not work for all Docker versions, and -you should check which one your runner is using. Specifically: +you should check which one your runner is using: -- If Docker 17.06 or later is used, the `entrypoint` can be set to an empty value. -- If Docker 17.03 or previous versions are used, the `entrypoint` can be set to +- _If Docker 17.06 or later is used,_ the `entrypoint` can be set to an empty value. +- _If Docker 17.03 or previous versions are used,_ the `entrypoint` can be set to `/bin/sh -c`, `/bin/bash -c` or an equivalent shell available in the image. The syntax of `image:entrypoint` is similar to [Dockerfile's `ENTRYPOINT`](https://docs.docker.com/engine/reference/builder/#entrypoint). -Let's assume you have a `super/sql:experimental` image with some SQL database -inside it and you would like to use it as a base image for your job because you +Let's assume you have a `super/sql:experimental` image with a SQL database +in it. You want to use it as a base image for your job because you want to execute some tests with this database binary. Let's also assume that -this image is configured with `/usr/bin/super-sql run` as an entrypoint. That -means that when starting the container without additional options, it runs -the database's process, while the runner expects that the image has no +this image is configured with `/usr/bin/super-sql run` as an entrypoint. When +the container starts without additional options, it runs +the database's process. The runner expects that the image has no entrypoint or that the entrypoint is prepared to start a shell command. -With the extended Docker configuration options, instead of creating your -own image based on `super/sql:experimental`, setting the `ENTRYPOINT` -to a shell, and then using the new image in your CI job, you can now simply -define an `entrypoint` in `.gitlab-ci.yml`. +With the extended Docker configuration options, instead of: + +- Creating your own image based on `super/sql:experimental`. +- Setting the `ENTRYPOINT` to a shell. +- Using the new image in your CI job. + +You can now define an `entrypoint` in the `.gitlab-ci.yml` file. **For Docker 17.06+:** @@ -508,7 +514,7 @@ Look for the `[runners.docker]` section: services = ["mysql:latest", "postgres:latest"] ``` -The image and services defined this way are added to all job run by +The image and services defined this way are added to all jobs run by that runner. ## Define an image from a private Container Registry @@ -516,8 +522,8 @@ that runner. To access private container registries, the GitLab Runner process can use: - [Statically defined credentials](#using-statically-defined-credentials). That is, a username and password for a specific registry. -- [Credentials Store](#using-credentials-store). For more information, see [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credentials-store). -- [Credential Helpers](#using-credential-helpers). For more information, see [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credential-helpers). +- [Credentials Store](#using-credentials-store). For more information, read [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credentials-store). +- [Credential Helpers](#using-credential-helpers). For more information, read [the relevant Docker documentation](https://docs.docker.com/engine/reference/commandline/login/#credential-helpers). To define which should be used, the GitLab Runner process reads the configuration in the following order: @@ -531,7 +537,7 @@ To define which should be used, the GitLab Runner process reads the configuratio GitLab Runner reads this configuration **only** from `config.toml` and ignores it if it's provided as an environment variable. This is because GitLab Runner uses **only** -`config.toml` configuration and does not interpolate **ANY** environment variables at +`config.toml` configuration and does not interpolate **any** environment variables at runtime. ### Requirements and limitations @@ -543,7 +549,7 @@ runtime. at least version **1.8** if you want to use private registries. - Available for [Kubernetes executor](https://docs.gitlab.com/runner/executors/kubernetes.html) in GitLab Runner 13.1 and later. -- [Credentials Store](#using-credentials-store) and [Credential Helpers](#using-credential-helpers) require binaries to be added to the GitLab Runner's `$PATH`, and require access to do so. Therefore, these features are not available on shared runners or any other runner where the user does not have access to the environment where the runner is installed. +- [Credentials Store](#using-credentials-store) and [Credential Helpers](#using-credential-helpers) require binaries to be added to the GitLab Runner's `$PATH`, and require access to do so. Therefore, these features are not available on shared runners, or any other runner where the user does not have access to the environment where the runner is installed. ### Using statically-defined credentials @@ -562,7 +568,7 @@ See below for examples of each. #### Determining your `DOCKER_AUTH_CONFIG` data As an example, let's assume you want to use the `registry.example.com:5000/private/image:latest` -image, which is private and requires you to sign in to a private container +image. This image is private and requires you to sign in to a private container registry. Let's also assume that these are the sign-in credentials: @@ -592,7 +598,7 @@ Use one of the following methods to determine the value of `DOCKER_AUTH_CONFIG`: - In some setups, it's possible that Docker client uses the available system key store to store the result of `docker login`. In that case, it's impossible to - read `~/.docker/config.json`, so you need to prepare the required + read `~/.docker/config.json`, so you must prepare the required base64-encoded version of `${username}:${password}` and create the Docker configuration JSON manually. Open a terminal and execute the following command: @@ -691,7 +697,7 @@ To add `DOCKER_AUTH_CONFIG` to a runner: To configure credentials store, follow these steps: 1. To use a credentials store, you need an external helper program to interact with a specific keychain or external store. - Make sure helper program is available in GitLab Runner `$PATH`. + Make sure the helper program is available in GitLab Runner `$PATH`. 1. Make GitLab Runner use it. There are two ways to accomplish this. Either: @@ -710,16 +716,16 @@ To configure credentials store, follow these steps: `${GITLAB_RUNNER_HOME}/.docker/config.json`. GitLab Runner reads this configuration file and uses the needed helper for this specific repository. -`credsStore` is used to access ALL the registries. -If you want to use both images from private registry and public images from Docker Hub, -pulling from Docker Hub would fail, because Docker daemon tries to use the same credentials for **ALL** the registries. +`credsStore` is used to access **all** the registries. +If you use both images from a private registry and public images from Docker Hub, +pulling from Docker Hub fails. Docker daemon tries to use the same credentials for **all** the registries. ### Using Credential Helpers > Support for using Credential Helpers was added in GitLab Runner 12.0 As an example, let's assume that you want to use the `aws_account_id.dkr.ecr.region.amazonaws.com/private/image:latest` -image which is private and requires you to log in into a private container registry. +image. This image is private and requires you to log in into a private container registry. To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow these steps: @@ -750,7 +756,7 @@ To configure access for `aws_account_id.dkr.ecr.region.amazonaws.com`, follow th } ``` - This configures Docker to use the credential helper for all Amazon ECR registries. + This configures Docker to use the credential helper for all Amazon Elastic Container Registry (ECR) registries. - Or, if you're running self-managed runners, add the above JSON to `${GITLAB_RUNNER_HOME}/.docker/config.json`. @@ -772,13 +778,13 @@ registries to the `"credHelpers"` hash as described above. ## Configuring services -Many services accept environment variables which allow you to easily change -database names or set account names depending on the environment. +Many services accept environment variables, which you can use to change +database names or set account names, depending on the environment. GitLab Runner 0.5.0 and up passes all YAML-defined variables to the created service containers. -For all possible configuration variables check the documentation of each image +For all possible configuration variables, check the documentation of each image provided in their corresponding Docker hub page. All variables are passed to all services containers. It's not @@ -786,12 +792,12 @@ designed to distinguish which variable should go where. ### PostgreSQL service example -See the specific documentation for +Read the specific documentation for [using PostgreSQL as a service](../services/postgres.md). ### MySQL service example -See the specific documentation for +Read the specific documentation for [using MySQL as a service](../services/mysql.md). ## How Docker integration works @@ -800,15 +806,15 @@ Below is a high level overview of the steps performed by Docker during job time. 1. Create any service container: `mysql`, `postgresql`, `mongodb`, `redis`. -1. Create cache container to store all volumes as defined in `config.toml` and +1. Create a cache container to store all volumes as defined in `config.toml` and `Dockerfile` of build image (`ruby:2.6` as in above example). -1. Create build container and link any service container to build container. -1. Start build container and send job script to the container. -1. Run job script. +1. Create a build container and link any service container to build container. +1. Start the build container, and send a job script to the container. +1. Run the job script. 1. Checkout code in: `/builds/group-name/project-name/`. 1. Run any step defined in `.gitlab-ci.yml`. -1. Check exit status of build script. -1. Remove build container and all created service containers. +1. Check the exit status of build script. +1. Remove the build container and all created service containers. ## How to debug a job locally @@ -827,8 +833,7 @@ EOF Here we use as an example the GitLab Runner repository which contains a Makefile, so running `make` executes the commands defined in the Makefile. -Your mileage may vary, so instead of `make` you could run the command which -is specific to your project. +Instead of `make`, you could run the command which is specific to your project. Then create some service containers: @@ -850,7 +855,7 @@ docker run --name build -i --link=service-mysql:mysql --link=service-postgres:po The above command creates a container named `build` that's spawned from the `ruby:2.6` image and has two services linked to it. The `build_script` is -piped using STDIN to the bash interpreter which in turn executes the +piped using `stdin` to the bash interpreter which in turn executes the `build_script` in the `build` container. When you finish testing and no longer need the containers, you can remove them @@ -861,5 +866,5 @@ docker rm -f -v build service-mysql service-postgres ``` This forcefully (`-f`) removes the `build` container, the two service -containers as well as all volumes (`-v`) that were created with the container +containers, and all volumes (`-v`) that were created with the container creation. diff --git a/doc/ci/docker/using_kaniko.md b/doc/ci/docker/using_kaniko.md index 13d3c607f8a..7eb2a8286c7 100644 --- a/doc/ci/docker/using_kaniko.md +++ b/doc/ci/docker/using_kaniko.md @@ -14,7 +14,7 @@ container images from a Dockerfile, inside a container or Kubernetes cluster. kaniko solves two problems with using the [Docker-in-Docker -build](using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor) method: +build](using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker) method: - Docker-in-Docker requires [privileged mode](https://docs.docker.com/engine/reference/run/#runtime-privilege-and-linux-capabilities) to function, which is a significant security concern. @@ -70,6 +70,39 @@ build: - if: $CI_COMMIT_TAG ``` +### Building an image with kaniko behind a proxy + +If you use a custom GitLab Runner behind an http(s) proxy, kaniko needs to be set +up accordingly. This means: + +- Adding the proxy to `/kaniko/.docker/config.json` +- Passing the `http_proxy` environment variables as build args so the Dockerfile + instructions can use the proxy when building the image. + +The previous example can be extended as follows: + +```yaml +build: + stage: build + image: + name: gcr.io/kaniko-project/executor:debug + entrypoint: [""] + script: + - mkdir -p /kaniko/.docker + - |- + KANIKOPROXYBUILDARGS="" + KANIKOCFG="{ \"auths\":{\"$CI_REGISTRY\":{\"username\":\"$CI_REGISTRY_USER\",\"password\":\"$CI_REGISTRY_PASSWORD\"}}" + if [ "x${http_proxy}" != "x" -o "x${https_proxy}" != "x" ]; then + KANIKOCFG="${KANIKOCFG}, \"proxies\": { \"default\": { \"httpProxy\": \"${http_proxy}\", \"httpsProxy\": \"${https_proxy}\", \"noProxy\": \"${no_proxy}\"}}" + KANIKOPROXYBUILDARGS="--build-arg http_proxy=${http_proxy} --build-arg https_proxy=${https_proxy} --build-arg no_proxy=${no_proxy}" + fi + KANIKOCFG="${KANIKOCFG} }" + echo "${KANIKOCFG}" > /kaniko/.docker/config.json + - /kaniko/executor --context $CI_PROJECT_DIR --dockerfile $CI_PROJECT_DIR/Dockerfile $KANIKOPROXYBUILDARGS --destination $CI_REGISTRY_IMAGE:$CI_COMMIT_TAG + only: + - tags +``` + ## Using a registry with a custom certificate When trying to push to a Docker registry that uses a certificate that is signed diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md index 95419e58d36..4dac076ffb7 100644 --- a/doc/ci/environments/deployment_safety.md +++ b/doc/ci/environments/deployment_safety.md @@ -14,6 +14,9 @@ You can: - [Restrict write-access to a critical environment](#restrict-write-access-to-a-critical-environment) - [Prevent deployments during deploy freeze windows](#prevent-deployments-during-deploy-freeze-windows) +- [Set appropriate roles to your project](#setting-appropriate-roles-to-your-project) +- [Protect production secrets](#protect-production-secrets) +- [Separate project for deployments](#separate-project-for-deployments) If you are using a continuous deployment workflow and want to ensure that concurrent deployments to the same environment do not happen, you should enable the following options: @@ -38,8 +41,8 @@ For example: ```yaml deploy: - script: deploy-to-prod - resource_group: prod + script: deploy-to-prod + resource_group: prod ``` Example of a problematic pipeline flow **before** using the resource group: @@ -89,6 +92,56 @@ If you want to prevent deployments for a particular period, for example during a vacation period when most employees are out, you can set up a [Deploy Freeze](../../user/project/releases/index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze). During a deploy freeze period, no deployment can be executed. This is helpful to ensure that deployments do not happen unexpectedly. + +## Setting appropriate roles to your project + +GitLab supports several different roles that can be assigned to your project members. See +[Project members permissions](../../user/permissions.md#project-members-permissions) +for an explanation of these roles and the permissions of each. + +<div class="video-fallback"> + See the video: <a href="https://www.youtube.com/watch?v=Mq3C1KveDc0">How to secure your CD pipelines</a>. +</div> +<figure class="video-container"> + <iframe src="https://www.youtube.com/embed/Mq3C1KveDc0" frameborder="0" allowfullscreen="true"> </iframe> +</figure> + +## Protect production secrets + +Production secrets are needed to deploy successfully. For example, when deploying to the cloud, +cloud providers require these secrets to connect to their services. In the project settings, you can +define and protect environment variables for these secrets. [Protected variables](../variables/README.md#protect-a-custom-variable) +are only passed to pipelines running on [protected branches](../../user/project/protected_branches.md) +or [protected tags](../../user/project/protected_tags.md). +The other pipelines don't get the protected variable. You can also +[scope variables to specific environments](../variables/where_variables_can_be_used.md#variables-with-an-environment-scope). +We recommend that you use protected variables on protected environments to make sure that the +secrets aren't exposed unintentionally. You can also define production secrets on the +[runner side](../runners/README.md#prevent-runners-from-revealing-sensitive-information). +This prevents other maintainers from reading the secrets and makes sure that the runner only runs on +protected branches. + +For more information, see [pipeline security](../pipelines/index.md#pipeline-security-on-protected-branches). + +## Separate project for deployments + +All project maintainers have access to production secrets. If you need to limit the number of users +that can deploy to a production environment, you can create a separate project and configure a new +permission model that isolates the CD permissions from the original project and prevents the +original project's maintainers from accessing the production secret and CD configuration. You can +connect the CD project to your development projects by using [multi-project pipelines](../multi_project_pipelines.md). + +## Protect `gitlab-ci.yml` from change + +A `.gitlab-ci.yml` may contain rules to deploy an application to the production server. This +deployment usually runs automatically after pushing a merge request. To prevent developers from +changing the `gitlab-ci.yml`, you can define it in a different repository. The configuration can +reference a file in another project with a completely different set of permissions (similar to +[separating a project for deployments](#separate-project-for-deployments)). +In this scenario, the `gitlab-ci.yml` is publicly accessible, but can only be edited by users with +appropriate permissions in the other project. + +For more information, see [Custom CI configuration path](../pipelines/settings.md#custom-ci-configuration-path). ## Troubleshooting @@ -99,14 +152,13 @@ If you have multiple jobs for the same environment (including non-deployment job ```yaml build:service-a: - environment: - name: production - + environment: + name: production + build:service-b: - environment: - name: production + environment: + name: production ``` -The [Skip outdated deployment jobs](../pipelines/settings.md#skip-outdated-deployment-jobs) might not work well with this configuration, and will need to be disabled. - -There is a [plan to introduce a new annotation for environments](https://gitlab.com/gitlab-org/gitlab/-/issues/208655) to address this issue. +The [Skip outdated deployment jobs](../pipelines/settings.md#skip-outdated-deployment-jobs) might +not work well with this configuration, and must be disabled. diff --git a/doc/ci/environments/incremental_rollouts.md b/doc/ci/environments/incremental_rollouts.md index 81acc3a36e9..15eb4d2c526 100644 --- a/doc/ci/environments/incremental_rollouts.md +++ b/doc/ci/environments/incremental_rollouts.md @@ -44,8 +44,8 @@ allows more control over the this feature. The steps in an incremental rollout d number of pods that are defined for the deployment, which are configured when the Kubernetes cluster is created. -For example, if your application has 10 pods and a 10% rollout job is run, the new instance of the -application will be deployed to a single pod while the remaining 9 will present the previous instance. +For example, if your application has 10 pods and a 10% rollout job runs, the new instance of the +application is deployed to a single pod while the remaining nine are present the previous instance. First we [define the template as manual](https://gitlab.com/gl-release/incremental-rollout-example/blob/master/.gitlab-ci.yml#L100-103): @@ -65,7 +65,7 @@ rollout 10%: ROLLOUT_PERCENTAGE: 10 ``` -When the jobs are built, a **play** button will appear next to the job's name. Click the **play** button +When the jobs are built, a **play** button appears next to the job's name. Click the **play** button to release each stage of pods. You can also rollback by running a lower percentage job. Once 100% is reached, you cannot roll back using this method. It is still possible to roll back by redeploying the old version using the **Rollback** button on the environment page. @@ -79,13 +79,13 @@ available, demonstrating manually triggered incremental rollouts. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7545) in GitLab 11.4. -Timed rollouts behave in the same way as manual rollouts, except that each job is defined with a delay -in minutes before it will deploy. Clicking on the job will reveal the countdown. +Timed rollouts behave in the same way as manual rollouts, except that each job is defined with a +delay in minutes before it deploys. Clicking the job reveals the countdown. ![Timed rollout](img/timed_rollout_v12_7.png) -It is possible to combine this functionality with manual incremental rollouts so that the job will -countdown and then deploy. +It is possible to combine this functionality with manual incremental rollouts so that the job +counts down and then deploys. First we [define the template as timed](https://gitlab.com/gl-release/timed-rollout-example/blob/master/.gitlab-ci.yml#L86-89): diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md index 10513e0797e..7bf30ef1b95 100644 --- a/doc/ci/environments/index.md +++ b/doc/ci/environments/index.md @@ -28,7 +28,7 @@ This helps find bugs in your software, and also in the deployment process as wel GitLab CI/CD is capable of not only testing or building your projects, but also deploying them in your infrastructure, with the added benefit of giving you a -way to track your deployments. In other words, you will always know what is +way to track your deployments. In other words, you always know what is currently being deployed or has been deployed on your servers. It's important to know that: @@ -102,12 +102,12 @@ We have defined three [stages](../yaml/README.md#stages): - `build` - `deploy` -The jobs assigned to these stages will run in this order. If any job fails, then -the pipeline fails and jobs that are assigned to the next stage won't run. +The jobs assigned to these stages run in this order. If any job fails, then +the pipeline fails and jobs that are assigned to the next stage don't run. In our case: -- The `test` job will run first. +- The `test` job runs first. - Then the `build` job. - Lastly the `deploy_staging` job. @@ -127,13 +127,13 @@ numbers, spaces, and `-`, `_`, `/`, `{`, `}`, or `.`. Also, it must not start no In summary, with the above `.gitlab-ci.yml` we have achieved the following: -- All branches will run the `test` and `build` jobs. -- The `deploy_staging` job will run [only](../yaml/README.md#onlyexcept-basic) on the `master` +- All branches run the `test` and `build` jobs. +- The `deploy_staging` job runs [only](../yaml/README.md#onlyexcept-basic) on the `master` branch, which means all merge requests that are created from branches don't get deployed to the staging server. -- When a merge request is merged, all jobs will run and the `deploy_staging` - job will deploy our code to a staging server while the deployment - will be recorded in an environment named `staging`. +- When a merge request is merged, all jobs run and the `deploy_staging` + job deploys our code to a staging server while the deployment + is recorded in an environment named `staging`. #### Environment variables and runners @@ -147,8 +147,8 @@ two forms: If you change the name of an existing environment, the: -- `$CI_ENVIRONMENT_NAME` variable will be updated with the new environment name. -- `$CI_ENVIRONMENT_SLUG` variable will remain unchanged to prevent unintended side +- `$CI_ENVIRONMENT_NAME` variable is updated with the new environment name. +- `$CI_ENVIRONMENT_SLUG` variable remains unchanged to prevent unintended side effects. Starting with GitLab 9.3, the environment URL is exposed to the runner via @@ -214,13 +214,13 @@ It parses the `deploy.env` report artifact, registers a list of variables as run uses it for expanding `environment:url: $DYNAMIC_ENVIRONMENT_URL` and sets it to the environment URL. You can also specify a static part of the URL at `environment:url:`, such as `https://$DYNAMIC_ENVIRONMENT_URL`. If the value of `DYNAMIC_ENVIRONMENT_URL` is -`example.com`, the final result will be `https://example.com`. +`example.com`, the final result is `https://example.com`. The assigned URL for the `review/your-branch-name` environment is [visible in the UI](#using-the-environment-url). Note the following: -- `stop_review` doesn't generate a dotenv report artifact, so it won't recognize the +- `stop_review` doesn't generate a dotenv report artifact, so it doesn't recognize the `DYNAMIC_ENVIRONMENT_URL` variable. Therefore you shouldn't set `environment:url:` in the `stop_review` job. - If the environment URL isn't valid (for example, the URL is malformed), the system doesn't update @@ -280,7 +280,7 @@ deploy_prod: The `when: manual` action: - Exposes a "play" button in the GitLab UI for that job. -- Means the `deploy_prod` job will only be triggered when the "play" button is clicked. +- Means the `deploy_prod` job is only triggered when the "play" button is clicked. You can find the "play" button in the pipelines, environments, deployments, and jobs views. @@ -330,7 +330,7 @@ For more information, see [Where variables can be used](../variables/where_varia Runners expose various [environment variables](../variables/README.md) when a job runs, so you can use them as environment names. -In the following example, the job will deploy to all branches except `master`: +In the following example, the job deploys to all branches except `master`: ```yaml deploy_review: @@ -363,7 +363,7 @@ For the value of: may contain a `/` or other characters that would be invalid in a domain name or URL, so we use `$CI_ENVIRONMENT_SLUG` to guarantee that we get a valid URL. - For example, given a `$CI_COMMIT_REF_NAME` of `100-Do-The-Thing`, the URL will be something + For example, given a `$CI_COMMIT_REF_NAME` of `100-Do-The-Thing`, the URL is something like `https://100-do-the-4f99a2.example.com`. Again, the way you set up the web server to serve these requests is based on your setup. @@ -396,7 +396,7 @@ The following configuration options are supported: - [`namespace`](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) -In the following example, the job will deploy your application to the +In the following example, the job deploys your application to the `production` Kubernetes namespace. ```yaml @@ -414,7 +414,7 @@ deploy: ``` When deploying to a Kubernetes cluster using the GitLab Kubernetes integration, -information about the cluster and namespace will be displayed above the job +information about the cluster and namespace is displayed above the job trace on the deployment job page: ![Deployment cluster information](../img/environments_deployment_cluster_v12_8.png) @@ -502,7 +502,7 @@ deploy_prod: A more realistic example would also include copying files to a location where a webserver (for example, NGINX) could then access and serve them. -The example below will copy the `public` directory to `/srv/nginx/$CI_COMMIT_REF_SLUG/public`: +The example below copies the `public` directory to `/srv/nginx/$CI_COMMIT_REF_SLUG/public`: ```yaml review_app: @@ -514,7 +514,7 @@ review_app: url: https://$CI_COMMIT_REF_SLUG.example.com ``` -This example requires that NGINX and GitLab Runner are set up on the server this job will run on. +This example requires that NGINX and GitLab Runner are set up on the server this job runs on. See the [limitations](#limitations) section for some edge cases regarding the naming of your branches and Review Apps. @@ -526,10 +526,10 @@ The complete example provides the following workflow to developers: - Push the branch to GitLab. - Create a merge request. -Behind the scenes, the runner will: +Behind the scenes, the runner: -- Pick up the changes and start running the jobs. -- Run the jobs sequentially as defined in `stages`: +- Picks up the changes and starts running the jobs. +- Runs the jobs sequentially as defined in `stages`: - First, run the tests. - If the tests succeed, build the app. - If the build succeeds, the app is deployed to an environment with a name specific to the @@ -561,7 +561,7 @@ A list of environments and deployment statuses is available on each project's ** For example: -![Environment view](../img/environments_available.png) +![Environment view](../img/environments_available_13_7.png) This example shows: @@ -571,10 +571,16 @@ This example shows: - The commit information of the last deployment, such as who committed it, to what branch, and the Git SHA of the commit. - The exact time the last deployment was performed. +- The upcoming deployment, if a deployment for the environment is in progress. +- When the environment stops automatically. - A button that takes you to the URL that you defined under the `environment` keyword in `.gitlab-ci.yml`. -- A button that re-deploys the latest deployment, meaning it runs the job - defined by the environment name for that specific commit. +- A number of deployment actions, including: + - Prevent the environment from [stopping automatically](#automatically-stopping-an-environment). + - [Open the live environment](#using-the-environment-url). + - Trigger [a manual deployment to a different environment](#configuring-manual-deployments). + - [Retry the deployment](#retrying-and-rolling-back). + - [Stop the environment](#stopping-an-environment). The information shown in the **Environments** page is limited to the latest deployments, but an environment can have multiple deployments. @@ -587,7 +593,7 @@ deployments, but an environment can have multiple deployments. > - The environments page can only be viewed by users with [Reporter permission](../../user/permissions.md#project-members-permissions) > and above. For more information on permissions, see the [permissions documentation](../../user/permissions.md). > - Only deploys that happen after your `.gitlab-ci.yml` is properly configured -> will show up in the **Environment** and **Last deployment** lists. +> show up in the **Environment** and **Last deployment** lists. ### Viewing deployment history @@ -619,7 +625,7 @@ To retry or rollback a deployment: #### What to expect with a rollback Pressing the **Rollback** button on a specific commit triggers a _new_ deployment with its own -unique job ID. This means that you will see a new deployment that points to the commit you're +unique job ID. This new deployment points to the commit you're rolling back to. Note that the defined deployment process in the job's `script` determines whether the rollback @@ -633,7 +639,7 @@ places within GitLab: - In a merge request widget as a link: ![Environment URL in merge request](../img/environments_mr_review_app.png) - In the Environments view as a button: - ![Environment URL in environments](../img/environments_available.png) + ![Environment URL in environments](../img/environments_available_13_7.png) - In the Deployments view as a button: ![Environment URL in deployments](../img/deployments_view.png) @@ -698,20 +704,20 @@ stop_review: If you can't use [Pipelines for merge requests](../merge_request_pipelines/index.md), setting the [`GIT_STRATEGY`](../runners/README.md#git-strategy) to `none` is necessary in the -`stop_review` job so that the [runner](https://docs.gitlab.com/runner/) won't +`stop_review` job so that the [runner](https://docs.gitlab.com/runner/) doesn't try to check out the code after the branch is deleted. When you have an environment that has a stop action defined (typically when -the environment describes a Review App), GitLab will automatically trigger a +the environment describes a Review App), GitLab automatically triggers a stop action when the associated branch is deleted. The `stop_review` job must be in the same `stage` as the `deploy_review` job in order for the environment to automatically stop. Additionally, both jobs should have matching [`rules`](../yaml/README.md#onlyexcept-basic) or [`only/except`](../yaml/README.md#onlyexcept-basic) configuration. In the example -above, if the configuration is not identical, the `stop_review` job might not be -included in all pipelines that include the `deploy_review` job, and it will not be -possible to trigger the `action: stop` to stop the environment automatically. +above, if the configuration isn't identical, the `stop_review` job might not be +included in all pipelines that include the `deploy_review` job, and it isn't +possible to trigger `action: stop` to stop the environment automatically. You can read more in the [`.gitlab-ci.yml` reference](../yaml/README.md#environmenton_stop). @@ -767,7 +773,7 @@ stop_review_app: ``` As long as a merge request is active and keeps getting new commits, -the review app will not stop, so developers don't need to worry about +the review app doesn't stop, so developers don't need to worry about re-initiating review app. On the other hand, since `stop_review_app` is set to `auto_stop_in: 1 week`, @@ -777,8 +783,8 @@ GitLab automatically triggers the `stop_review_app` job to stop the environment. You can also check the expiration date of environments through the GitLab UI. To do so, go to **Operations > Environments > Environment**. You can see the auto-stop period at the left-top section and a pin-mark button at the right-top section. This pin-mark -button can be used to prevent auto-stopping the environment. By clicking this button, the `auto_stop_in` setting is over-written -and the environment will be active until it's stopped manually. +button can be used to prevent auto-stopping the environment. By clicking this button, the +`auto_stop_in` setting is overwritten and the environment is active until it's stopped manually. ![Environment auto stop](../img/environment_auto_stop_v12_8.png) @@ -820,8 +826,8 @@ build with the specified environment runs. Newer deployments can also You may want to specify an environment keyword to [protect builds from unauthorized access](protected_environments.md), or to get access to [scoped variables](#scoping-environments-with-specs). In these cases, -you can use the `action: prepare` keyword to ensure deployments won't be created, -and no builds would be canceled: +you can use the `action: prepare` keyword to ensure deployments aren't created, +and no builds are canceled: ```yaml build: @@ -929,13 +935,13 @@ dashboard to appear, you need to Configure Prometheus to collect at least one In GitLab 9.2 and later, all deployments to an environment are shown directly on the monitoring dashboard. -Once configured, GitLab will attempt to retrieve [supported performance metrics](../../user/project/integrations/prometheus_library/index.md) +Once configured, GitLab attempts to retrieve [supported performance metrics](../../user/project/integrations/prometheus_library/index.md) for any environment that has had a successful deployment. If monitoring data was -successfully retrieved, a **Monitoring** button will appear for each environment. +successfully retrieved, a **Monitoring** button appears for each environment. ![Environment Detail with Metrics](../img/deployments_view.png) -Clicking on the **Monitoring** button will display a new page showing up to the last +Clicking the **Monitoring** button displays a new page showing up to the last 8 hours of performance data. It may take a minute or two for data to appear after initial deployment. @@ -962,10 +968,10 @@ of your web browser. To enable it, follow the instructions given in the service documentation. Note that container-based deployments often lack basic tools (like an editor), and may -be stopped or restarted at any time. If this happens, you will lose all your +be stopped or restarted at any time. If this happens, you lose all your changes. Treat this as a debugging tool, not a comprehensive online IDE. -Once enabled, your environments will gain a "terminal" button: +Once enabled, your environments gain a **Terminal** button: ![Terminal button on environment index](../img/environments_terminal_button_on_index.png) @@ -973,12 +979,12 @@ You can also access the terminal button from the page for a specific environment ![Terminal button for an environment](../img/environments_terminal_button_on_show.png) -Wherever you find it, clicking the button will take you to a separate page to +Wherever you find it, clicking the button takes you to a separate page to establish the terminal session: ![Terminal page](../img/environments_terminal_page.png) -This works just like any other terminal. You'll be in the container created +This works like any other terminal. You're in the container created by your deployment so you can: - Run shell commands and get responses in real time. @@ -1008,9 +1014,8 @@ fetch = +refs/environments/*:refs/remotes/origin/environments/* You can limit the environment scope of a variable by defining which environments it can be available for. -Wildcards can be used, and the default environment scope is `*`, which means -any jobs will have this variable, not matter if an environment is defined or -not. +Wildcards can be used and the default environment scope is `*`. This means that +any jobs can have this variable regardless of whether an environment is defined. For example, if the environment scope is `production`, then only the jobs having the environment `production` defined would have this specific variable. @@ -1057,7 +1062,7 @@ environment's operational health. ## Limitations In the `environment: name`, you are limited to only the [predefined environment variables](../variables/predefined_variables.md). -Re-using variables defined inside `script` as part of the environment name will not work. +Re-using variables defined inside `script` as part of the environment name doesn't work. ## Further reading @@ -1066,7 +1071,7 @@ Below are some links you may find interesting: - [The `.gitlab-ci.yml` definition of environments](../yaml/README.md#environment) - [A blog post on Deployments & Environments](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/) - [Review Apps - Use dynamic environments to deploy your code for every branch](../review_apps/index.md) -- [Deploy Boards for your applications running on Kubernetes](../../user/project/deploy_boards.md) **(PREMIUM)** +- [Deploy Boards for your applications running on Kubernetes](../../user/project/deploy_boards.md) <!-- ## Troubleshooting diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md index 94f9aac51d6..0e4ad1df65f 100644 --- a/doc/ci/environments/protected_environments.md +++ b/doc/ci/environments/protected_environments.md @@ -36,14 +36,14 @@ To protect an environment: 1. In the **Allowed to Deploy** dropdown menu, select the role, users, or groups you want to give deploy access to. Keep in mind that: - There are two roles to choose from: - - **Maintainers**: will allow access to all maintainers in the project. - - **Developers**: will allow access to all maintainers and all developers in the project. + - **Maintainers**: Allows access to all maintainers in the project. + - **Developers**: Allows access to all maintainers and all developers in the project. - You can only select groups that are already associated with the project. - - Only users that have at least Developer permission level will appear in + - Only users that have at least the Developer permission level appear in the **Allowed to Deploy** dropdown menu. 1. Click the **Protect** button. -The protected environment will now appear in the list of protected environments. +The protected environment now appears in the list of protected environments. ### Use the API to protect an environment @@ -79,7 +79,7 @@ Alternatively, you can use the API to protect an environment: 1. Use the API to add a user to the group as a reporter: ```shell - $ curl --request POST --header "PRIVATE-TOKEN: xxxxxxxxxxxx" --data "user_id=3222377&access_level=20" "https://gitlab.com/api/v4/groups/9899826/members" + $ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "user_id=3222377&access_level=20" "https://gitlab.com/api/v4/groups/9899826/members" {"id":3222377,"name":"Sean Carroll","username":"sfcarroll","state":"active","avatar_url":"https://assets.gitlab-static.net/uploads/-/system/user/avatar/3222377/avatar.png","web_url":"https://gitlab.com/sfcarroll","access_level":20,"created_at":"2020-10-26T17:37:50.309Z","expires_at":null} ``` @@ -87,7 +87,7 @@ Alternatively, you can use the API to protect an environment: 1. Use the API to add the group to the project as a reporter: ```shell - $ curl --request POST --header "PRIVATE-TOKEN: xxxxxxxxxxxx" --request POST "https://gitlab.com/api/v4/projects/22034114/share?group_id=9899826&group_access=20" + $ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --request POST "https://gitlab.com/api/v4/projects/22034114/share?group_id=9899826&group_access=20" {"id":1233335,"project_id":22034114,"group_id":9899826,"group_access":20,"expires_at":null} ``` @@ -95,7 +95,7 @@ Alternatively, you can use the API to protect an environment: 1. Use the API to add the group with protected environment access: ```shell - curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' --header "PRIVATE-TOKEN: xxxxxxxxxxx" "https://gitlab.com/api/v4/projects/22034114/protected_environments" + curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.com/api/v4/projects/22034114/protected_environments" ``` The group now has access and can be seen in the UI. diff --git a/doc/ci/examples/README.md b/doc/ci/examples/README.md index e728941dd9d..9fa0bb080ac 100644 --- a/doc/ci/examples/README.md +++ b/doc/ci/examples/README.md @@ -20,32 +20,31 @@ Examples are available in several forms. As a collection of: ## CI/CD examples -The following table lists examples with step-by-step tutorials that are contained in this section. +The following table lists examples with step-by-step tutorials that are contained in this section: -| Use case | Resource | -|:------------------------------|:---------------------------------------------------------------------------------------------------------------------------| +| Use case | Resource | +|:------------------------------|:---------| | Browser performance testing | [Browser Performance Testing with the Sitespeed.io container](../../user/project/merge_requests/browser_performance_testing.md). | -| Load performance testing | [Load Performance Testing with the k6 container](../../user/project/merge_requests/load_performance_testing.md). | -| Clojure | [Test a Clojure application with GitLab CI/CD](test-clojure-application.md). | -| Deployment with Dpl | [Using `dpl` as deployment tool](deployment/README.md). | -| Elixir | [Testing a Phoenix application with GitLab CI/CD](test_phoenix_app_with_gitlab_ci_cd/index.md). | -| End-to-end testing | [End-to-end testing with GitLab CI/CD and WebdriverIO](end_to_end_testing_webdriverio/index.md). | -| Game development | [DevOps and Game Dev with GitLab CI/CD](devops_and_game_dev_with_gitlab_ci_cd/index.md). | +| Clojure | [Test a Clojure application with GitLab CI/CD](test-clojure-application.md). | +| Deployment with Dpl | [Using `dpl` as deployment tool](deployment/README.md). | | GitLab Pages | See the [GitLab Pages](../../user/project/pages/index.md) documentation for a complete example of deploying a static site. | -| Java with Spring Boot | [Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD](deploy_spring_boot_to_cloud_foundry/index.md). | -| Java with Maven | [How to deploy Maven projects to Artifactory with GitLab CI/CD](artifactory_and_gitlab/index.md). | -| PHP with PHPunit, atoum | [Testing PHP projects](php.md). | -| PHP with NPM, SCP | [Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD](deployment/composer-npm-deploy.md). | -| PHP with Laravel, Envoy | [Test and deploy Laravel applications with GitLab CI/CD and Envoy](laravel_with_gitlab_and_envoy/index.md). | -| Python on Heroku | [Test and deploy a Python application with GitLab CI/CD](test-and-deploy-python-application-to-heroku.md). | -| Ruby on Heroku | [Test and deploy a Ruby application with GitLab CI/CD](test-and-deploy-ruby-application-to-heroku.md). | -| Scala on Heroku | [Test and deploy a Scala application to Heroku](test-scala-application.md). | +| End-to-end testing | [End-to-end testing with GitLab CI/CD and WebdriverIO](end_to_end_testing_webdriverio/index.md). | +| Game development | [DevOps and Game Dev with GitLab CI/CD](devops_and_game_dev_with_gitlab_ci_cd/index.md). | +| Java with Maven | [How to deploy Maven projects to Artifactory with GitLab CI/CD](artifactory_and_gitlab/index.md). | +| Java with Spring Boot | [Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD](deploy_spring_boot_to_cloud_foundry/index.md). | +| Load performance testing | [Load Performance Testing with the k6 container](../../user/project/merge_requests/load_performance_testing.md). | +| Multi project pipeline | [Build, test deploy using multi project pipeline](https://gitlab.com/gitlab-examples/upstream-project). | +| NPM with semantic-release | [Publish NPM packages to the GitLab Package Registry using semantic-release](semantic-release.md). | +| PHP with Laravel, Envoy | [Test and deploy Laravel applications with GitLab CI/CD and Envoy](laravel_with_gitlab_and_envoy/index.md). | +| PHP with NPM, SCP | [Running Composer and NPM scripts with deployment via SCP in GitLab CI/CD](deployment/composer-npm-deploy.md). | +| PHP with PHPunit, atoum | [Testing PHP projects](php.md). | | Parallel testing Ruby & JS | [GitLab CI/CD parallel jobs testing for Ruby & JavaScript projects](https://docs.knapsackpro.com/2019/how-to-run-parallel-jobs-for-rspec-tests-on-gitlab-ci-pipeline-and-speed-up-ruby-javascript-testing). | -| Secrets management with Vault | [Authenticating and Reading Secrets With Hashicorp Vault](authenticating-with-hashicorp-vault/index.md). | -| Multi project pipeline | [Build, test deploy using multi project pipeline](https://gitlab.com/gitlab-examples/upstream-project). | -| NPM with semantic-release | [Publish NPM packages to the GitLab Package Registry using semantic-release](semantic-release.md). | +| Python on Heroku | [Test and deploy a Python application with GitLab CI/CD](test-and-deploy-python-application-to-heroku.md). | +| Ruby on Heroku | [Test and deploy a Ruby application with GitLab CI/CD](test-and-deploy-ruby-application-to-heroku.md). | +| Scala on Heroku | [Test and deploy a Scala application to Heroku](test-scala-application.md). | +| Secrets management with Vault | [Authenticating and Reading Secrets With Hashicorp Vault](authenticating-with-hashicorp-vault/index.md). | -### Contributing examples +### How to contributing examples Contributions are welcome! You can help your favorite programming language users and GitLab by sending a merge request with a guide for that language. @@ -72,6 +71,7 @@ choose one of these templates: - [dotNET (`dotNET.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/dotNET.gitlab-ci.yml) - [dotNET Core (`dotNET-Core.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/dotNET-Core.yml) - [Elixir (`Elixir.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Elixir.gitlab-ci.yml) +- [Flutter (`Flutter.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Flutter.gitlab-ci.yml) - [goLang (`Go.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Go.gitlab-ci.yml) - [Gradle (`Gradle.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Gradle.gitlab-ci.yml) - [Grails (`Grails.gitlab-ci.yml`)](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Grails.gitlab-ci.yml) diff --git a/doc/ci/examples/artifactory_and_gitlab/index.md b/doc/ci/examples/artifactory_and_gitlab/index.md index e37bdcc9407..c1df21297e3 100644 --- a/doc/ci/examples/artifactory_and_gitlab/index.md +++ b/doc/ci/examples/artifactory_and_gitlab/index.md @@ -3,9 +3,14 @@ stage: Verify group: Continuous Integration info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments disqus_identifier: 'https://docs.gitlab.com/ee/articles/artifactory_and_gitlab/index.html' +author: Fabio Busatto +author_gitlab: bikebilly type: tutorial +date: 2017-08-15 --- +<!-- vale off --> + # How to deploy Maven projects to Artifactory with GitLab CI/CD ## Introduction diff --git a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md index b7f59761889..fccc62a4ca0 100644 --- a/doc/ci/examples/authenticating-with-hashicorp-vault/index.md +++ b/doc/ci/examples/authenticating-with-hashicorp-vault/index.md @@ -19,14 +19,14 @@ To learn more, read [Using external secrets in CI](../../secrets/index.md). This tutorial assumes you are familiar with GitLab CI/CD and Vault. -To follow along, you will need: +To follow along, you must have: - An account on GitLab. - A running Vault server and access to it is required to configure authentication and create roles and policies. For HashiCorp Vaults, this can be the Open Source or Enterprise version. NOTE: -You will need to replace the `vault.example.com` URL below with the URL of your Vault server and `gitlab.example.com` with the URL of your GitLab instance. +You must replace the `vault.example.com` URL below with the URL of your Vault server, and `gitlab.example.com` with the URL of your GitLab instance. ## How it works @@ -47,6 +47,7 @@ The JWT's payload looks like this: "project_id": "22", # "project_path": "mygroup/myproject", # "user_id": "42", # Id of the user executing the job + "user_login": "myuser" # GitLab @username "user_email": "myuser@example.com", # Email of the user executing the job "pipeline_id": "1212", # "job_id": "1212", # @@ -56,7 +57,7 @@ The JWT's payload looks like this: } ``` -The JWT is encoded by using RS256 and signed with a dedicated private key. The expire time for the token will be set to job's timeout, if specified, or 5 minutes if it is not. The key used to sign this token may change without any notice. In such case retrying the job will generate new JWT using the current signing key. +The JWT is encoded by using RS256 and signed with a dedicated private key. The expire time for the token is set to job's timeout, if specified, or 5 minutes if it is not. The key used to sign this token may change without any notice. In such case retrying the job generates new JWT using the current signing key. You can use this JWT and your instance's JWKS endpoint (`https://gitlab.example.com/-/jwks`) to authenticate with a Vault server that is configured to allow the JWT Authentication method for authentication. @@ -110,7 +111,7 @@ EOF Success! Uploaded policy: myproject-production ``` -You'll also need roles that will link the JWT with these policies. +You also need roles that link the JWT with these policies. One for staging named `myproject-staging`: @@ -150,7 +151,7 @@ $ vault write auth/jwt/role/myproject-production - <<EOF EOF ``` -This example uses [bound_claims](https://www.vaultproject.io/api/auth/jwt#bound_claims) to specify that only a JWT with matching values for the specified claims will be allowed to authenticate. +This example uses [bound_claims](https://www.vaultproject.io/api/auth/jwt#bound_claims) to specify that only a JWT with matching values for the specified claims is allowed to authenticate. Combined with [protected branches](../../../user/project/protected_branches.md), you can restrict who is able to authenticate and read the secrets. @@ -158,7 +159,7 @@ Combined with [protected branches](../../../user/project/protected_branches.md), [user_claim](https://www.vaultproject.io/api/auth/jwt#user_claim) specifies the name for the Identity alias created by Vault upon a successful login. -[bound_claims_type](https://www.vaultproject.io/api-docs/auth/jwt#bound_claims_type) configures the interpretation of the `bound_claims` values. If set to `glob`, the values will be interpreted as globs, with `*` matching any number of characters. +[bound_claims_type](https://www.vaultproject.io/api-docs/auth/jwt#bound_claims_type) configures the interpretation of the `bound_claims` values. If set to `glob`, the values are interpreted as globs, with `*` matching any number of characters. For the full list of options, see Vault's [Create Role documentation](https://www.vaultproject.io/api/auth/jwt#create-role). @@ -177,7 +178,7 @@ $ vault write auth/jwt/config \ For the full list of available configuration options, see Vault's [API documentation](https://www.vaultproject.io/api/auth/jwt#configure). -The following job, when run for the `master` branch, will be able to read secrets under `secret/myproject/staging/`, but not the secrets under `secret/myproject/production/`: +The following job, when run for the `master` branch, is able to read secrets under `secret/myproject/staging/`, but not the secrets under `secret/myproject/production/`: ```yaml read_secrets: @@ -201,7 +202,7 @@ read_secrets: ![read_secrets staging](img/vault-read-secrets-staging.png) -The following job will be able to authenticate using the `myproject-production` role and read secrets under `/secret/myproject/production/`: +The following job is able to authenticate using the `myproject-production` role and read secrets under `/secret/myproject/production/`: ```yaml read_secrets: diff --git a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md index f4f3bf306ef..9c145677f6e 100644 --- a/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md +++ b/doc/ci/examples/deploy_spring_boot_to_cloud_foundry/index.md @@ -2,18 +2,23 @@ stage: Release group: Release info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +author: Dylan Griffith +author_gitlab: DylanGriffith type: tutorial +date: 2018-06-07 +description: "Continuous Deployment of a Spring Boot application to Cloud Foundry with GitLab CI/CD" --- +<!-- vale off --> + # Deploy a Spring Boot application to Cloud Foundry with GitLab CI/CD ## Introduction -In this article, we'll demonstrate how to deploy a [Spring -Boot](https://projects.spring.io/spring-boot/) application to [Cloud -Foundry (CF)](https://www.cloudfoundry.org/) with GitLab CI/CD using the [Continuous -Deployment](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-deployment) -method. +This article demonstrates how to use the [Continuous Deployment](https://about.gitlab.com/blog/2016/08/05/continuous-integration-delivery-and-deployment-with-gitlab/#continuous-deployment) +method to deploy a [Spring Boot](https://projects.spring.io/spring-boot/) application to +[Cloud Foundry (CF)](https://www.cloudfoundry.org/) +with GitLab CI/CD. All the code for this project can be found in this [GitLab repository](https://gitlab.com/gitlab-examples/spring-gitlab-cf-deploy-demo). @@ -25,17 +30,16 @@ using GitLab CI/CD, read through the blog post [Continuous Delivery of a Spring This tutorial assumes you are familiar with Java, GitLab, Cloud Foundry, and GitLab CI/CD. -To follow along, you will need: +To follow along, you need: - An account on [Pivotal Web Services (PWS)](https://run.pivotal.io/) or any other Cloud Foundry (CF) instance. - An account on GitLab. NOTE: -You will need to replace the `api.run.pivotal.io` URL in the all below -commands with the [API -URL](https://docs.cloudfoundry.org/running/cf-api-endpoint.html) of your CF -instance if you're not deploying to PWS. +If you're not deploying to PWS, you must replace the `api.run.pivotal.io` URL in all the below +commands with the [API URL](https://docs.cloudfoundry.org/running/cf-api-endpoint.html) +of your CF instance. ## Create your project @@ -46,9 +50,9 @@ GitLab when creating a new project: ## Configure the deployment to Cloud Foundry -To deploy to Cloud Foundry we need to add a `manifest.yml` file. This -is the configuration for the CF CLI we will use to deploy the application. We -will create this in the root directory of our project with the following +To deploy to Cloud Foundry you must add a `manifest.yml` file. This +is the configuration for the CF CLI you must use to deploy the application. +Create this in the root directory of your project with the following content: ```yaml @@ -62,12 +66,12 @@ applications: ## Configure GitLab CI/CD to deploy your application -Now we need to add the GitLab CI/CD configuration file -([`.gitlab-ci.yml`](../../yaml/README.md)) to our -project's root. This is how GitLab figures out what commands need to be run whenever -code is pushed to our repository. We will add the following `.gitlab-ci.yml` -file to the root directory of the repository, GitLab will detect it -automatically and run the steps defined once we push our code: +Now you must add the GitLab CI/CD configuration file +([`.gitlab-ci.yml`](../../yaml/README.md)) +to your project's root. This is how GitLab figures out what commands must run whenever +code is pushed to your repository. Add the following `.gitlab-ci.yml` +file to the root directory of the repository. GitLab detects it +automatically and runs the defined steps once you push your code: ```yaml image: java:8 @@ -96,15 +100,13 @@ production: - master ``` -We've used the `java:8` [Docker -image](../../docker/using_docker_images.md) to build -our application as it provides the up-to-date Java 8 JDK on [Docker -Hub](https://hub.docker.com/). We've also added the [`only` -clause](../../yaml/README.md#onlyexcept-basic) -to ensure our deployments only happen when we push to the master branch. +This uses the `java:8` [Docker image](../../docker/using_docker_images.md) +to build your application, as it provides the up-to-date Java 8 JDK on [Docker Hub](https://hub.docker.com/). +You also added the [`only` clause](../../yaml/README.md#onlyexcept-basic) +to ensure your deployments only happen when you push to the master branch. Because the steps defined in `.gitlab-ci.yml` require credentials to sign in to -CF, you'll need to add your CF credentials as +CF, you must add your CF credentials as [environment variables](../../variables/README.md#predefined-environment-variables) in GitLab CI/CD. To set the environment variables, navigate to your project's **Settings > CI/CD**, and then expand **Variables**. Name the variables @@ -122,8 +124,8 @@ your application and add its credentials to GitLab instead of using a developer's credentials. To start a manual deployment in GitLab go to **CI/CD > Pipelines** then click -on **Run Pipeline**. After the app is finished deploying, it will display the -URL of your application in the logs for the `production` job like: +**Run Pipeline**. After the app is finished deploying, it displays the +URL of your application in the logs for the `production` job: ```shell requested state: started diff --git a/doc/ci/examples/deployment/README.md b/doc/ci/examples/deployment/README.md index 386512af38b..958093364af 100644 --- a/doc/ci/examples/deployment/README.md +++ b/doc/ci/examples/deployment/README.md @@ -55,10 +55,10 @@ To use different provider take a look at long list of [Supported Providers](http ## Using Dpl with Docker -In most cases, you will have configured [GitLab Runner](https://docs.gitlab.com/runner/) to use your server's shell commands. +In most cases, you configured [GitLab Runner](https://docs.gitlab.com/runner/) to use your server's shell commands. This means that all commands are run in the context of local user (e.g. `gitlab_runner` or `gitlab_ci_multi_runner`). It also means that most probably in your Docker container you don't have the Ruby runtime installed. -You will have to install it: +You must install it: ```yaml staging: @@ -115,7 +115,7 @@ We also use two secure variables: ## Storing API keys -Secure Variables can added by going to your project's +To add secure variables, navigate to your project's **Settings > CI / CD > Variables**. The variables that are defined in the project settings are sent along with the build script to the runner. The secure variables are stored out of the repository. Never store secrets in diff --git a/doc/ci/examples/deployment/composer-npm-deploy.md b/doc/ci/examples/deployment/composer-npm-deploy.md index 24990264f19..6bc96ae6c30 100644 --- a/doc/ci/examples/deployment/composer-npm-deploy.md +++ b/doc/ci/examples/deployment/composer-npm-deploy.md @@ -9,13 +9,13 @@ type: tutorial This guide covers the building of dependencies of a PHP project while compiling assets via an NPM script using [GitLab CI/CD](../../README.md). -While it is possible to create your own image with custom PHP and Node.js versions, for brevity, we will use an existing [Docker image](https://hub.docker.com/r/tetraweb/php/) that contains both PHP and Node.js installed. +While it is possible to create your own image with custom PHP and Node.js versions, for brevity we use an existing [Docker image](https://hub.docker.com/r/tetraweb/php/) that contains both PHP and Node.js installed. ```yaml image: tetraweb/php ``` -The next step is to install zip/unzip packages and make composer available. We will place these in the `before_script` section: +The next step is to install zip/unzip packages and make composer available. We place these in the `before_script` section: ```yaml before_script: @@ -26,7 +26,7 @@ before_script: - php -r "unlink('composer-setup.php');" ``` -This will make sure we have all requirements ready. Next, we want to run `composer install` to fetch all PHP dependencies and `npm install` to load Node.js packages, then run the `npm` script. We need to append them into `before_script` section: +This makes sure we have all requirements ready. Next, run `composer install` to fetch all PHP dependencies and `npm install` to load Node.js packages. Then run the `npm` script. We need to append them into `before_script` section: ```yaml before_script: @@ -43,19 +43,19 @@ In this particular case, the `npm deploy` script is a Gulp script that does the 1. Copy various assets (images, fonts) around 1. Replace some strings -All these operations will put all files into a `build` folder, which is ready to be deployed to a live server. +All these operations put all files into a `build` folder, which is ready to be deployed to a live server. ## How to transfer files to a live server -You have multiple options: rsync, SCP, SFTP, and so on. For now, we will use SCP. +You have multiple options: rsync, SCP, SFTP, and so on. For now, use SCP. -To make this work, you need to add a GitLab CI/CD Variable (accessible on `gitlab.example/your-project-name/variables`). That variable will be called `STAGING_PRIVATE_KEY` and it's the **private** SSH key of your server. +To make this work, you must add a GitLab CI/CD Variable (accessible on `gitlab.example/your-project-name/variables`). Name this variable `STAGING_PRIVATE_KEY` and set it to the **private** SSH key of your server. ### Security tip Create a user that has access **only** to the folder that needs to be updated. -After you create that variable, you need to make sure that key will be added to the Docker container on run: +After you create that variable, make sure that key is added to the Docker container on run: ```yaml before_script: @@ -71,7 +71,7 @@ In order, this means that: 1. We check if the `ssh-agent` is available and we install it if it's not. 1. We create the `~/.ssh` folder. 1. We make sure we're running bash. -1. We disable host checking (we don't ask for user accept when we first connect to a server and since every job will equal a first connect, we kind of need this). +1. We disable host checking (we don't ask for user accept when we first connect to a server, and since every job equals a first connect, we need this). And this is basically all you need in the `before_script` section. @@ -96,14 +96,14 @@ stage_deploy: Here's the breakdown: -1. `only:dev` means that this build will run only when something is pushed to the `dev` branch. You can remove this block completely and have everything be ran on every push (but probably this is something you don't want) -1. `ssh-add ...` we will add that private key you added on the web UI to the Docker container -1. We will connect via `ssh` and create a new `_tmp` folder -1. We will connect via `scp` and upload the `build` folder (which was generated by a `npm` script) to our previously created `_tmp` folder -1. We will connect again via `ssh` and move the `live` folder to an `_old` folder, then move `_tmp` to `live`. -1. We connect to SSH and remove the `_old` folder +1. `only:dev` means that this build runs only when something is pushed to the `dev` branch. You can remove this block completely and have everything run on every push (but probably this is something you don't want). +1. `ssh-add ...` we add that private key you added on the web UI to the Docker container. +1. We connect via `ssh` and create a new `_tmp` folder. +1. We connect via `scp` and upload the `build` folder (which was generated by a `npm` script) to our previously created `_tmp` folder. +1. We connect again via `ssh` and move the `live` folder to an `_old` folder, then move `_tmp` to `live`. +1. We connect to SSH and remove the `_old` folder. -What's the deal with the artifacts? We just tell GitLab CI/CD to keep the `build` directory (later on, you can download that as needed). +What's the deal with the artifacts? We tell GitLab CI/CD to keep the `build` directory (later on, you can download that as needed). ### Why we do it this way @@ -114,7 +114,7 @@ If you're using this only for stage server, you could do this in two steps: - scp -P22 -r build/* server_user@server_host:htdocs/wp-content/themes/live ``` -The problem is that there will be a small period of time when you won't have the app on your server. +The problem is that there's a small period of time when you don't have the app on your server. Therefore, for a production environment we use additional steps to ensure that at any given time, a functional app is in place. @@ -122,13 +122,13 @@ Therefore, for a production environment we use additional steps to ensure that a Since this was a WordPress project, I gave real life code snippets. Some further ideas you can pursue: -- Having a slightly different script for `master` branch will allow you to deploy to a production server from that branch and to a stage server from any other branches. +- Having a slightly different script for `master` branch allows you to deploy to a production server from that branch and to a stage server from any other branches. - Instead of pushing it live, you can push it to WordPress official repository (with creating a SVN commit, etc.). - You could generate i18n text domains on the fly. --- -Our final `.gitlab-ci.yml` will look like this: +Our final `.gitlab-ci.yml` looks like this: ```yaml image: tetraweb/php diff --git a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md index 7abdcf1f9be..298ffff568a 100644 --- a/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md +++ b/doc/ci/examples/devops_and_game_dev_with_gitlab_ci_cd/index.md @@ -2,9 +2,14 @@ stage: Verify group: Continuous Integration info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +author: Ryan Hall +author_gitlab: blitzgren type: tutorial +date: 2018-03-07 --- +<!-- vale off --> + # DevOps and Game Dev with GitLab CI/CD With advances in WebGL and WebSockets, browsers are extremely viable as game development diff --git a/doc/ci/examples/end_to_end_testing_webdriverio/index.md b/doc/ci/examples/end_to_end_testing_webdriverio/index.md index 96183b040a2..4521c2ed52e 100644 --- a/doc/ci/examples/end_to_end_testing_webdriverio/index.md +++ b/doc/ci/examples/end_to_end_testing_webdriverio/index.md @@ -2,9 +2,15 @@ stage: Verify group: Testing info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +author: Vincent Tunru +author_gitlab: Vinnl type: tutorial +date: 2019-02-18 +description: 'Confidence checking your entire app every time a new feature is added can quickly become repetitive. Learn how to automate it with GitLab CI/CD.' --- +<!-- vale off --> + # End-to-end testing with GitLab CI/CD and WebdriverIO [Review Apps](../../review_apps/index.md) are great: for every merge request diff --git a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md index 490fb857942..c6ddeefb916 100644 --- a/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md +++ b/doc/ci/examples/laravel_with_gitlab_and_envoy/index.md @@ -2,9 +2,15 @@ stage: Verify group: Continuous Integration info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +disqus_identifier: 'https://docs.gitlab.com/ee/articles/laravel_with_gitlab_and_envoy/index.html' +author: Mehran Rasulian +author_gitlab: mehranrasulian type: tutorial +date: 2017-08-31 --- +<!-- vale off --> + # Test and deploy Laravel applications with GitLab CI/CD and Envoy ## Introduction diff --git a/doc/ci/examples/semantic-release.md b/doc/ci/examples/semantic-release.md index 70d29b739b1..037faaf66a2 100644 --- a/doc/ci/examples/semantic-release.md +++ b/doc/ci/examples/semantic-release.md @@ -35,7 +35,7 @@ You can also view or fork the complete [example source](https://gitlab.com/gitla } ``` -1. Update the `files` key with glob pattern(s) that selects all files that should be included in the published module. More information about `files` can be found [in NPM's documentation](https://docs.npmjs.com/cli/v6/configuring-npm/package-json#files). +1. Update the `files` key with glob pattern(s) that selects all files that should be included in the published module. More information about `files` can be found [in NPM's documentation](https://docs.npmjs.com/cli/v6/configuring-npm/package-json/#files). 1. Add a `.gitignore` file to the project to avoid committing `node_modules`: diff --git a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md index 089d72852bb..1204a1ae837 100644 --- a/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md +++ b/doc/ci/examples/test-and-deploy-ruby-application-to-heroku.md @@ -28,16 +28,16 @@ test: staging: stage: deploy script: - - gem install dpl - - dpl --provider=heroku --app=gitlab-ci-ruby-test-staging --api-key=$HEROKU_STAGING_API_KEY + - gem install dpl --pre + - dpl heroku api --app=gitlab-ci-ruby-test-staging --api-key=$HEROKU_STAGING_API_KEY only: - master production: stage: deploy script: - - gem install dpl - - dpl --provider=heroku --app=gitlab-ci-ruby-test-prod --api-key=$HEROKU_PRODUCTION_API_KEY + - gem install dpl --pre + - dpl heroku api --app=gitlab-ci-ruby-test-prod --api-key=$HEROKU_PRODUCTION_API_KEY only: - tags ``` @@ -50,7 +50,7 @@ This project has three jobs: ## Store API keys -You'll need to create two variables in your project's **Settings > CI/CD > Environment variables**: +You'll need to create two variables in your project's **Settings > CI/CD > Environment variables** and do not check **Protect variable** and **Mask variable**: - `HEROKU_STAGING_API_KEY` - Heroku API key used to deploy staging app. - `HEROKU_PRODUCTION_API_KEY` - Heroku API key used to deploy production app. diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-new.png b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-new.png Binary files differdeleted file mode 100644 index 04d3dc40fa5..00000000000 --- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-new.png +++ /dev/null diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-server.png b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-server.png Binary files differdeleted file mode 100644 index 63812b41c2c..00000000000 --- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/mix-phoenix-server.png +++ /dev/null diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/pipelines.png b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/pipelines.png Binary files differdeleted file mode 100644 index c0daa1a6a91..00000000000 --- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/pipelines.png +++ /dev/null diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/select_template_v12_6.png b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/select_template_v12_6.png Binary files differdeleted file mode 100644 index c8c5e152a13..00000000000 --- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/select_template_v12_6.png +++ /dev/null diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/set_up_ci_v12_6.png b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/set_up_ci_v12_6.png Binary files differdeleted file mode 100644 index fafabb27bac..00000000000 --- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/img/set_up_ci_v12_6.png +++ /dev/null diff --git a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md index 90f04fb3615..057b6ec126f 100644 --- a/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md +++ b/doc/ci/examples/test_phoenix_app_with_gitlab_ci_cd/index.md @@ -1,397 +1,8 @@ --- -stage: Verify -group: Continuous Integration -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -type: tutorial +redirect_to: '../README.md' --- -# Testing a Phoenix application with GitLab CI/CD +This example is no longer available. [View other examples](../README.md). -[Phoenix](https://www.phoenixframework.org/) is a web development framework written in [Elixir](https://elixir-lang.org), which is a -functional language designed for productivity and maintainability that runs on the -[Erlang VM](https://www.erlang.org). Erlang VM is really fast and can handle very large numbers of -simultaneous users. - -That's why we're hearing so much about Phoenix today. - -In this tutorial, we'll teach you how to set up [GitLab CI/CD](../../README.md) to build and test a Phoenix -application. - -The tutorial assumes that you know how to create a Phoenix app, run tests locally, and how to work with Git -and the GitLab UI. - -## Introduction - -### What is Phoenix? - -[Phoenix](https://www.phoenixframework.org/) is a web development framework written in [Elixir](https://elixir-lang.org). It's useful - for building fast, reliable, and high-performance applications, as it uses [Erlang VM](https://www.erlang.org). - -Many components and concepts are similar to Ruby on Rails or Python's Django. High developer -productivity and high application performance are only a few advantages on learning how to use it. -Working on the MVC pattern, it's was designed to be modular and flexible. Easy to maintain a growing -app is a plus. - -Phoenix can run in any OS where Erlang is supported: - -- Ubuntu -- CentOS -- Mac OS X -- Debian -- Windows -- Fedora -- Raspberry Pi OS - -Check the [Phoenix learning guide](https://hexdocs.pm/phoenix/overview.html) for more information. - -### What is Elixir? - -[Elixir](https://elixir-lang.org) is a dynamic, functional language created to use all the maturity of Erlang -(30 years old!) in these days, in an easy way. It has similarities with Ruby, specially on syntax, -so Ruby developers are quite excited with the rapid growing of Elixir. A full-stack Ruby developer -can learn how to use Elixir and Phoenix in just a few weeks! - -In Elixir we have a command called `mix`, which is a helper to create projects, testing, run -migrations and [much more](https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix). We'll use it later on in this tutorial. - -Check the [Elixir documentation](https://elixir-lang.org/getting-started/introduction) for more information. - -## Requirements - -To follow this tutorial, you'll need to have installed: - -- Elixir [installation instructions](https://elixir-lang.org/install) -- Phoenix Framework [installation instructions](https://hexdocs.pm/phoenix/installation.html) -- PostgreSQL (if you need to use MySQL server, check [Phoenix instructions](https://hexdocs.pm/phoenix/ecto.html#using-mysql)) - -### Create a new Phoenix project - -Open your terminal and go to the directory you wish to create your project. -You don't need to create an empty directory for the project's files, because the `mix` command will -do it for us. - -When we call `mix` command, we'll pass two arguments: - -- The task we want it to run: `phoenix.new` -- And the parameter `phoenix.new` requires, which is the name of the new project. In this case, - we're calling it `hello_gitlab_ci`, but you're free to set your own name: - -```shell -mix phoenix.new hello_gitlab_ci -``` - -When asked, answer `Y` to fetch and install dependencies. - -If everything went fine, you'll get an output like this: - -![mix phoenix.new](img/mix-phoenix-new.png) - -Now, our project is located inside the directory with the same name we pass to `mix` command, for -example, `~/GitLab/hello_gitlab_ci`. -If we take a look at the directory, we'll see the Phoenix files and the dependencies needed to run. - -### Initialize the PostgreSQL database - -By default, Phoenix requires a PostgreSQL database to store whatever we need to store in our app. In -this case, we'll only create an empty database. - -First, we need to navigate to our recently created project's directory, and then execute again -`mix`. This time, `mix` will receive the parameter `ecto.create`, which is the task to create our -new database. [Ecto](https://hexdocs.pm/ecto/Ecto.html) is the database wrapper for Elixir. - -When we do run `mix` the first time after creating our project, it will compile our files to -bytecode, which will be interpreted by Erlang VM. In the next times, it will only compile our -changes. - -Run the commands below to create our empty database: - -```shell -cd hello_gitlab_ci -mix ecto.create -``` - -We expect to see this output at the end of the command: - -```plaintext -Generated hello_gitlab_ci app -The database for HelloGitlabCi.Repo has been created -``` - -Phoenix assumes that our PostgreSQL database will have a `postgres` user account with the correct -permissions and a password of `postgres`. If it's not your case, check -[Ecto's instructions](https://hexdocs.pm/ecto/Ecto.html#module-repositories). - -### Start Phoenix server - -Now, it's time to see if everything we did until now went well. We'll call `mix` again, this time -with `phoenix.server` parameter, which will start Phoenix's HTTP Server. - -```shell -mix phoenix.server -``` - -This will be the output to this command: - -```plaintext -[info] Running HelloGitlabCi.Endpoint with Cowboy using http://localhost:4000 -23 May 11:44:35 - info: compiling -23 May 11:44:37 - info: compiled 6 files into 2 files, copied 3 in 9.8 sec -``` - -Now, we have our app running locally. We can preview it directly on our browser. Let's open -[`localhost:4000`](http://localhost:4000) to see our Phoenix Framework welcome page. If the link do -not work, open [`127.0.0.1:4000`](http://127.0.0.1:4000) instead and later, configure your OS to -point `localhost` to `127.0.0.1`. - -![mix phoenix.server](img/mix-phoenix-server.png) - -Great, now we have a local Phoenix Server running our app. - -Locally, our application is running in an [`iex`](https://elixir-lang.org/getting-started/introduction.html#interactive-mode) session, which stands for Interactive Elixir. -In this interactive mode, we can type any Elixir expression and get its result. To exit `iex`, we -need to press `Ctrl+C` twice. So, when we need to stop the Phoenix server, we have to hit `Ctrl+C` -twice. - -## Introducing GitLab CI/CD - -With GitLab, we can manage our development workflow, improve our productivity, track issues, -perform code review, and much more from a single platform. With GitLab CI/CD, we can be much more -productive, because every time we, or our co-workers push any code, GitLab CI/CD will build and -test the changes, telling us in real time if anything goes wrong. - -Certainly, when our application starts to grow, we'll need more developers working on the same -project and this process of building and testing can easily become a mess without proper management. -That's also why GitLab CI/CD is so important to our application. Every time someone pushes its code to -GitLab, we'll quickly know if their changes broke something or not. We don't need to stop everything -we're doing to test manually and locally every change our team does. - -Let's see this in practice. - -## Adjusting Phoenix configuration - -Now, we need to adjust our Phoenix configuration before configuring GitLab CI/CD. -There is a directory (`config`) in your Phoenix project that contains a configuration file for every -environment it can run. Since we will work with a single environment, we'll edit just the test -configuration file (`test.exs`). - -But, why do we need to adjust our configuration? Well, GitLab CI/CD builds and tests our code in one -isolated virtual machine, called a [runner](../../runners/README.md), using Docker technology. In this runner, -GitLab CI/CD has access to everything our Phoenix application need to run, exactly as we have in our -`localhost`, but we have to tell GitLab CI/CD where to create and find this database using system -variables. This way, GitLab CI/CD will create our test database inside the runner, just like we do -when running our Phoenix in our `localhost`. - -- Open `hello_gitlab_ci/config/test.exs` on your favorite code editor -- Go to **Configure your database** session and edit the block to include `System.get_env`: - - ```elixir - # Configure your database - config :hello_gitlab_ci, HelloGitlabCi.Repo, - adapter: Ecto.Adapters.Postgres, - username: System.get_env("POSTGRES_USER") || "postgres", - password: System.get_env("POSTGRES_PASSWORD") || "postgres", - database: System.get_env("POSTGRES_DB") || "hello_gitlab_ci_test", - hostname: System.get_env("POSTGRES_HOST") || "localhost", - pool: Ecto.Adapters.SQL.Sandbox - ``` - - We'll need these system variables later on. - -- Create an empty file named `.gitkeep` into `hello_gitlab_ci/priv/repo/migrations` - - As our project is still fresh, we don't have any data on our database, so, the `migrations` - directory will be empty. - Without `.gitkeep`, Git will not upload this empty directory and we'll got an error when running our - test on GitLab. - - If we add a folder via the GitLab UI, GitLab itself will add the `.gitkeep` to that new dir. - -Now, let's run a local test and see if everything we did didn't break anything. - -## Testing - -Earlier, when we created our project, we ran `mix phoenix.new`. -This task created everything a Phoenix application needed, including some unit tests into -`hello_gitlab_ci/test` directory. - -Let's run a new task with `mix` to run those tests for us. This time, the parameter expected is -`test`. We can add `--trace` parameter for debugging purposes. - -In your terminal, navigate to the directory `hello_gitlab_ci` and run: - -```shell -mix test -``` - -Our expected result is this: - -```plaintext -.... - -Finished in 0.7 seconds -4 tests, 0 failures - -Randomized with seed 610000 -``` - -Our test was successful. It's time to push our files to GitLab. - -## Configuring CI/CD Pipeline - -The first step is to create a new file called `.gitlab-ci.yml` in `hello_gitlab_ci` directory of our -project. - -- The easiest way to do this is to click on **Set up CI/CD** on project's main page: - - ![Set up CI](img/set_up_ci_v12_6.png) - -- On the next screen, we can use a template with Elixir tests already included. Click on **Apply a template** and select **Elixir**: - - ![Select template](img/select_template_v12_6.png) - - This template file tells GitLab CI/CD about what we wish to do every time a new commit is made. - However, we have to adapt it slightly to run a Phoenix app. - -- The first line tells GitLab what Docker image will be used. - - Remember when we learned about runners, the isolated virtual machine where GitLab CI/CD builds and tests - our application? This virtual machine must have all dependencies to run our application. This is - where a Docker image is needed. The correct image will provide the entire system for us. - - As we are focusing on testing (not deploying), you can use the [elixir:latest](https://hub.docker.com/_/elixir) Docker image, which already has the - dependencies for running Phoenix tests installed, such as Elixir and Erlang: - - ```yaml - image: elixir:latest - ``` - -- We'll only use `postgres`, so we can delete the `mysql` and `redis` lines from the `services` section: - - ```yaml - services: - - postgres:latest - ``` - -- Now, we'll create a new section called `variables`, before the `before_script` section: - - ```yaml - variables: - POSTGRES_DB: hello_gitlab_ci_test - POSTGRES_HOST: postgres - POSTGRES_USER: postgres - POSTGRES_PASSWORD: "postgres" - MIX_ENV: "test" - ``` - - Above, we set up the values for GitLab CI/CD to authenticate into PostgreSQL, like we did in - `config/test.exs` earlier. The `POSTGRES_USER` and `POSTGRES_PASSWORD` values - are used by the `postgres` service to create a user with those credentials. - -- In the `before_script` section, we'll add some commands to prepare everything for the test: - - ```yaml - before_script: - - mix local.rebar --force - - mix local.hex --force - - mix deps.get --only test - - mix ecto.create - - mix ecto.migrate - ``` - - This ensures that [rebar3](https://rebar3.org) and [hex](https://hex.pm) are both installed - before attempting to fetch the dependencies that are required to run the tests. Next, the `postgres` db - is created and migrated with `ecto`, to ensure it's up-to-date. - -- Finally, we'll leave the `mix` section unchanged. - -Let's take a look at the updated file after the changes: - -```yaml -image: elixir:latest - -services: - - postgres:latest - -variables: - POSTGRES_DB: hello_gitlab_ci_test - POSTGRES_HOST: postgres - POSTGRES_USER: postgres - POSTGRES_PASSWORD: "postgres" - MIX_ENV: "test" - -before_script: - - mix local.rebar --force - - mix local.hex --force - - mix deps.get --only test - - mix ecto.create - - mix ecto.migrate - -mix: - script: - - mix test -``` - -For safety, we can check if we get any syntax errors before submitting this file to GitLab. Copy the -contents of `.gitlab-ci.yml` and paste it on [GitLab CI/CD Lint tool](https://gitlab.com/ci/lint). Please note that -this link will only work for logged in users. - -## Watching the build - -I don't know about you, but I love to watch that black screen being filled with compilation output. -With this, I can feel the happiness of something I made working correctly. On `localhost` it's easy -to watch our build, but on GitLab, is it possible? Yes! - -Let's go to **Pipelines** and see GitLab doing the job. Just click on **Pipelines** to find the -actual running build job. - -![Pipelines](img/pipelines.png) - -Click on build's ID to watch the entire process. If everything went as expected, we can wait for the -**Build succeeded** at the end of the process! :) - -```shell -$ mix test -.... - -Finished in 0.3 seconds -4 tests, 0 failures - -Randomized with seed 206909 -Build succeeded -``` - -If we take a look at the project's main page on the GitLab UI, we can see the status of the last -build made by GitLab CI/CD. - -Time to show the world our green build badge! Navigate to your project's **Settings > CI/CD** and -expand **General pipelines settings**. Scroll down to **Pipeline status** and copy the Markdown code -for your badge. Paste it on the top of your `README.md` file, to let people outside of our project -see if our latest code is running without errors. - -When we finish this edition, GitLab will start another build and show a **build running** badge. It -is expected, after all we just configured GitLab CI/CD to do this for every push! But you may think -"Why run build and tests for simple things like editing README.md?" and it is a good question. -For changes that don't affect your application, you can add the keyword [`[ci skip]`](../../yaml/README.md#skip-pipeline) -to commit message and the build related to that commit will be skipped. - -In the end, we finally got our pretty green build succeeded badge! By outputting the result on the -README file, it shows to whoever lands on your project's page that your code is up-to-date and -working properly. - -## Conclusion - -When we have a growing application with many developers working on it, or when we have an open -source project being watched and contributed by the community, it is really important to have our -code permanently working. GitLab CI/CD is a time saving powerful tool to help us maintain our code -organized and working. - -As we could see in this post, GitLab CI/CD is really easy to configure and use. We have [many -other reasons](https://about.gitlab.com/blog/2015/02/03/7-reasons-why-you-should-be-using-ci/) to keep -using GitLab CI/CD. The benefits to our teams will be huge! - -## References - -- [GitLab CI/CD introductory guide](https://about.gitlab.com/blog/2015/12/14/getting-started-with-gitlab-and-gitlab-ci/) -- [GitLab CI/CD full Documentation](../../README.md) -- [GitLab Runner documentation](../../runners/README.md) -- [Using Docker images documentation](../../docker/using_docker_images.md) +<!-- This redirect file can be deleted after <2021-04-05>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/ci/img/environments_available.png b/doc/ci/img/environments_available.png Binary files differdeleted file mode 100644 index 6c64e9398f7..00000000000 --- a/doc/ci/img/environments_available.png +++ /dev/null diff --git a/doc/ci/img/environments_available_13_7.png b/doc/ci/img/environments_available_13_7.png Binary files differnew file mode 100644 index 00000000000..2e1f56c5894 --- /dev/null +++ b/doc/ci/img/environments_available_13_7.png diff --git a/doc/ci/introduction/index.md b/doc/ci/introduction/index.md index 3fa427bc875..c04bcd6f549 100644 --- a/doc/ci/introduction/index.md +++ b/doc/ci/introduction/index.md @@ -147,10 +147,10 @@ according to each stage (Verify, Package, Release). - Continuous Deployment, automatically deploying your app to production. - Continuous Delivery, manually click to deploy your app to production. - Deploy static websites with [GitLab Pages](../../user/project/pages/index.md). - - Ship features to only a portion of your pods and let a percentage of your user base to visit the temporarily deployed feature with [Canary Deployments](../../user/project/canary_deployments.md). **(PREMIUM)** + - Ship features to only a portion of your pods and let a percentage of your user base to visit the temporarily deployed feature with [Canary Deployments](../../user/project/canary_deployments.md). - Deploy your features behind [Feature Flags](../../operations/feature_flags.md). - Add release notes to any Git tag with [GitLab Releases](../../user/project/releases/index.md). - - View of the current health and status of each CI environment running on Kubernetes with [Deploy Boards](../../user/project/deploy_boards.md). **(PREMIUM)** + - View of the current health and status of each CI environment running on Kubernetes with [Deploy Boards](../../user/project/deploy_boards.md). - Deploy your application to a production environment in a Kubernetes cluster with [Auto Deploy](../../topics/autodevops/stages.md#auto-deploy). With GitLab CI/CD you can also: diff --git a/doc/ci/merge_request_pipelines/img/pipeline-fork_v13_7.png b/doc/ci/merge_request_pipelines/img/pipeline-fork_v13_7.png Binary files differnew file mode 100644 index 00000000000..eb44290aa66 --- /dev/null +++ b/doc/ci/merge_request_pipelines/img/pipeline-fork_v13_7.png diff --git a/doc/ci/merge_request_pipelines/index.md b/doc/ci/merge_request_pipelines/index.md index 220032eeab1..999d15eac24 100644 --- a/doc/ci/merge_request_pipelines/index.md +++ b/doc/ci/merge_request_pipelines/index.md @@ -177,6 +177,10 @@ coming from a fork: - It's created and runs in the fork (source) project, not the parent (target) project. - It uses the fork project's CI/CD configuration and resources. +If a pipeline runs in a fork, the **fork** icon appears for the pipeline in the merge request. + +![Pipeline ran in fork](img/pipeline-fork_v13_7.png) + Sometimes parent project members want the pipeline to run in the parent project. This could be to ensure that the post-merge pipeline passes in the parent project. For example, a fork project could try to use a corrupted runner that doesn't execute diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md index 1b9bade3b76..e83789efdbf 100644 --- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md +++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/index.md @@ -50,6 +50,8 @@ To enable pipelines for merge results: - You must not be using [fast forward merges](../../../user/project/merge_requests/fast_forward_merge.md) yet. To follow progress, see [#58226](https://gitlab.com/gitlab-org/gitlab/-/issues/26996). +- Your repository must be a GitLab repository, not an + [external repository](../../ci_cd_for_external_repos/index.md). ## Enable pipelines for merged results @@ -58,7 +60,7 @@ To enable pipelines for merged results for your project: 1. [Configure your CI/CD configuration file](../index.md#configuring-pipelines-for-merge-requests) so that the pipeline or individual jobs run for merge requests. 1. Visit your project's **Settings > General** and expand **Merge requests**. -1. Check **Enable merged results pipelines.**. +1. Check **Enable merged results pipelines**. 1. Click **Save changes**. WARNING: diff --git a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md index 0b25b32b2a5..e5b9ad030d0 100644 --- a/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md +++ b/doc/ci/merge_request_pipelines/pipelines_for_merged_results/merge_trains/index.md @@ -74,6 +74,8 @@ To enable merge trains: - You must have maintainer [permissions](../../../../user/permissions.md). - You must be using [GitLab Runner](https://gitlab.com/gitlab-org/gitlab-runner) 11.9 or later. - In GitLab 12.0 and later, you need [Redis](https://redis.io/) 3.2 or later. +- Your repository must be a GitLab repository, not an + [external repository](../../../ci_cd_for_external_repos/index.md). ## Enable merge trains @@ -177,9 +179,13 @@ for more information. ### Merge Train Pipeline cannot be retried -A Merge Train pipeline cannot be retried because the merge request is dropped from the merge train upon failure. For this reason, the retry button does not appear next to the pipeline icon. +When a pipeline for merge trains fails the merge request is dropped from the train and the pipeline can't be retried. +Pipelines for merge trains run on the merged result of the changes in the merge request and +the changes from other merge requests already on the train. If the merge request is dropped from the train, +the merged result is out of date and the pipeline can't be retried. -In the case of pipeline failure, you should [re-enqueue](#add-a-merge-request-to-a-merge-train) the merge request to the merge train, which then initiates a new pipeline. +Instead, you should [add the merge request to the train](#add-a-merge-request-to-a-merge-train) +again, which triggers a new pipeline. ### Unable to add to merge train with message "The pipeline for this merge request failed." diff --git a/doc/ci/multi_project_pipelines.md b/doc/ci/multi_project_pipelines.md index 1df196182c0..006d6bda0e0 100644 --- a/doc/ci/multi_project_pipelines.md +++ b/doc/ci/multi_project_pipelines.md @@ -13,6 +13,9 @@ type: reference You can set up [GitLab CI/CD](README.md) across multiple projects, so that a pipeline in one project can trigger a pipeline in another project. +<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> +For an overview see the [Multi-project pipelines demo](https://www.youtube.com/watch?v=g_PIwBM1J84). + GitLab CI/CD is a powerful continuous integration tool that works not only per project, but also across projects with multi-project pipelines. diff --git a/doc/ci/yaml/img/ci_config_visualization_hover_v13_7.png b/doc/ci/pipeline_editor/img/ci_config_visualization_hover_v13_7.png Binary files differindex 9387fc6ccf4..9387fc6ccf4 100644 --- a/doc/ci/yaml/img/ci_config_visualization_hover_v13_7.png +++ b/doc/ci/pipeline_editor/img/ci_config_visualization_hover_v13_7.png diff --git a/doc/ci/yaml/img/ci_config_visualization_v13_7.png b/doc/ci/pipeline_editor/img/ci_config_visualization_v13_7.png Binary files differindex ef2aa6fe9e9..ef2aa6fe9e9 100644 --- a/doc/ci/yaml/img/ci_config_visualization_v13_7.png +++ b/doc/ci/pipeline_editor/img/ci_config_visualization_v13_7.png diff --git a/doc/ci/pipeline_editor/img/pipeline_editor_commit_v13_8.png b/doc/ci/pipeline_editor/img/pipeline_editor_commit_v13_8.png Binary files differnew file mode 100644 index 00000000000..cc1f666f319 --- /dev/null +++ b/doc/ci/pipeline_editor/img/pipeline_editor_commit_v13_8.png diff --git a/doc/ci/pipeline_editor/img/pipeline_editor_lint_v13_8.png b/doc/ci/pipeline_editor/img/pipeline_editor_lint_v13_8.png Binary files differnew file mode 100644 index 00000000000..28d21f71378 --- /dev/null +++ b/doc/ci/pipeline_editor/img/pipeline_editor_lint_v13_8.png diff --git a/doc/ci/pipeline_editor/img/pipeline_editor_validate_v13_8.png b/doc/ci/pipeline_editor/img/pipeline_editor_validate_v13_8.png Binary files differnew file mode 100644 index 00000000000..a4140d5220a --- /dev/null +++ b/doc/ci/pipeline_editor/img/pipeline_editor_validate_v13_8.png diff --git a/doc/ci/pipeline_editor/index.md b/doc/ci/pipeline_editor/index.md new file mode 100644 index 00000000000..61b8e289509 --- /dev/null +++ b/doc/ci/pipeline_editor/index.md @@ -0,0 +1,133 @@ +--- +stage: Verify +group: Pipeline Authoring +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +type: reference +--- + +# Pipeline Editor **(CORE)** + +> - [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/4540) in GitLab 13.8. +> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default. +> - It's enabled on GitLab.com. +> - It's not recommended for production use. +> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-pipeline-editor). **(CORE ONLY)** + +WARNING: +This feature might not be available to you. Check the **version history** note above for details. + +The pipeline editor is the primary place to edit the GitLab CI/CD configuration in +your `.gitlab-ci.yml` file. To access it, go to **CI/CD > Editor**. + +From the pipeline editor page you can: + +- [Validate](#validate-ci-configuration) your configuration syntax while editing the file. +- Do a deeper [lint](#lint-ci-configuration) of your configuration, that verifies it with any configuration + added with the [`include`](../yaml/README.md#include) keyword. +- See a [visualization](#visualize-ci-configuration) of the current configuration. +- [Commit](#commit-changes-to-ci-configuration) the changes to a specific branch. + +NOTE: +You must have already [created a CI/CD configuration file](../quick_start/README.md#create-a-gitlab-ciyml-file) +to use the editor. + +## Validate CI configuration + +As you edit your pipeline configuration, it is continually validated against the GitLab CI/CD +pipeline schema. It checks the syntax of your CI YAML configuration, and also runs +some basic logical validations. + +The result of this validation is shown at the top of the editor page. If your configuration +is invalid, a tip is shown to help you fix the problem: + +![Errors in a CI configuration validation](img/pipeline_editor_validate_v13_8.png) + +## Lint CI configuration + +To test the validity of your GitLab CI/CD configuration before committing the changes, +you can use the CI lint tool. To access it, go to **CI/CD > Editor** and select the **Lint** tab. + +This tool checks for syntax and logical errors but goes into more detail than the +automatic [validation](#validate-ci-configuration) in the editor. + +The results are updated in real-time. Any changes you make to the configuration are +reflected in the CI lint. It displays the same results as the existing [CI Lint tool](../lint.md). + +![Linting errors in a CI configuration](img/pipeline_editor_lint_v13_8.png) + +## Visualize CI configuration + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241722) in GitLab 13.5. +> - [Moved to **CI/CD > Editor**](https://gitlab.com/gitlab-org/gitlab/-/issues/263141) in GitLab 13.7. +> - It was [deployed behind a feature flag](../../user/feature_flags.md), disabled by default. +> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/290117) in GitLab 13.8. +> - It's enabled on GitLab.com. +> - It's not recommended for production use. +> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-cicd-configuration-visualization). **(CORE ONLY)** + +WARNING: +This feature might not be available to you. Check the **version history** note above for details. + +To see a visualization of your `gitlab-ci.yml` configuration, navigate to **CI/CD > Editor** +and select the `visualization` tab. The visualization shows all stages and jobs. +[`needs`](../yaml/README.md#needs) relationships are displayed as lines connecting jobs together, showing the hierarchy of execution: + +![CI configuration Visualization](img/ci_config_visualization_v13_7.png) + +Hovering on a job highlights its `needs` relationships: + +![CI configuration visualization on hover](img/ci_config_visualization_hover_v13_7.png) + +If the configuration does not have any `needs` relationships, then no lines are drawn because +each job depends only on the previous stage being completed successfully. + +### Enable or disable CI/CD configuration visualization **(CORE ONLY)** + +CI/CD configuration visualization is under development but ready for production use. +It is deployed behind a feature flag that is **enabled by default**. +[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) +can opt to disable it. + +To disable it: + +```ruby +Feature.disable(:ci_config_visualization_tab) +``` + +To enable it: + +```ruby +Feature.enable(:ci_config_visualization_tab) +``` + +## Commit changes to CI configuration + +The commit form appears at the bottom of each tab in the editor so you can commit +your changes at any time. + +When you are satisfied with your changes, add a descriptive commit message and enter +a branch. The branch field defaults to your project's default branch. + +If you enter a new branch name, the **Start a new merge request with these changes** +checkbox appears. Select it to start a new merge request after you commit the changes. + +![The commit form with a new branch](img/pipeline_editor_commit_v13_8.png) + +## Enable or disable pipeline editor **(CORE ONLY)** + +The pipeline editor is under development and not ready for production use. It is +deployed behind a feature flag that is **enabled by default**. +[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) +can disable it. + +To disable it: + +```ruby +Feature.disable(:ci_pipeline_editor_page) +``` + +To enable it: + +```ruby +Feature.enable(:ci_pipeline_editor_page) +``` diff --git a/doc/ci/pipelines/img/job_artifacts_merge_request.png b/doc/ci/pipelines/img/job_artifacts_merge_request.png Binary files differnew file mode 100644 index 00000000000..fa1ed9acbf8 --- /dev/null +++ b/doc/ci/pipelines/img/job_artifacts_merge_request.png diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md index 22e331f2de0..7920a3bf7f3 100644 --- a/doc/ci/pipelines/index.md +++ b/doc/ci/pipelines/index.md @@ -89,9 +89,9 @@ This table lists the refspecs injected for each pipeline type: | Pipeline type | Refspecs | |--------------- |---------------------------------------- | -| Pipeline for Branches | `+refs/pipelines/<id>:refs/pipelines/<id>` and `+refs/heads/<name>:refs/remotes/origin/<name>` | -| pipeline for Tags | `+refs/pipelines/<id>:refs/pipelines/<id>` and `+refs/tags/<name>:refs/tags/<name>` | -| [Pipeline for Merge Requests](../merge_request_pipelines/index.md) | `+refs/pipelines/<id>:refs/pipelines/<id>` | +| Pipeline for Branches | `+<sha>:refs/pipelines/<id>` and `+refs/heads/<name>:refs/remotes/origin/<name>` | +| pipeline for Tags | `+<sha>:refs/pipelines/<id>` and `+refs/tags/<name>:refs/tags/<name>` | +| [Pipeline for Merge Requests](../merge_request_pipelines/index.md) | `+<sha>:refs/pipelines/<id>` | The refs `refs/heads/<name>` and `refs/tags/<name>` exist in your project repository. GitLab generates the special ref `refs/pipelines/<id>` during a @@ -132,6 +132,10 @@ Pipelines can be manually executed, with predefined or manually-specified [varia You might do this if the results of a pipeline (for example, a code build) are required outside the normal operation of the pipeline. +[In GitLab 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/30101), +all global variables with descriptions defined in the `.gitlab-ci.yml` file are +displayed in the variable fields. + To execute a pipeline manually: 1. Navigate to your project's **CI/CD > Pipelines**. @@ -345,18 +349,7 @@ Stages in pipeline mini graphs are collapsible. Hover your mouse over them and c ### Pipeline success and duration charts -> - Introduced in GitLab 3.1.1 as Commit Stats, and later renamed to Pipeline Charts. -> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/38318) to CI / CD Analytics in GitLab 12.8. - -GitLab tracks the history of your pipeline successes and failures, as well as how long each pipeline ran. To view this information, go to **Analytics > CI / CD Analytics**. - -View successful pipelines: - -![Successful pipelines](img/pipelines_success_chart.png) - -View pipeline duration history: - -![Pipeline duration](img/pipelines_duration_chart.png) +Pipeline analytics are available on the [**CI/CD Analytics** page](../../user/analytics/ci_cd_analytics.md#pipeline-success-and-duration-charts). ### Pipeline badges diff --git a/doc/ci/pipelines/job_artifacts.md b/doc/ci/pipelines/job_artifacts.md index 787ee8f8573..4c77a578aa4 100644 --- a/doc/ci/pipelines/job_artifacts.md +++ b/doc/ci/pipelines/job_artifacts.md @@ -155,9 +155,10 @@ as artifacts. The collected Code Quality report uploads to GitLab as an artifact and is summarized in merge requests. -#### `artifacts:reports:sast` **(ULTIMATE)** +#### `artifacts:reports:sast` > - Introduced in GitLab 11.5. +> - Made [available in all tiers](https://gitlab.com/groups/gitlab-org/-/epics/2098) in GitLab 13.3. > - Requires GitLab Runner 11.5 and above. The `sast` report collects [SAST vulnerabilities](../../user/application_security/sast/index.md) @@ -349,6 +350,11 @@ in the GitLab UI to do this: ![Job artifacts browser button](img/job_artifacts_browser_button.png) +1. While on the details page of a merge request, you can see the download + icon for each job's artifacts on the right side of the merge request widget: + + ![Job artifacts in Merge Request](img/job_artifacts_merge_request.png) + 1. And finally, when browsing an archive you can see the download button at the top right corner: @@ -459,6 +465,23 @@ To retrieve a job artifact from a different project, you might need to use a private token to [authenticate and download](../../api/job_artifacts.md#get-job-artifacts) the artifact. +## Keep artifacts from most recent successful jobs + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/16267) in GitLab 13.0. +> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/229936) in GitLab 13.4. +> - [Made optional with a CI/CD setting](https://gitlab.com/gitlab-org/gitlab/-/issues/241026) in GitLab 13.8. + +By default, the latest artifacts from the most recent successful jobs are never deleted. +If a job is configured with [`expire_in`](../yaml/README.md#artifactsexpire_in), +its artifacts only expire if a more recent artifact exists. + +Keeping the latest artifacts can use a large amount of storage space in projects +with a lot of jobs or large artifacts. If the latest artifacts are not needed in +a project, you can disable this behavior to save space: + +1. Navigate to **Settings > CI/CD > Artifacts**. +1. Uncheck **Keep artifacts from most recent successful jobs**. + ## Troubleshooting ### Error message `No files to upload` diff --git a/doc/ci/pipelines/schedules.md b/doc/ci/pipelines/schedules.md index 35a8888381f..cddfcb754ec 100644 --- a/doc/ci/pipelines/schedules.md +++ b/doc/ci/pipelines/schedules.md @@ -67,7 +67,7 @@ To configure a job to be executed only when the pipeline has been scheduled (or the opposite), use [only and except](../yaml/README.md#onlyexcept-basic) configuration keywords. -For example: +In the example below `make world` runs in scheduled pipelines, and `make build` runs in pipelines that are not scheduled: ```yaml job:on-schedule: diff --git a/doc/ci/quick_start/README.md b/doc/ci/quick_start/README.md index 7fd88d011b3..e9c85353db3 100644 --- a/doc/ci/quick_start/README.md +++ b/doc/ci/quick_start/README.md @@ -129,7 +129,7 @@ The pipeline starts when the commit is committed. - To validate your `.gitlab-ci.yml` file, use the [CI Lint tool](../lint.md), which is available in every project. -- You can also use [CI/CD configuration visualization](../yaml/visualization.md) to +- You can also use [CI/CD configuration visualization](../pipeline_editor/index.md#visualize-ci-configuration) to view a graphical representation of your `.gitlab-ci.yml` file. - For the complete `.gitlab-ci.yml` syntax, see [the `.gitlab-ci.yml` reference topic](../yaml/README.md). diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md index 31fcfe9d6e8..3512b77e4e2 100644 --- a/doc/ci/review_apps/index.md +++ b/doc/ci/review_apps/index.md @@ -69,7 +69,7 @@ The process of configuring Review Apps is as follows: When configuring Review Apps for a project, you need to add a new job to `.gitlab-ci.yml`, as mentioned above. To facilitate this and if you are using Kubernetes, you can click -the **Enable Review Apps** button and GitLab will prompt you with a template code block that +the **Enable Review Apps** button and GitLab prompts you with a template code block that you can copy and paste into `.gitlab-ci.yml` as a starting point. To do so: 1. Go to the project your want to create a Review App job for. @@ -115,7 +115,7 @@ and faster to preview proposed modifications. Configuring Route Maps involves telling GitLab how the paths of files in your repository map to paths of pages on your website using a Route Map. -Once set, GitLab will display **View on ...** buttons, which will take you +Once set, GitLab displays **View on ...** buttons, which take you to the pages changed directly from merge requests. To set up a route map, add a file inside the repository at `.gitlab/route-map.yml`, @@ -165,15 +165,15 @@ The public path for a source path is determined by finding the first In the example above, the fact that mappings are evaluated in order of their definition is used to ensure that `source/index.html.haml` -will match `/source\/(.+?\.html).*/` instead of `/source\/(.*)/`, -and will result in a public path of `index.html`, instead of +matches `/source\/(.+?\.html).*/` instead of `/source\/(.*)/`, +and results in a public path of `index.html`, instead of `index.html.haml`. -After you have the route mapping set up, it will take effect in the following locations: +After you have the route mapping set up, it takes effect in the following locations: - In the merge request widget. The: - - **View app** button will take you to the environment URL set in `.gitlab-ci.yml`. - - Dropdown will list the first 5 matched items from the route map, but you can filter them if more + - **View app** button takes you to the environment URL set in `.gitlab-ci.yml`. + - Dropdown lists the first 5 matched items from the route map, but you can filter them if more than 5 are available. ![View app file list in merge request widget](img/view_on_mr_widget.png) @@ -221,7 +221,7 @@ To see Visual reviews in action, see the [Visual Reviews Walk through](https://y The feedback form is served through a script you add to pages in your Review App. If you have [Developer permissions](../../user/permissions.md) to the project, you can access it by clicking the **Review** button in the **Pipeline** section -of the merge request. The form modal will also show a dropdown for changed pages +of the merge request. The form modal also shows a dropdown for changed pages if [route maps](#route-maps) are configured in the project. ![review button](img/review_button.png) @@ -251,13 +251,13 @@ to replace those values at runtime when each review app is created: `CI_MERGE_REQUEST_IID` variable. `CI_MERGE_REQUEST_IID` is available only if [`only: [merge_requests]`](../merge_request_pipelines/index.md) is used and the merge request is created. -- `data-mr-url` is the URL of the GitLab instance and will be the same for all +- `data-mr-url` is the URL of the GitLab instance and is the same for all review apps. - `data-project-path` is the project's path, which can be found by `CI_PROJECT_PATH`. -- `data-require-auth` is optional for public projects but required for [private and internal ones](#authentication-for-visual-reviews). If this is set to `true`, the user will be required to enter their [personal access token](../../user/profile/personal_access_tokens.md) instead of their name and email. +- `data-require-auth` is optional for public projects but required for [private and internal ones](#authentication-for-visual-reviews). If this is set to `true`, the user is required to enter their [personal access token](../../user/profile/personal_access_tokens.md) instead of their name and email. - `id` is always `review-app-toolbar-script`, you don't need to change that. - `src` is the source of the review toolbar script, which resides in the - respective GitLab instance and will be the same for all review apps. + respective GitLab instance and is the same for all review apps. For example, in a Ruby application with code hosted on in a project GitLab.com, you would need to have this script: diff --git a/doc/ci/runners/README.md b/doc/ci/runners/README.md index c9a5f2f3899..d6ea4d83825 100644 --- a/doc/ci/runners/README.md +++ b/doc/ci/runners/README.md @@ -116,7 +116,7 @@ You can also enable shared runners for individual projects. To enable shared runners: 1. Go to the project's **Settings > CI/CD** and expand the **Runners** section. -1. Click **Allow shared runners**. +1. Select **Enable shared runners for this project**. #### Disable shared runners @@ -126,7 +126,12 @@ You must have Owner permissions for the project or group. To disable shared runners for a project: 1. Go to the project's **Settings > CI/CD** and expand the **Runners** section. -1. In the **Shared runners** area, click **Disable shared runners**. +1. In the **Shared runners** area, select **Enable shared runners for this project** so the toggle is grayed-out. + +Shared runners are automatically disabled for a project: + +- If the shared runners setting for the parent group is disabled, and +- If overriding this setting is not permitted at the project level. To disable shared runners for a group: @@ -264,6 +269,15 @@ by a project that has jobs with a long timeout (for example, one week). When not configured, runners do not override the project timeout. +On GitLab.com, you cannot override the job timeout for shared runners and must use the [project defined timeout](../pipelines/settings.md#timeout). + +To set the maximum job timeout: + +1. In a project, go to **Settings > CI/CD > Runners**. +1. Select your specific runner to edit the settings. +1. Enter a value under **Maximum job timeout**. +1. Select **Save changes**. + How this feature works: **Example 1 - Runner timeout bigger than project timeout** diff --git a/doc/ci/unit_test_reports.md b/doc/ci/unit_test_reports.md index 2505e56356d..1fec1f77bc3 100644 --- a/doc/ci/unit_test_reports.md +++ b/doc/ci/unit_test_reports.md @@ -68,36 +68,11 @@ execution time and the error output. ### Number of recent failures > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241759) in GitLab 13.7. -> - It's [deployed behind a feature flag](../user/feature_flags.md), disabled by default. -> - It's disabled on GitLab.com. -> - It's not recommended for production use. -> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-the-number-of-recent-failures). **(CORE ONLY)** - -WARNING: -This feature might not be available to you. Check the **version history** note above for details. +> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/268249) in GitLab 13.8. If a test failed in the project's default branch in the last 14 days, a message like `Failed {n} time(s) in {default_branch} in the last 14 days` is displayed for that test. -#### Enable or disable the number of recent failures **(CORE ONLY)** - -Displaying the number of failures in the last 14 days is under development and not -ready for production use. It is deployed behind a feature flag that is **disabled by default**. -[GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md) -can enable it. - -To enable it: - -```ruby -Feature.enable(:test_failure_history) -``` - -To disable it: - -```ruby -Feature.disable(:test_failure_history) -``` - ## How to set it up To enable the Unit test reports in merge requests, you need to add diff --git a/doc/ci/variables/README.md b/doc/ci/variables/README.md index f4ca51be151..5fca8e8c2b7 100644 --- a/doc/ci/variables/README.md +++ b/doc/ci/variables/README.md @@ -594,7 +594,35 @@ WARNING: Variables with multi-line values are not supported due to limitations with the Auto DevOps scripting environment. -### Override a variable by manually running a pipeline +### When you can override variables + +You can override the value of a variable when: + +1. [Manually running](#override-a-variable-by-manually-running-a-pipeline) pipelines in the UI. +1. Manually creating pipelines [via API](../../api/pipelines.md#create-a-new-pipeline). +1. Manually playing a job via the UI. +1. Using [push options](../../user/project/push_options.md#push-options-for-gitlab-cicd). +1. Manually triggering pipelines with [the API](../triggers/README.md#making-use-of-trigger-variables). +1. Passing variables to a [downstream pipeline](../multi_project_pipelines.md#passing-variables-to-a-downstream-pipeline). + +These pipeline variables declared in these events take [priority over other variables](#priority-of-environment-variables). + +#### Restrict who can override variables + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/295234) in GitLab 13.8. + +To allow only users with Maintainer role to set these variables, you can use +[the API](../../api/projects.md#edit-project) to enable the project setting `restrict_user_defined_variables`. +When a user without Maintainer role tries to run a pipeline with overridden +variables, an `Insufficient permissions to set pipeline variables` error occurs. + +The setting is `disabled` by default. + +If you [store your CI configurations in a different repository](../../ci/pipelines/settings.md#custom-ci-configuration-path), +use this setting for strict control over all aspects of the environment +the pipeline runs in. + +#### Override a variable by manually running a pipeline > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/44059) in GitLab 10.8. @@ -785,7 +813,9 @@ Feature.enable(:ci_if_parenthesis_enabled) ### Storing regular expressions in variables -It is possible to store a regular expression in a variable, to be used for pattern matching: +It is possible to store a regular expression in a variable, to be used for pattern matching. +The following example tests whether `$RELEASE` contains either the +string `staging0` or the string `staging1`: ```yaml variables: @@ -847,13 +877,7 @@ before making them visible again. ### Restricted access to debug logging > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213159) in GitLab 13.7. -> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default. -> - It's enabled on GitLab.com. -> - It's recommended for production use. -> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-restricted-access-to-debug-logging). **(CORE ONLY)** - -WARNING: -This feature might not be available to you. Check the **version history** note above for details. +> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/292661) in GitLab 13.8. With restricted access to debug logging, only users with [developer or higher permissions](../../user/permissions.md#project-members-permissions) @@ -867,25 +891,6 @@ If you add `CI_DEBUG_TRACE` as a local variable to your runners, debug logs are to all users with access to job logs. The permission levels are not checked by Runner, so you should make use of the variable in GitLab only. -#### Enable or disable Restricted access to debug logging **(CORE ONLY)** - -Restricted Access to Debug logging is under development but ready for production use. -It is deployed behind a feature flag that is **enabled by default**. -[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) -can opt to disable it. - -To enable it: - -```ruby -Feature.enable(:restrict_access_to_build_debug_mode) -``` - -To disable it: - -```ruby -Feature.disable(:restrict_access_to_build_debug_mode) -``` - ### Enable Debug logging To enable debug logs (traces), set the `CI_DEBUG_TRACE` variable to `true`: diff --git a/doc/ci/variables/deprecated_variables.md b/doc/ci/variables/deprecated_variables.md index 755e34fa5ca..8d23ec1fd97 100644 --- a/doc/ci/variables/deprecated_variables.md +++ b/doc/ci/variables/deprecated_variables.md @@ -1,36 +1,8 @@ --- -stage: Verify -group: Continuous Integration -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -type: reference +redirect_to: 'README.md' --- -# Deprecated GitLab CI/CD variables +This documentation page was removed. For information about variables, see [GitLab CI/CD environment variables](README.md) -Read through this document to learn what predefined variables -were deprecated and their new references. - -## GitLab 9.0 renamed variables - -To follow conventions of naming across GitLab, and to further move away from the -`build` term and toward `job`, some [CI/CD environment variables](README.md#predefined-environment-variables) were renamed for GitLab 9.0 -release. - -Starting with GitLab 9.0, we have deprecated the `$CI_BUILD_*` variables. **You are -strongly advised to use the new variables as we might remove the old ones in -future GitLab releases.** - -| 8.x name | 9.0+ name | -| --------------------- |------------------------ | -| `CI_BUILD_BEFORE_SHA` | `CI_COMMIT_BEFORE_SHA` | -| `CI_BUILD_ID` | `CI_JOB_ID` | -| `CI_BUILD_MANUAL` | `CI_JOB_MANUAL` | -| `CI_BUILD_NAME` | `CI_JOB_NAME` | -| `CI_BUILD_REF` | `CI_COMMIT_SHA` | -| `CI_BUILD_REF_NAME` | `CI_COMMIT_REF_NAME` | -| `CI_BUILD_REF_SLUG` | `CI_COMMIT_REF_SLUG` | -| `CI_BUILD_REPO` | `CI_REPOSITORY_URL` | -| `CI_BUILD_STAGE` | `CI_JOB_STAGE` | -| `CI_BUILD_TAG` | `CI_COMMIT_TAG` | -| `CI_BUILD_TOKEN` | `CI_JOB_TOKEN` | -| `CI_BUILD_TRIGGERED` | `CI_PIPELINE_TRIGGERED` | +<!-- This redirect file can be deleted after 2021-04-14. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md index ba0a5e8f461..701fe33b53f 100644 --- a/doc/ci/variables/predefined_variables.md +++ b/doc/ci/variables/predefined_variables.md @@ -14,138 +14,134 @@ Some of the predefined environment variables are available only if a minimum version of [GitLab Runner](https://docs.gitlab.com/runner/) is used. Consult the table below to find the version of GitLab Runner that's required. -NOTE: -Starting with GitLab 9.0, we have deprecated some variables. Read the -[9.0 Renaming](deprecated_variables.md#gitlab-90-renamed-variables) section to find out their replacements. -**To avoid problems with deprecated and removed variables in future releases, you are strongly advised to use the new variables.** - You can add a command to your `.gitlab-ci.yml` file to [output the values of all variables available for a job](README.md#list-all-environment-variables). Kubernetes-specific environment variables are detailed in the [Kubernetes deployment variables](../../user/project/clusters/index.md#deployment-variables) section. -| Variable | GitLab | Runner | Description | -|-----------------------------------------------|--------|--------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `CHAT_CHANNEL` | 10.6 | all | Source chat channel which triggered the [ChatOps](../chatops/README.md) command | -| `CHAT_INPUT` | 10.6 | all | Additional arguments passed in the [ChatOps](../chatops/README.md) command | -| `CI` | all | 0.4 | Mark that job is executed in CI environment | -| `CI_API_V4_URL` | 11.7 | all | The GitLab API v4 root URL | -| `CI_BUILDS_DIR` | all | 11.10 | Top-level directory where builds are executed. | -| `CI_COMMIT_BEFORE_SHA` | 11.2 | all | The previous latest commit present on a branch. Is always `0000000000000000000000000000000000000000` in pipelines for merge requests. | -| `CI_COMMIT_DESCRIPTION` | 10.8 | all | The description of the commit: the message without first line, if the title is shorter than 100 characters; full message in other case. | -| `CI_COMMIT_MESSAGE` | 10.8 | all | The full commit message. | -| `CI_COMMIT_REF_NAME` | 9.0 | all | The branch or tag name for which project is built | -| `CI_COMMIT_REF_PROTECTED` | 11.11 | all | `true` if the job is running on a protected reference, `false` if not | -| `CI_COMMIT_REF_SLUG` | 9.0 | all | `$CI_COMMIT_REF_NAME` lowercased, shortened to 63 bytes, and with everything except `0-9` and `a-z` replaced with `-`. No leading / trailing `-`. Use in URLs, host names and domain names. | -| `CI_COMMIT_SHA` | 9.0 | all | The commit revision for which project is built | -| `CI_COMMIT_SHORT_SHA` | 11.7 | all | The first eight characters of `CI_COMMIT_SHA` | -| `CI_COMMIT_BRANCH` | 12.6 | 0.5 | The commit branch name. Present in branch pipelines, including pipelines for the default branch. Not present in merge request pipelines or tag pipelines. | -| `CI_COMMIT_TAG` | 9.0 | 0.5 | The commit tag name. Present only when building tags. | -| `CI_COMMIT_TITLE` | 10.8 | all | The title of the commit - the full first line of the message | -| `CI_COMMIT_TIMESTAMP` | 13.4 | all | The timestamp of the commit in the ISO 8601 format. | -| `CI_CONCURRENT_ID` | all | 11.10 | Unique ID of build execution within a single executor. | -| `CI_CONCURRENT_PROJECT_ID` | all | 11.10 | Unique ID of build execution within a single executor and project. | -| `CI_CONFIG_PATH` | 9.4 | 0.5 | The path to CI configuration file. Defaults to `.gitlab-ci.yml` | -| `CI_DEBUG_TRACE` | all | 1.7 | Whether [debug logging (tracing)](README.md#debug-logging) is enabled | -| `CI_DEFAULT_BRANCH` | 12.4 | all | The name of the default branch for the project. | -| `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX` | 13.7 | all | The image prefix for pulling images through the Dependency Proxy. | -| `CI_DEPENDENCY_PROXY_SERVER` | 13.7 | all | The server for logging in to the Dependency Proxy. This is equivelant to `$CI_SERVER_HOST:$CI_SERVER_PORT`. | -| `CI_DEPENDENCY_PROXY_PASSWORD` | 13.7 | all | The password to use to pull images through the Dependency Proxy. | -| `CI_DEPENDENCY_PROXY_USER` | 13.7 | all | The username to use to pull images through the Dependency Proxy. | -| `CI_DEPLOY_FREEZE` | 13.2 | all | Included with the value `true` if the pipeline runs during a [deploy freeze window](../../user/project/releases/index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze). | -| `CI_DEPLOY_PASSWORD` | 10.8 | all | Authentication password of the [GitLab Deploy Token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token), only present if the Project has one related. | -| `CI_DEPLOY_USER` | 10.8 | all | Authentication username of the [GitLab Deploy Token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token), only present if the Project has one related. | -| `CI_DISPOSABLE_ENVIRONMENT` | all | 10.1 | Marks that the job is executed in a disposable environment (something that is created only for this job and disposed of/destroyed after the execution - all executors except `shell` and `ssh`). If the environment is disposable, it is set to true, otherwise it is not defined at all. | -| `CI_ENVIRONMENT_NAME` | 8.15 | all | The name of the environment for this job. Only present if [`environment:name`](../yaml/README.md#environmentname) is set. | -| `CI_ENVIRONMENT_SLUG` | 8.15 | all | A simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, etc. Only present if [`environment:name`](../yaml/README.md#environmentname) is set. | -| `CI_ENVIRONMENT_URL` | 9.3 | all | The URL of the environment for this job. Only present if [`environment:url`](../yaml/README.md#environmenturl) is set. | -| `CI_EXTERNAL_PULL_REQUEST_IID` | 12.3 | all | Pull Request ID from GitHub if the [pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | -| `CI_EXTERNAL_PULL_REQUEST_SOURCE_REPOSITORY` | 13.3 | all | The source repository name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | -| `CI_EXTERNAL_PULL_REQUEST_TARGET_REPOSITORY` | 13.3 | all | The target repository name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | -| `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_NAME` | 12.3 | all | The source branch name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | -| `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_SHA` | 12.3 | all | The HEAD SHA of the source branch of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | -| `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_NAME` | 12.3 | all | The target branch name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | -| `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_SHA` | 12.3 | all | The HEAD SHA of the target branch of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | -| `CI_HAS_OPEN_REQUIREMENTS` | 13.1 | all | Included with the value `true` only if the pipeline's project has any open [requirements](../../user/project/requirements/index.md). Not included if there are no open requirements for the pipeline's project. | -| `CI_OPEN_MERGE_REQUESTS` | 13.7 | all | Contains a comma-delimited list of up to 4 Merge Requests from the current source project and branch in the form `gitlab-org/gitlab!333,gitlab-org/gitlab-foss!11` | -| `CI_JOB_ID` | 9.0 | all | The unique ID of the current job that GitLab CI/CD uses internally | -| `CI_JOB_IMAGE` | 12.9 | 12.9 | The name of the image running the CI job | -| `CI_JOB_MANUAL` | 8.12 | all | The flag to indicate that job was manually started | -| `CI_JOB_NAME` | 9.0 | 0.5 | The name of the job as defined in `.gitlab-ci.yml` | -| `CI_JOB_STAGE` | 9.0 | 0.5 | The name of the stage as defined in `.gitlab-ci.yml` | -| `CI_JOB_STATUS` | all | 13.5 | The state of the job as each runner stage is executed. Use with [`after_script`](../yaml/README.md#after_script) where `CI_JOB_STATUS` can be either: `success`, `failed` or `canceled`. | +| Variable | GitLab | Runner | Description | +|-----------------------------------------------|--------|--------|-------------| +| `CHAT_CHANNEL` | 10.6 | all | Source chat channel which triggered the [ChatOps](../chatops/README.md) command. | +| `CHAT_INPUT` | 10.6 | all | Additional arguments passed in the [ChatOps](../chatops/README.md) command. | +| `CI` | all | 0.4 | Mark that job is executed in CI environment. | +| `CI_API_V4_URL` | 11.7 | all | The GitLab API v4 root URL. | +| `CI_BUILDS_DIR` | all | 11.10 | Top-level directory where builds are executed. | +| `CI_COMMIT_BEFORE_SHA` | 11.2 | all | The previous latest commit present on a branch. Is always `0000000000000000000000000000000000000000` in pipelines for merge requests. | +| `CI_COMMIT_DESCRIPTION` | 10.8 | all | The description of the commit: the message without first line, if the title is shorter than 100 characters; full message in other case. | +| `CI_COMMIT_MESSAGE` | 10.8 | all | The full commit message. | +| `CI_COMMIT_REF_NAME` | 9.0 | all | The branch or tag name for which project is built. | +| `CI_COMMIT_REF_PROTECTED` | 11.11 | all | `true` if the job is running on a protected reference, `false` if not. | +| `CI_COMMIT_REF_SLUG` | 9.0 | all | `$CI_COMMIT_REF_NAME` in lowercase, shortened to 63 bytes, and with everything except `0-9` and `a-z` replaced with `-`. No leading / trailing `-`. Use in URLs, host names and domain names. | +| `CI_COMMIT_SHA` | 9.0 | all | The commit revision for which project is built. | +| `CI_COMMIT_SHORT_SHA` | 11.7 | all | The first eight characters of `CI_COMMIT_SHA`. | +| `CI_COMMIT_BRANCH` | 12.6 | 0.5 | The commit branch name. Present in branch pipelines, including pipelines for the default branch. Not present in merge request pipelines or tag pipelines. | +| `CI_COMMIT_TAG` | 9.0 | 0.5 | The commit tag name. Present only when building tags. | +| `CI_COMMIT_TITLE` | 10.8 | all | The title of the commit - the full first line of the message. | +| `CI_COMMIT_TIMESTAMP` | 13.4 | all | The timestamp of the commit in the ISO 8601 format. | +| `CI_CONCURRENT_ID` | all | 11.10 | Unique ID of build execution in a single executor. | +| `CI_CONCURRENT_PROJECT_ID` | all | 11.10 | Unique ID of build execution in a single executor and project. | +| `CI_CONFIG_PATH` | 9.4 | 0.5 | The path to CI configuration file. Defaults to `.gitlab-ci.yml`. | +| `CI_DEBUG_TRACE` | all | 1.7 | Whether [debug logging (tracing)](README.md#debug-logging) is enabled. | +| `CI_DEFAULT_BRANCH` | 12.4 | all | The name of the default branch for the project. | +| `CI_DEPENDENCY_PROXY_GROUP_IMAGE_PREFIX` | 13.7 | all | The image prefix for pulling images through the Dependency Proxy. | +| `CI_DEPENDENCY_PROXY_SERVER` | 13.7 | all | The server for logging in to the Dependency Proxy. This is equivalent to `$CI_SERVER_HOST:$CI_SERVER_PORT`. | +| `CI_DEPENDENCY_PROXY_PASSWORD` | 13.7 | all | The password to use to pull images through the Dependency Proxy. | +| `CI_DEPENDENCY_PROXY_USER` | 13.7 | all | The username to use to pull images through the Dependency Proxy. | +| `CI_DEPLOY_FREEZE` | 13.2 | all | Included with the value `true` if the pipeline runs during a [deploy freeze window](../../user/project/releases/index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze). | +| `CI_DEPLOY_PASSWORD` | 10.8 | all | Authentication password of the [GitLab Deploy Token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token), only present if the Project has one related. | +| `CI_DEPLOY_USER` | 10.8 | all | Authentication username of the [GitLab Deploy Token](../../user/project/deploy_tokens/index.md#gitlab-deploy-token), only present if the Project has one related. | +| `CI_DISPOSABLE_ENVIRONMENT` | all | 10.1 | Marks that the job is executed in a disposable environment (something that is created only for this job and disposed of/destroyed after the execution - all executors except `shell` and `ssh`). If the environment is disposable, it is set to true, otherwise it is not defined at all. | +| `CI_ENVIRONMENT_NAME` | 8.15 | all | The name of the environment for this job. Only present if [`environment:name`](../yaml/README.md#environmentname) is set. | +| `CI_ENVIRONMENT_SLUG` | 8.15 | all | A simplified version of the environment name, suitable for inclusion in DNS, URLs, Kubernetes labels, and so on. Only present if [`environment:name`](../yaml/README.md#environmentname) is set. | +| `CI_ENVIRONMENT_URL` | 9.3 | all | The URL of the environment for this job. Only present if [`environment:url`](../yaml/README.md#environmenturl) is set. | +| `CI_EXTERNAL_PULL_REQUEST_IID` | 12.3 | all | Pull Request ID from GitHub if the [pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | +| `CI_EXTERNAL_PULL_REQUEST_SOURCE_REPOSITORY` | 13.3 | all | The source repository name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | +| `CI_EXTERNAL_PULL_REQUEST_TARGET_REPOSITORY` | 13.3 | all | The target repository name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | +| `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_NAME` | 12.3 | all | The source branch name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | +| `CI_EXTERNAL_PULL_REQUEST_SOURCE_BRANCH_SHA` | 12.3 | all | The HEAD SHA of the source branch of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | +| `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_NAME` | 12.3 | all | The target branch name of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | +| `CI_EXTERNAL_PULL_REQUEST_TARGET_BRANCH_SHA` | 12.3 | all | The HEAD SHA of the target branch of the pull request if [the pipelines are for external pull requests](../ci_cd_for_external_repos/index.md#pipelines-for-external-pull-requests). Available only if `only: [external_pull_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the pull request is open. | +| `CI_HAS_OPEN_REQUIREMENTS` | 13.1 | all | Included with the value `true` only if the pipeline's project has any open [requirements](../../user/project/requirements/index.md). Not included if there are no open requirements for the pipeline's project. | +| `CI_OPEN_MERGE_REQUESTS` | 13.8 | all | Available in branch and merge request pipelines. Contains a comma-separated list of up to four merge requests that use the current branch and project as the merge request source. For example `gitlab-org/gitlab!333,gitlab-org/gitlab-foss!11`. | +| `CI_JOB_ID` | 9.0 | all | The unique ID of the current job that GitLab CI/CD uses internally. | +| `CI_JOB_IMAGE` | 12.9 | 12.9 | The name of the image running the CI job. | +| `CI_JOB_MANUAL` | 8.12 | all | The flag to indicate that job was manually started. | +| `CI_JOB_NAME` | 9.0 | 0.5 | The name of the job as defined in `.gitlab-ci.yml`. | +| `CI_JOB_STAGE` | 9.0 | 0.5 | The name of the stage as defined in `.gitlab-ci.yml`. | +| `CI_JOB_STATUS` | all | 13.5 | The state of the job as each runner stage is executed. Use with [`after_script`](../yaml/README.md#after_script) where `CI_JOB_STATUS` can be either: `success`, `failed` or `canceled`. | | `CI_JOB_TOKEN` | 9.0 | 1.2 | Token used for authenticating with [a few API endpoints](../../api/README.md#gitlab-ci-job-token) and downloading [dependent repositories](../../user/project/new_ci_build_permissions_model.md#dependent-repositories). The token is valid as long as the job is running. | | `CI_JOB_JWT` | 12.10 | all | RS256 JSON web token that can be used for authenticating with third party systems that support JWT authentication, for example [HashiCorp's Vault](../secrets/index.md). | -| `CI_JOB_URL` | 11.1 | 0.5 | Job details URL | -| `CI_KUBERNETES_ACTIVE` | 13.0 | all | Included with the value `true` only if the pipeline has a Kubernetes cluster available for deployments. Not included if no cluster is available. Can be used as an alternative to [`only:kubernetes`/`except:kubernetes`](../yaml/README.md#onlykubernetesexceptkubernetes) with [`rules:if`](../yaml/README.md#rulesif) | -| `CI_MERGE_REQUEST_ASSIGNEES` | 11.9 | all | Comma-separated list of username(s) of assignee(s) for the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_ID` | 11.6 | all | The instance-level ID of the merge request. Only available if [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. This is a unique ID across all projects on GitLab. | -| `CI_MERGE_REQUEST_IID` | 11.6 | all | The project-level IID (internal ID) of the merge request. Only available If [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. This ID is unique for the current project. | -| `CI_MERGE_REQUEST_LABELS` | 11.9 | all | Comma-separated label names of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_MILESTONE` | 11.9 | all | The milestone title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_PROJECT_ID` | 11.6 | all | The ID of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_PROJECT_PATH` | 11.6 | all | The path of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (e.g. `namespace/awesome-project`). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_PROJECT_URL` | 11.6 | all | The URL of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (e.g. `http://192.168.10.15:3000/namespace/awesome-project`). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_REF_PATH` | 11.6 | all | The ref path of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). (e.g. `refs/merge-requests/1/head`). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_SOURCE_BRANCH_NAME` | 11.6 | all | The source branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the source branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used, the merge request is created, and the pipeline is a [merged result pipeline](../merge_request_pipelines/pipelines_for_merged_results/index.md). **(PREMIUM)** | -| `CI_MERGE_REQUEST_SOURCE_PROJECT_ID` | 11.6 | all | The ID of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` | 11.6 | all | The path of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_SOURCE_PROJECT_URL` | 11.6 | all | The URL of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_TARGET_BRANCH_NAME` | 11.6 | all | The target branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | -| `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the target branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used, the merge request is created, and the pipeline is a [merged result pipeline](../merge_request_pipelines/pipelines_for_merged_results/index.md). **(PREMIUM)** | -| `CI_MERGE_REQUEST_TITLE` | 11.9 | all | The title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_JOB_URL` | 11.1 | 0.5 | Job details URL. | +| `CI_KUBERNETES_ACTIVE` | 13.0 | all | Included with the value `true` only if the pipeline has a Kubernetes cluster available for deployments. Not included if no cluster is available. Can be used as an alternative to [`only:kubernetes`/`except:kubernetes`](../yaml/README.md#onlykubernetesexceptkubernetes) with [`rules:if`](../yaml/README.md#rulesif). | +| `CI_MERGE_REQUEST_ASSIGNEES` | 11.9 | all | Comma-separated list of username(s) of assignee(s) for the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_MERGE_REQUEST_ID` | 11.6 | all | The instance-level ID of the merge request. Only available if [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. This is a unique ID across all projects on GitLab. | +| `CI_MERGE_REQUEST_IID` | 11.6 | all | The project-level IID (internal ID) of the merge request. Only available If [the pipelines are for merge requests](../merge_request_pipelines/index.md) and the merge request is created. This ID is unique for the current project. | +| `CI_MERGE_REQUEST_LABELS` | 11.9 | all | Comma-separated label names of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_MERGE_REQUEST_MILESTONE` | 11.9 | all | The milestone title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_MERGE_REQUEST_PROJECT_ID` | 11.6 | all | The ID of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_MERGE_REQUEST_PROJECT_PATH` | 11.6 | all | The path of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (for example `namespace/awesome-project`). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_MERGE_REQUEST_PROJECT_URL` | 11.6 | all | The URL of the project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md) (for example `http://192.168.10.15:3000/namespace/awesome-project`). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_MERGE_REQUEST_REF_PATH` | 11.6 | all | The ref path of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). (for example `refs/merge-requests/1/head`). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_MERGE_REQUEST_SOURCE_BRANCH_NAME` | 11.6 | all | The source branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_MERGE_REQUEST_SOURCE_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the source branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used, the merge request is created, and the pipeline is a [merged result pipeline](../merge_request_pipelines/pipelines_for_merged_results/index.md). **(PREMIUM)** | +| `CI_MERGE_REQUEST_SOURCE_PROJECT_ID` | 11.6 | all | The ID of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` | 11.6 | all | The path of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_MERGE_REQUEST_SOURCE_PROJECT_URL` | 11.6 | all | The URL of the source project of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_MERGE_REQUEST_TARGET_BRANCH_NAME` | 11.6 | all | The target branch name of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | +| `CI_MERGE_REQUEST_TARGET_BRANCH_SHA` | 11.9 | all | The HEAD SHA of the target branch of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used, the merge request is created, and the pipeline is a [merged result pipeline](../merge_request_pipelines/pipelines_for_merged_results/index.md). **(PREMIUM)** | +| `CI_MERGE_REQUEST_TITLE` | 11.9 | all | The title of the merge request if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Available only if `only: [merge_requests]` or [`rules`](../yaml/README.md#rules) syntax is used and the merge request is created. | | `CI_MERGE_REQUEST_EVENT_TYPE` | 12.3 | all | The event type of the merge request, if [the pipelines are for merge requests](../merge_request_pipelines/index.md). Can be `detached`, `merged_result` or `merge_train`. | | `CI_MERGE_REQUEST_DIFF_ID` | 13.7 | all | The version of the merge request diff, if [the pipelines are for merge requests](../merge_request_pipelines/index.md). | | `CI_MERGE_REQUEST_DIFF_BASE_SHA` | 13.7 | all | The base SHA of the merge request diff, if [the pipelines are for merge requests](../merge_request_pipelines/index.md). | -| `CI_NODE_INDEX` | 11.5 | all | Index of the job in the job set. If the job is not parallelized, this variable is not set. | -| `CI_NODE_TOTAL` | 11.5 | all | Total number of instances of this job running in parallel. If the job is not parallelized, this variable is set to `1`. | -| `CI_PAGES_DOMAIN` | 11.8 | all | The configured domain that hosts GitLab Pages. | -| `CI_PAGES_URL` | 11.8 | all | URL to GitLab Pages-built pages. Always belongs to a subdomain of `CI_PAGES_DOMAIN`. | -| `CI_PIPELINE_ID` | 8.10 | all | The instance-level ID of the current pipeline. This is a unique ID across all projects on GitLab. | -| `CI_PIPELINE_IID` | 11.0 | all | The project-level IID (internal ID) of the current pipeline. This ID is unique for the current project. | +| `CI_NODE_INDEX` | 11.5 | all | Index of the job in the job set. If the job is not parallelized, this variable is not set. | +| `CI_NODE_TOTAL` | 11.5 | all | Total number of instances of this job running in parallel. If the job is not parallelized, this variable is set to `1`. | +| `CI_PAGES_DOMAIN` | 11.8 | all | The configured domain that hosts GitLab Pages. | +| `CI_PAGES_URL` | 11.8 | all | URL to GitLab Pages-built pages. Always belongs to a subdomain of `CI_PAGES_DOMAIN`. | +| `CI_PIPELINE_ID` | 8.10 | all | The instance-level ID of the current pipeline. This is a unique ID across all projects on GitLab. | +| `CI_PIPELINE_IID` | 11.0 | all | The project-level IID (internal ID) of the current pipeline. This ID is unique for the current project. | | `CI_PIPELINE_SOURCE` | 10.0 | all | Indicates how the pipeline was triggered. Possible options are: `push`, `web`, `schedule`, `api`, `external`, `chat`, `webide`, `merge_request_event`, `external_pull_request_event`, `parent_pipeline`, [`trigger`, or `pipeline`](../triggers/README.md#authentication-tokens). For pipelines created before GitLab 9.5, this is displayed as `unknown`. | -| `CI_PIPELINE_TRIGGERED` | all | all | The flag to indicate that job was [triggered](../triggers/README.md) | -| `CI_PIPELINE_URL` | 11.1 | 0.5 | Pipeline details URL | +| `CI_PIPELINE_TRIGGERED` | all | all | The flag to indicate that job was [triggered](../triggers/README.md). | +| `CI_PIPELINE_URL` | 11.1 | 0.5 | Pipeline details URL. | +| `CI_PROJECT_CONFIG_PATH` | 13.8 | all | The CI configuration path for the project. | | `CI_PROJECT_DIR` | all | all | The full path where the repository is cloned and where the job is run. If the GitLab Runner `builds_dir` parameter is set, this variable is set relative to the value of `builds_dir`. For more information, see [Advanced configuration](https://docs.gitlab.com/runner/configuration/advanced-configuration.html#the-runners-section) for GitLab Runner. | -| `CI_PROJECT_ID` | all | all | The unique ID of the current project that GitLab CI/CD uses internally | -| `CI_PROJECT_NAME` | 8.10 | 0.5 | The name of the directory for the project that is currently being built. For example, if the project URL is `gitlab.example.com/group-name/project-1`, the `CI_PROJECT_NAME` would be `project-1`. | -| `CI_PROJECT_NAMESPACE` | 8.10 | 0.5 | The project namespace (username or group name) that is currently being built | -| `CI_PROJECT_ROOT_NAMESPACE` | 13.2 | 0.5 | The **root** project namespace (username or group name) that is currently being built. For example, if `CI_PROJECT_NAMESPACE` is `root-group/child-group/grandchild-group`, `CI_PROJECT_ROOT_NAMESPACE` would be `root-group`. | -| `CI_PROJECT_PATH` | 8.10 | 0.5 | The namespace with project name | -| `CI_PROJECT_PATH_SLUG` | 9.3 | all | `$CI_PROJECT_PATH` lowercased and with everything except `0-9` and `a-z` replaced with `-`. Use in URLs and domain names. | -| `CI_PROJECT_REPOSITORY_LANGUAGES` | 12.3 | all | Comma-separated, lowercased list of the languages used in the repository (e.g. `ruby,javascript,html,css`) | -| `CI_PROJECT_TITLE` | 12.4 | all | The human-readable project name as displayed in the GitLab web interface. | -| `CI_PROJECT_URL` | 8.10 | 0.5 | The HTTP(S) address to access project | -| `CI_PROJECT_VISIBILITY` | 10.3 | all | The project visibility (internal, private, public) | -| `CI_REGISTRY` | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of the GitLab Container Registry. This variable includes a `:port` value if one has been specified in the registry configuration. | -| `CI_REGISTRY_IMAGE` | 8.10 | 0.5 | If the Container Registry is enabled for the project it returns the address of the registry tied to the specific project | -| `CI_REGISTRY_PASSWORD` | 9.0 | all | The password to use to push containers to the GitLab Container Registry, for the current project. | -| `CI_REGISTRY_USER` | 9.0 | all | The username to use to push containers to the GitLab Container Registry, for the current project. | -| `CI_REPOSITORY_URL` | 9.0 | all | The URL to clone the Git repository | -| `CI_RUNNER_DESCRIPTION` | 8.10 | 0.5 | The description of the runner as saved in GitLab | -| `CI_RUNNER_EXECUTABLE_ARCH` | all | 10.6 | The OS/architecture of the GitLab Runner executable (note that this is not necessarily the same as the environment of the executor) | -| `CI_RUNNER_ID` | 8.10 | 0.5 | The unique ID of runner being used | -| `CI_RUNNER_REVISION` | all | 10.6 | GitLab Runner revision that is executing the current job | -| `CI_RUNNER_SHORT_TOKEN` | all | 12.3 | First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID | -| `CI_RUNNER_TAGS` | 8.10 | 0.5 | The defined runner tags | -| `CI_RUNNER_VERSION` | all | 10.6 | GitLab Runner version that is executing the current job | -| `CI_SERVER` | all | all | Mark that job is executed in CI environment | -| `CI_SERVER_URL` | 12.7 | all | The base URL of the GitLab instance, including protocol and port (like `https://gitlab.example.com:8080`) | -| `CI_SERVER_HOST` | 12.1 | all | Host component of the GitLab instance URL, without protocol and port (like `gitlab.example.com`) | -| `CI_SERVER_PORT` | 12.8 | all | Port component of the GitLab instance URL, without host and protocol (like `3000`) | -| `CI_SERVER_PROTOCOL` | 12.8 | all | Protocol component of the GitLab instance URL, without host and port (like `https`) | -| `CI_SERVER_NAME` | all | all | The name of CI server that is used to coordinate jobs | -| `CI_SERVER_REVISION` | all | all | GitLab revision that is used to schedule jobs | -| `CI_SERVER_VERSION` | all | all | GitLab version that is used to schedule jobs | -| `CI_SERVER_VERSION_MAJOR` | 11.4 | all | GitLab version major component | -| `CI_SERVER_VERSION_MINOR` | 11.4 | all | GitLab version minor component | -| `CI_SERVER_VERSION_PATCH` | 11.4 | all | GitLab version patch component | -| `CI_SHARED_ENVIRONMENT` | all | 10.1 | Marks that the job is executed in a shared environment (something that is persisted across CI invocations like `shell` or `ssh` executor). If the environment is shared, it is set to true, otherwise it is not defined at all. | -| `GITLAB_CI` | all | all | Mark that job is executed in GitLab CI/CD environment | -| `GITLAB_FEATURES` | 10.6 | all | The comma separated list of licensed features available for your instance and plan | -| `GITLAB_USER_EMAIL` | 8.12 | all | The email of the user who started the job | -| `GITLAB_USER_ID` | 8.12 | all | The ID of the user who started the job | -| `GITLAB_USER_LOGIN` | 10.0 | all | The login username of the user who started the job | -| `GITLAB_USER_NAME` | 10.0 | all | The real name of the user who started the job | +| `CI_PROJECT_ID` | all | all | The unique ID of the current project that GitLab CI/CD uses internally. | +| `CI_PROJECT_NAME` | 8.10 | 0.5 | The name of the directory for the project that is being built. For example, if the project URL is `gitlab.example.com/group-name/project-1`, the `CI_PROJECT_NAME` would be `project-1`. | +| `CI_PROJECT_NAMESPACE` | 8.10 | 0.5 | The project namespace (username or group name) that is being built. | +| `CI_PROJECT_ROOT_NAMESPACE` | 13.2 | 0.5 | The **root** project namespace (username or group name) that is being built. For example, if `CI_PROJECT_NAMESPACE` is `root-group/child-group/grandchild-group`, `CI_PROJECT_ROOT_NAMESPACE` would be `root-group`. | +| `CI_PROJECT_PATH` | 8.10 | 0.5 | The namespace with project name. | +| `CI_PROJECT_PATH_SLUG` | 9.3 | all | `$CI_PROJECT_PATH` in lowercase and with everything except `0-9` and `a-z` replaced with `-`. Use in URLs and domain names. | +| `CI_PROJECT_REPOSITORY_LANGUAGES` | 12.3 | all | Comma-separated, lowercase list of the languages used in the repository (for example `ruby,javascript,html,css`). | +| `CI_PROJECT_TITLE` | 12.4 | all | The human-readable project name as displayed in the GitLab web interface. | +| `CI_PROJECT_URL` | 8.10 | 0.5 | The HTTP(S) address to access project. | +| `CI_PROJECT_VISIBILITY` | 10.3 | all | The project visibility (internal, private, public). | +| `CI_REGISTRY` | 8.10 | 0.5 | If the Container Registry is enabled it returns the address of the GitLab Container Registry. This variable includes a `:port` value if one has been specified in the registry configuration. | +| `CI_REGISTRY_IMAGE` | 8.10 | 0.5 | If the Container Registry is enabled for the project it returns the address of the registry tied to the specific project. | +| `CI_REGISTRY_PASSWORD` | 9.0 | all | The password to use to push containers to the GitLab Container Registry, for the current project. | +| `CI_REGISTRY_USER` | 9.0 | all | The username to use to push containers to the GitLab Container Registry, for the current project. | +| `CI_REPOSITORY_URL` | 9.0 | all | The URL to clone the Git repository. | +| `CI_RUNNER_DESCRIPTION` | 8.10 | 0.5 | The description of the runner as saved in GitLab. | +| `CI_RUNNER_EXECUTABLE_ARCH` | all | 10.6 | The OS/architecture of the GitLab Runner executable (note that this is not necessarily the same as the environment of the executor). | +| `CI_RUNNER_ID` | 8.10 | 0.5 | The unique ID of runner being used. | +| `CI_RUNNER_REVISION` | all | 10.6 | GitLab Runner revision that is executing the current job. | +| `CI_RUNNER_SHORT_TOKEN` | all | 12.3 | First eight characters of the runner's token used to authenticate new job requests. Used as the runner's unique ID. | +| `CI_RUNNER_TAGS` | 8.10 | 0.5 | The defined runner tags. | +| `CI_RUNNER_VERSION` | all | 10.6 | GitLab Runner version that is executing the current job. | +| `CI_SERVER` | all | all | Mark that job is executed in CI environment. | +| `CI_SERVER_URL` | 12.7 | all | The base URL of the GitLab instance, including protocol and port (like `https://gitlab.example.com:8080`). | +| `CI_SERVER_HOST` | 12.1 | all | Host component of the GitLab instance URL, without protocol and port (like `gitlab.example.com`). | +| `CI_SERVER_PORT` | 12.8 | all | Port component of the GitLab instance URL, without host and protocol (like `3000`). | +| `CI_SERVER_PROTOCOL` | 12.8 | all | Protocol component of the GitLab instance URL, without host and port (like `https`). | +| `CI_SERVER_NAME` | all | all | The name of CI server that is used to coordinate jobs. | +| `CI_SERVER_REVISION` | all | all | GitLab revision that is used to schedule jobs. | +| `CI_SERVER_VERSION` | all | all | GitLab version that is used to schedule jobs. | +| `CI_SERVER_VERSION_MAJOR` | 11.4 | all | GitLab version major component. | +| `CI_SERVER_VERSION_MINOR` | 11.4 | all | GitLab version minor component. | +| `CI_SERVER_VERSION_PATCH` | 11.4 | all | GitLab version patch component. | +| `CI_SHARED_ENVIRONMENT` | all | 10.1 | Marks that the job is executed in a shared environment (something that is persisted across CI invocations like `shell` or `ssh` executor). If the environment is shared, it is set to true, otherwise it is not defined at all. | +| `GITLAB_CI` | all | all | Mark that job is executed in GitLab CI/CD environment. | +| `GITLAB_FEATURES` | 10.6 | all | The comma separated list of licensed features available for your instance and plan. | +| `GITLAB_USER_EMAIL` | 8.12 | all | The email of the user who started the job. | +| `GITLAB_USER_ID` | 8.12 | all | The ID of the user who started the job. | +| `GITLAB_USER_LOGIN` | 10.0 | all | The login username of the user who started the job. | +| `GITLAB_USER_NAME` | 10.0 | all | The real name of the user who started the job. | diff --git a/doc/ci/variables/where_variables_can_be_used.md b/doc/ci/variables/where_variables_can_be_used.md index f2dc58bc144..e84714f2a46 100644 --- a/doc/ci/variables/where_variables_can_be_used.md +++ b/doc/ci/variables/where_variables_can_be_used.md @@ -27,6 +27,7 @@ There are two places defined variables can be used. On the: | `environment:url` | yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab.<br/><br/>Supported are all variables defined for a job (project/group variables, variables from `.gitlab-ci.yml`, variables from triggers, variables from pipeline schedules).<br/><br/>Not supported are variables defined in the GitLab Runner `config.toml` and variables created in the job's `script`. | | `environment:name` | yes | GitLab | Similar to `environment:url`, but the variables expansion doesn't support the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). | | `resource_group` | yes | GitLab | Similar to `environment:url`, but the variables expansion doesn't support the following:<br/><br/>- Variables that are based on the environment's name (`CI_ENVIRONMENT_NAME`, `CI_ENVIRONMENT_SLUG`).<br/>- Any other variables related to environment (currently only `CI_ENVIRONMENT_URL`).<br/>- [Persisted variables](#persisted-variables). | +| `include` | yes | GitLab | The variable expansion is made by the [internal variable expansion mechanism](#gitlab-internal-variable-expansion-mechanism) in GitLab. <br/><br/>Predefined project variables are supported: `GITLAB_FEATURES`, `CI_DEFAULT_BRANCH`, and all variables that start with `CI_PROJECT_` (for example `CI_PROJECT_NAME`). | | `variables` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) | | `image` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) | | `services:[]` | yes | Runner | The variable expansion is made by GitLab Runner's [internal variable expansion mechanism](#gitlab-runner-internal-variable-expansion-mechanism) | diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 7ca74cdf2a2..19b8f0f1c89 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -363,8 +363,6 @@ use the [`extends` keyword](#extends). | [`remote`](#includeremote) | Include a file from a remote URL. Must be publicly accessible. | | [`template`](#includetemplate) | Include templates that are provided by GitLab. | -The `include` methods do not support [variable expansion](../variables/where_variables_can_be_used.md#variables-usage). - `.gitlab-ci.yml` configuration included by all methods is evaluated at pipeline creation. The configuration is a snapshot in time and persisted in the database. Any changes to referenced `.gitlab-ci.yml` configuration is not reflected in GitLab until the next pipeline is created. @@ -379,6 +377,48 @@ NOTE: Use merging to customize and override included CI/CD configurations with local definitions. Local definitions in `.gitlab-ci.yml` override included definitions. +#### Variables with `include` + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/284883) in GitLab 13.8. +> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default. +> - It's disabled on GitLab.com. +> - It's not recommended for production use. +> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-includepredefined-project-variables). **(CORE ONLY)** + +WARNING: +This feature might not be available to you. Check the **version history** note above for details. + +You can [use some predefined variables in `include` sections](../variables/where_variables_can_be_used.md#gitlab-ciyml-file) +in your `.gitlab-ci.yml`: + +```yaml +include: + project: '$CI_PROJECT_PATH' + file: '.compliance-gitlab-ci.yml' +``` + +For an example of how you can include these predefined variables, and their impact on CI jobs, +see the following [CI variable demo](https://youtu.be/4XR8gw3Pkos). + +##### Enable or disable include:predefined-project-variables **(CORE ONLY)** + +Use of predefined project variables in `include` section of `.gitlab-ci.yml` is under development and not ready for production use. It is +deployed behind a feature flag that is **disabled by default**. +[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) +can enable it. + +To enable it: + +```ruby +Feature.enable(:variables_in_include_section_ci) +``` + +To disable it: + +```ruby +Feature.disable(:variables_in_include_section_ci) +``` + #### `include:local` `include:local` includes a file from the same repository as `.gitlab-ci.yml`. @@ -412,9 +452,10 @@ include: '.gitlab-ci-production.yml' > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53903) in GitLab 11.7. -To include files from another private project under the same GitLab instance, -use `include:file`. This file is referenced with full paths relative to the -root directory (`/`). For example: +To include files from another private project on the same GitLab instance, +use `include:file`. You can use `include:file` in combination with `include:project` only. + +The included file is referenced with a full path, relative to the root directory (`/`). For example: ```yaml include: @@ -445,10 +486,7 @@ You can use local (relative to target project), project, remote, or template inc ##### Multiple files from a project > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26793) in GitLab 13.6. -> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default. -> - It's enabled on GitLab.com. -> - It's recommended for production use. -> - For GitLab self-managed instances, GitLab administrators can opt to disable it. **(CORE ONLY)** +> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/271560) in GitLab 13.8. You can include multiple files from the same project: @@ -461,23 +499,6 @@ include: - '/templates/.tests.yml' ``` -Including multiple files from the same project is under development but ready for production use. It is -deployed behind a feature flag that is **enabled by default**. -[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) -can opt to disable it. - -To enable it: - -```ruby -Feature.enable(:ci_include_multiple_files_from_project) -``` - -To disable it: - -```ruby -Feature.disable(:ci_include_multiple_files_from_project) -``` - #### `include:remote` `include:remote` can be used to include a file from a different location, @@ -615,10 +636,33 @@ job: ``` Sometimes, `script` commands must be wrapped in single or double quotes. -For example, commands that contain a colon (`:`) must be wrapped in quotes. +For example, commands that contain a colon (`:`) must be wrapped in single quotes (`'`). The YAML parser needs to interpret the text as a string rather than -a "key: value" pair. Be careful when using special characters: -`:`, `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` ``. +a "key: value" pair. + +For example, this script uses a colon: + +```yaml +job: + script: + - curl --request POST --header 'Content-Type: application/json' "https://gitlab/api/v4/projects" +``` + +To be considered valid YAML, you must wrap the entire command in single quotes. If +the command already uses single quotes, you should change them to double quotes (`"`) +if possible: + +```yaml +job: + script: + - 'curl --request POST --header "Content-Type: application/json" "https://gitlab/api/v4/projects"' +``` + +You can verify the syntax is valid with the [CI Lint](../lint.md) tool. + +Be careful when using these special characters as well: + +- `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` ``. If any of the script commands return an exit code other than zero, the job fails and further commands are not executed. Store the exit code in a variable to @@ -1414,10 +1458,11 @@ In this example, if the first rule matches, then the job has `when: manual` and #### `rules:variables` > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/209864) in GitLab 13.7. -> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default. -> - It's disabled on GitLab.com. -> - It's not recommended for production use. -> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-rulesvariables). **(CORE ONLY)** +> - It was [deployed behind a feature flag](../../user/feature_flags.md), disabled by default. +> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/289803) on GitLab 13.8. +> - It's enabled on GitLab.com. +> - It's recommended for production use. +> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-rulesvariables). **(CORE ONLY)** WARNING: This feature might not be available to you. Check the **version history** note above for details. @@ -1444,10 +1489,10 @@ job: ##### Enable or disable rules:variables **(CORE ONLY)** -rules:variables is under development and not ready for production use. It is -deployed behind a feature flag that is **disabled by default**. +rules:variables is under development but ready for production use. +It is deployed behind a feature flag that is **enabled by default**. [GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) -can enable it. +can opt to disable it. To enable it: @@ -2270,6 +2315,58 @@ job3: - deploy_to_staging ``` +#### `allow_failure:exit_codes` + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/273157) in GitLab 13.8. +> - It's [deployed behind a feature flag](../../user/feature_flags.md), enabled by default. +> - It's enabled on GitLab.com. +> - It's recommended for production use. +> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-allow_failureexit_codes). **(CORE ONLY)** + +WARNING: +This feature might not be available to you. Check the **version history** note above for details. + +Use `allow_failure:exit_codes` to dynamically control if a job should be allowed +to fail. You can list which exit codes are not considered failures. The job fails +for any other exit code: + +```yaml +test_job_1: + script: + - echo "Run a script that results in exit code 1. This job fails." + - exit 1 + allow_failure: + exit_codes: 137 + +test_job_2: + script: + - echo "Run a script that results in exit code 137. This job is allowed to fail." + - exit 137 + allow_failure: + exit_codes: + - 137 + - 255 +``` + +##### Enable or disable `allow_failure:exit_codes` **(CORE ONLY)** + +`allow_failure:exit_codes` is under development but ready for production use. It is +deployed behind a feature flag that is **enabled by default**. +[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) +can disable it. + +To disable it: + +```ruby +Feature.disable(:ci_allow_failure_with_exit_codes) +``` + +To enable it: + +```ruby +Feature.enable(:ci_allow_failure_with_exit_codes) +``` + ### `when` `when` is used to implement jobs that are run in case of failure or despite the @@ -2961,8 +3058,6 @@ larger than the [maximum artifact size](../../user/gitlab_com/index.md#gitlab-ci Job artifacts are only collected for successful jobs by default, and artifacts are restored after [caches](#cache). -[Not all executors can use caches](https://docs.gitlab.com/runner/executors/#compatibility-chart). - [Read more about artifacts](../pipelines/job_artifacts.md). #### `artifacts:paths` @@ -3266,7 +3361,7 @@ job: The latest artifacts for refs are locked against deletion, and kept regardless of the expiry time. [Introduced in](https://gitlab.com/gitlab-org/gitlab/-/issues/16267) GitLab 13.0 behind a disabled feature flag, and [made the default behavior](https://gitlab.com/gitlab-org/gitlab/-/issues/229936) -in GitLab 13.4. +in GitLab 13.4. In [GitLab 13.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/241026), you can [disable this behavior in the CI/CD settings](../pipelines/job_artifacts.md#keep-artifacts-from-most-recent-successful-jobs). #### `artifacts:reports` @@ -3386,6 +3481,10 @@ If there is more than one matched line in the job output, the last line is used. For the matched line, the first occurence of `\d+(\.\d+)?` is the code coverage. Leading zeros are removed. +Coverage output from [child pipelines](../parent_child_pipelines.md) is not recorded +or displayed. Check [the related issue](https://gitlab.com/gitlab-org/gitlab/-/issues/280818) +for more details. + ### `retry` > - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/3442) in GitLab 9.5. @@ -3536,15 +3635,13 @@ job split into three separate jobs. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15356) in GitLab 13.3. -Use `matrix:` to configure different variables for jobs that are running in parallel. +Use `matrix:` to run a job multiple times in parallel in a single pipeline, +but with different variable values for each instance of the job. There can be from 2 to 50 jobs. Jobs can only run in parallel if there are multiple runners, or a single runner is [configured to run multiple jobs concurrently](#using-your-own-runners). -[In GitLab 13.5](https://gitlab.com/gitlab-org/gitlab/-/issues/26362) and later, -you can have one-dimensional matrices with a single job. - Every job gets the same `CI_NODE_TOTAL` [environment variable](../variables/README.md#predefined-environment-variables) value, and a unique `CI_NODE_INDEX` value. ```yaml @@ -3583,6 +3680,22 @@ deploystacks: [vultr, processing] The job naming style was [improved in GitLab 13.4](https://gitlab.com/gitlab-org/gitlab/-/issues/230452). +##### One-dimensional `matrix` jobs + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26362) in GitLab 13.5. + +You can also have one-dimensional matrices with a single job: + +```yaml +deploystacks: + stage: deploy + script: + - bin/deploy + parallel: + matrix: + - PROVIDER: [aws, ovh, gcp, vultr] +``` + ### `trigger` > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8997) in [GitLab Premium](https://about.gitlab.com/pricing/) 11.8. @@ -3933,7 +4046,23 @@ The Release name. If omitted, it is populated with the value of `release: tag_na #### `release:description` -Specifies the longer description of the Release. +Specifies the long description of the Release. You can also specify a file that contains the +description. + +##### Read description from a file + +> [Introduced](https://gitlab.com/gitlab-org/release-cli/-/merge_requests/67) in GitLab 13.7. + +You can specify a file in `$CI_PROJECT_DIR` that contains the description. The file must be relative +to the project directory (`$CI_PROJECT_DIR`), and if the file is a symbolic link it can't reside +outside of `$CI_PROJECT_DIR`. The `./path/to/file` and file name can't contain spaces. + +```yaml +job: + release: + tag_name: ${MAJOR}_${MINOR}_${REVISION} + description: './path/to/CHANGELOG.md' +``` #### `release:ref` diff --git a/doc/ci/yaml/gitlab_ci_yaml.md b/doc/ci/yaml/gitlab_ci_yaml.md index 602e02dbe6b..e4ede9cf699 100644 --- a/doc/ci/yaml/gitlab_ci_yaml.md +++ b/doc/ci/yaml/gitlab_ci_yaml.md @@ -27,7 +27,7 @@ The scripts are grouped into **jobs**, and jobs run as part of a larger **pipeline**. You can group multiple independent jobs into **stages** that run in a defined order. You should organize your jobs in a sequence that suits your application and is in accordance with -the tests you wish to perform. To [visualize](visualization.md) the process, imagine +the tests you wish to perform. To [visualize](../pipeline_editor/index.md#visualize-ci-configuration) the process, imagine the scripts you add to jobs are the same as CLI commands you run on your computer. When you add a `.gitlab-ci.yml` file to your diff --git a/doc/ci/yaml/visualization.md b/doc/ci/yaml/visualization.md index 59a92370c70..ff3b0456eca 100644 --- a/doc/ci/yaml/visualization.md +++ b/doc/ci/yaml/visualization.md @@ -1,52 +1,8 @@ --- -stage: Verify -group: Pipeline Authoring -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +redirect_to: '../pipeline_editor/index.md#visualize-ci-configuration' --- -# Visualize your CI/CD configuration +This document was moved to [another location](../pipeline_editor/index.md#visualize-ci-configuration). -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241722) in GitLab 13.5. -> - [Moved to **CI/CD > Editor**](https://gitlab.com/gitlab-org/gitlab/-/issues/263141) in GitLab 13.7. -> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default. -> - It's disabled on GitLab.com. -> - It's not recommended for production use. -> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-cicd-configuration-visualization). **(CORE ONLY)** - -WARNING: -This feature might not be available to you. Check the **version history** note above for details. - -To see a visualization of your `gitlab-ci.yml` configuration, navigate to **CI/CD > Editor** -and select the `Visualization` tab. The visualization shows all stages and jobs. -[`needs`](README.md#needs) relationships are displayed as lines connecting jobs together, showing the hierarchy of execution: - -![CI Config Visualization](img/ci_config_visualization_v13_7.png) - -Hovering on a job highlights its `needs` relationships: - -![CI Config Visualization on hover](img/ci_config_visualization_hover_v13_7.png) - -If the configuration does not have any `needs` relationships, then no lines are drawn because -each job depends only on the previous stage being completed successfully. - -You can only preview one `gitlab-ci.yml` file at a time. Configuration imported with -[`includes`](README.md#include) is ignored and not included in the visualization. - -## Enable or disable CI/CD configuration visualization **(CORE ONLY)** - -CI/CD configuration visualization is under development and not ready for production use. It is -deployed behind a feature flag that is **disabled by default**. -[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) -can enable it. - -To enable it: - -```ruby -Feature.enable(:ci_config_visualization_tab) -``` - -To disable it: - -```ruby -Feature.disable(:ci_config_visualization_tab) -``` +<!-- This redirect file can be deleted after 2021-04-13. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/README.md b/doc/development/README.md index 2e4674b5288..0d3c1b3cbe9 100644 --- a/doc/development/README.md +++ b/doc/development/README.md @@ -256,11 +256,11 @@ See [database guidelines](database/index.md). - [Externalization](i18n/externalization.md) - [Translation](i18n/translation.md) -## Product Analytics guides +## Product Intelligence guides -- [Product Analytics guide](https://about.gitlab.com/handbook/product/product-analytics-guide/) -- [Usage Ping guide](product_analytics/usage_ping.md) -- [Snowplow guide](product_analytics/snowplow.md) +- [Product Intelligence guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) +- [Usage Ping guide](usage_ping.md) +- [Snowplow guide](snowplow.md) ## Experiment guide @@ -292,6 +292,7 @@ See [database guidelines](database/index.md). - [Reference processing](reference_processing.md) - [Compatibility with multiple versions of the application running at the same time](multi_version_compatibility.md) - [Features inside `.gitlab/`](features_inside_dot_gitlab.md) +- [Dashboards for stage groups](stage_group_dashboards.md) ## Other GitLab Development Kit (GDK) guides diff --git a/doc/development/adding_database_indexes.md b/doc/development/adding_database_indexes.md index 0991c4740cc..01904d37883 100644 --- a/doc/development/adding_database_indexes.md +++ b/doc/development/adding_database_indexes.md @@ -195,3 +195,34 @@ Without an explicit name argument, Rails can return a false positive for `index_exists?`, causing a required index to not be created properly. By always requiring a name for certain types of indexes, the chance of error is greatly reduced. + +## Temporary indexes + +There may be times when an index is only needed temporarily. + +For example, in a migration, a column of a table might be conditionally +updated. To query which columns need to be updated within the +[query performance guidelines](query_performance.md), an index is needed that would otherwise +not be used. + +In these cases, a temporary index should be considered. To specify a +temporary index: + +1. Prefix the index name with `tmp_` and follow the [naming conventions](database/constraint_naming_convention.md) and [requirements for naming indexes](#requirements-for-naming-indexes) for the rest of the name. +1. Create a follow-up issue to remove the index in the next (or future) milestone. +1. Add a comment in the migration mentioning the removal issue. + +A temporary migration would look like: + +```ruby +INDEX_NAME = 'tmp_index_projects_on_owner_where_emails_disabled' + +def up + # Temporary index to be removed in 13.9 https://gitlab.com/gitlab-org/gitlab/-/issues/1234 + add_concurrent_index :projects, :creator_id, where: 'emails_disabled = false', name: INDEX_NAME +end + +def down + remove_concurrent_index_by_name :projects, INDEX_NAME +end +``` diff --git a/doc/development/agent/identity.md b/doc/development/agent/identity.md index 65de1a6f0c8..884ce015a02 100644 --- a/doc/development/agent/identity.md +++ b/doc/development/agent/identity.md @@ -37,9 +37,9 @@ has a different configuration. Some may enable features A and B, and some may enable features B and C. This flexibility enables different groups of people to use different features of the agent in the same cluster. -For example, [Priyanka (Platform Engineer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#priyanka-platform-engineer) +For example, [Priyanka (Platform Engineer)](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/#priyanka-platform-engineer) may want to use cluster-wide features of the agent, while -[Sasha (Software Developer)](https://about.gitlab.com/handbook/marketing/product-marketing/roles-personas/#sasha-software-developer) +[Sasha (Software Developer)](https://about.gitlab.com/handbook/marketing/strategic-marketing/roles-personas/#sasha-software-developer) uses the agent that only has access to a particular namespace. Each agent is likely running using a diff --git a/doc/development/agent/local.md b/doc/development/agent/local.md index 75d45366238..47246a6a6d3 100644 --- a/doc/development/agent/local.md +++ b/doc/development/agent/local.md @@ -38,7 +38,7 @@ You can run `kas` and `agentk` locally to test the [Kubernetes Agent](index.md) gdk start # Stop GDK's version of kas gdk stop gitlab-k8s-agent - + # Start kas bazel run //cmd/kas -- --configuration-file="$(pwd)/cfg.yaml" ``` @@ -56,3 +56,45 @@ for more targets. <i class="fa fa-youtube-play youtube" aria-hidden="true"></i> To learn more about how the repository is structured, see [GitLab Kubernetes Agent repository overview](https://www.youtube.com/watch?v=j8CyaCWroUY). + +## Run tests locally + +You can run all tests, or a subset of tests, locally. + +- **To run all tests**: Run the command `make test`. +- **To run all test targets in the directory**: Run the command + `bazel test //internal/module/gitops/server:all`. + + You can use `*` in the command, instead of `all`, but it must be quoted to + avoid shell expansion: `bazel test '//internal/module/gitops/server:*'`. +- **To run all tests in a directory and its subdirectories**: Run the command + `bazel test //internal/module/gitops/server/...`. + +### Run specific test scenarios + +To run only a specific test scenario, you need the directory name and the target +name of the test. For example, to run the tests at +`internal/module/gitops/server/module_test.go`, the `BUILD.bazel` file that +defines the test's target name lives at `internal/module/gitops/server/BUILD.bazel`. +In the latter, the target name is defined like: + +```bazel +go_test( + name = "server_test", + size = "small", + srcs = [ + "module_test.go", +``` + +The target name is `server_test` and the directory is `internal/module/gitops/server/`. +Run the test scenario with this command: + +```shell +bazel test //internal/module/gitops/server:server_test +``` + +### Additional resources + +- Bazel documentation about [specifying targets to build](https://docs.bazel.build/versions/master/guide.html#specifying-targets-to-build). +- [The Bazel query](https://docs.bazel.build/versions/master/query.html) +- [Bazel query how to](https://docs.bazel.build/versions/master/query-how-to.html) diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md index 832a89ecac1..d73c3a8d6f6 100644 --- a/doc/development/api_graphql_styleguide.md +++ b/doc/development/api_graphql_styleguide.md @@ -760,7 +760,7 @@ To limit the amount of queries performed, we can use [BatchLoader](graphql_guide ### Writing resolvers -Our code should aim to be thin declarative wrappers around finders and services. You can +Our code should aim to be thin declarative wrappers around finders and [services](../development/reusing_abstractions.md#service-classes). You can repeat lists of arguments, or extract them to concerns. Composition is preferred over inheritance in most cases. Treat resolvers like controllers: resolvers should be a DSL that compose other application abstractions. @@ -1256,6 +1256,10 @@ single mutation when multiple are performed within a single request. ### The `resolve` method +Similar to [writing resolvers](#writing-resolvers), the `resolve` method of a mutation +should aim to be a thin declarative wrapper around a +[service](../development/reusing_abstractions.md#service-classes). + The `resolve` method receives the mutation's arguments as keyword arguments. From here, we can call the service that modifies the resource. @@ -1352,6 +1356,7 @@ Key points: - Errors may be reported to users either at `$root.errors` (top-level error) or at `$root.data.mutationName.errors` (mutation errors). The location depends on what kind of error this is, and what information it holds. +- Mutation fields [must have `null: true`](https://graphql-ruby.org/mutations/mutation_errors#nullable-mutation-payload-fields) Consider an example mutation `doTheThing` that returns a response with two fields: `errors: [String]`, and `thing: ThingType`. The specific nature of diff --git a/doc/development/changelog.md b/doc/development/changelog.md index 894ae5a1893..8fad32ed163 100644 --- a/doc/development/changelog.md +++ b/doc/development/changelog.md @@ -47,7 +47,7 @@ the `author` field. GitLab team members **should not**. - Any user-facing change **must** have a changelog entry. This includes both visual changes (regardless of how minor), and changes to the rendered DOM which impact how a screen reader may announce the content. - Any client-facing change to our REST and GraphQL APIs **must** have a changelog entry. - Performance improvements **should** have a changelog entry. -- Changes that need to be documented in the Product Analytics [Event Dictionary](https://about.gitlab.com/handbook/product/product-analytics-guide/#event-dictionary) +- Changes that need to be documented in the Product Intelligence [Event Dictionary](https://about.gitlab.com/handbook/product/product-intelligence-guide/#event-dictionary) also require a changelog entry. - _Any_ contribution from a community member, no matter how small, **may** have a changelog entry regardless of these guidelines if the contributor wants one. @@ -55,7 +55,7 @@ the `author` field. GitLab team members **should not**. - Any docs-only changes **should not** have a changelog entry. - Any change behind a disabled feature flag **should not** have a changelog entry. - Any change behind an enabled feature flag **should** have a changelog entry. -- Any change that adds new usage data metrics and changes that needs to be documented in Product Analytics [Event Dictionary](https://about.gitlab.com/handbook/product/product-analytics-guide/#event-dictionary) **should** have a changelog entry. +- Any change that adds new usage data metrics and changes that needs to be documented in Product Intelligence [Event Dictionary](https://about.gitlab.com/handbook/product/product-intelligence-guide/#event-dictionary) **should** have a changelog entry. - A change that adds snowplow events **should** have a changelog entry - - A change that [removes a feature flag](feature_flags/development.md) **should** have a changelog entry - only if the feature flag did not default to true already. diff --git a/doc/development/cicd/templates.md b/doc/development/cicd/templates.md index 1ab569ba0df..94b03634e25 100644 --- a/doc/development/cicd/templates.md +++ b/doc/development/cicd/templates.md @@ -34,7 +34,7 @@ Also, all templates must be named with the `*.gitlab-ci.yml` suffix. ### Backward compatibility A template might be dynamically included with the `include:template:` keyword. If -you make a change to an *existing* template, you **must** make sure that it won't break +you make a change to an *existing* template, you **must** make sure that it doesn't break CI/CD in existing projects. For example, changing a job name in a template could break pipelines in an existing project. @@ -59,12 +59,20 @@ performance: ``` If the job name `performance` in the template is renamed to `browser-performance`, -user's `.gitlab-ci.yml` will immediately cause a lint error because there +the user's `.gitlab-ci.yml` immediately causes a lint error because there are no such jobs named `performance` in the included template anymore. Therefore, users have to fix their `.gitlab-ci.yml` that could annoy their workflow. Please read [versioning](#versioning) section for introducing breaking change safely. +### Best practices + +- Avoid using [global keywords](../../ci/yaml/README.md#global-keywords), + such as `image`, `stages` and `variables` at top-level. + When a root `.gitlab-ci.yml` [includes](../../ci/yaml/README.md#include) + multiple templates, these global keywords could be overridden by the + others and cause an unexpected behavior. + ## Versioning Versioning allows you to introduce a new template without modifying the existing @@ -103,7 +111,7 @@ If the `latest` template does not exist yet, you can copy [the stable template]( Users may want to use an older [stable template](#stable-version) that is not bundled in the current GitLab package. For example, the stable templates in GitLab v13.0 and -GitLab v14.0 could be so different that a user will want to continue using the v13.0 template even +GitLab v14.0 could be so different that a user wants to continue using the v13.0 template even after upgrading to GitLab 14.0. You can add a note in the template or in documentation explaining how to use `include:remote` @@ -152,7 +160,7 @@ When you add a template into one of those directories, make sure that it correct ### Write an RSpec test -You should write an RSpec test to make sure that pipeline jobs will be generated correctly: +You should write an RSpec test to make sure that pipeline jobs are generated correctly: 1. Add a test file at `spec/lib/gitlab/ci/templates/<template-category>/<template-name>_spec.rb` 1. Test that pipeline jobs are properly created via `Ci::CreatePipelineService`. @@ -163,10 +171,10 @@ When you introduce a breaking change to [a `latest` template](#latest-version), you must: 1. Test the upgrade path from [the stable template](#stable-version). -1. Verify what kind of errors users will encounter. +1. Verify what kind of errors users encounter. 1. Document it as a troubleshooting guide. -This information will be important for users when [a stable template](#stable-version) +This information is important for users when [a stable template](#stable-version) is updated in a major version GitLab release. ## Security diff --git a/doc/development/code_review.md b/doc/development/code_review.md index 00f4cf90481..fe395dc2304 100644 --- a/doc/development/code_review.md +++ b/doc/development/code_review.md @@ -24,6 +24,7 @@ uncovered edge cases. The default approach is to choose a reviewer from your group or team for the first review. This is only a recommendation and the reviewer may be from a different team. However, it is recommended to pick someone who is a [domain expert](#domain-experts). +If your merge request touches more than one domain (for example, Dynamic Analysis and GraphQL), ask for reviews from an expert from each domain. You can read more about the importance of involving reviewer(s) in the section on the responsibility of the author below. @@ -69,14 +70,17 @@ It picks reviewers and maintainers from the list at the [engineering projects](https://about.gitlab.com/handbook/engineering/projects/) page, with these behaviors: -1. It doesn't pick people whose [GitLab status](../user/profile/index.md#current-status) - contains the string 'OOO', or the emoji is `:palm_tree:` or `:beach:`. +1. It doesn't pick people whose Slack or [GitLab status](../user/profile/index.md#current-status): + - contains the string 'OOO', 'PTO', 'Parental Leave', or 'Friends and Family' + - emoji is `:palm_tree:`, `:beach:`, `:beach_umbrella:`, `:beach_with_umbrella:`, `:ferris_wheel:`, `:thermometer:`, `:face_with_thermometer:`, `:red_circle:`, `:bulb:`, `:sun_with_face:`. 1. [Trainee maintainers](https://about.gitlab.com/handbook/engineering/workflow/code-review/#trainee-maintainer) are three times as likely to be picked as other reviewers. -1. People whose [GitLab status](../user/profile/index.md#current-status) emoji - is `:large_blue_circle:` are more likely to be picked. This applies to both reviewers and trainee maintainers. +1. Team members whose Slack or [GitLab status](../user/profile/index.md#current-status) emoji + is 🔵 `:large_blue_circle:` are more likely to be picked. This applies to both reviewers and trainee maintainers. - Reviewers with `:large_blue_circle:` are two times as likely to be picked as other reviewers. - Trainee maintainers with `:large_blue_circle:` are four times as likely to be picked as other reviewers. +1. People whose [GitLab status](../user/profile/index.md#current-status) emoji + is 🔶 `:large_orange_diamond:` are half as likely to be picked. This applies to both reviewers and trainee maintainers. 1. It always picks the same reviewers and maintainers for the same branch name (unless their OOO status changes, as in point 1). It removes leading `ce-` and `ee-`, and trailing `-ce` and `-ee`, so @@ -116,7 +120,7 @@ with [domain expertise](#domain-experts). by a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors)**. 1. If your merge request only includes end-to-end changes (*3*) **or** if the MR author is a [Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors), it must be **approved by a [Quality maintainer](https://about.gitlab.com/handbook/engineering/projects/#gitlab_maintainers_qa)** 1. If your merge request includes a new or updated [application limit](https://about.gitlab.com/handbook/product/product-processes/#introducing-application-limits), it must be **approved by a [product manager](https://about.gitlab.com/company/team/)**. -1. If your merge request includes Product Analytics (telemetry) changes, it should be reviewed and approved by a [Product analytics engineer](https://gitlab.com/gitlab-org/growth/product-analytics/engineers). +1. If your merge request includes Product Intelligence (telemetry or analytics) changes, it should be reviewed and approved by a [Product Intelligence engineer](https://gitlab.com/gitlab-org/growth/product_intelligence/engineers). - (*1*): Please note that specs other than JavaScript specs are considered backend code. - (*2*): We encourage you to seek guidance from a database maintainer if your merge @@ -336,6 +340,7 @@ experience, refactors the existing code). Then: convey your intent. - For non-mandatory suggestions, decorate with (non-blocking) so the author knows they can optionally resolve within the merge request or follow-up at a later stage. + - There's a [Chrome/Firefox addon](https://gitlab.com/conventionalcomments/conventional-comments-button) which you can use to apply [Conventional Comment](https://conventionalcomments.org/) prefixes. - After a round of line notes, it can be helpful to post a summary note such as "Looks good to me", or "Just a couple things to address." - Assign the merge request to the author if changes are required following your @@ -505,7 +510,7 @@ and get on with their work quickly. If you think you are at capacity and are unable to accept any more reviews until some have been completed, communicate this through your GitLab status by setting -the `:red_circle:` emoji and mentioning that you are at capacity in the status +the 🔴 `:red_circle:` emoji and mentioning that you are at capacity in the status text. This guides contributors to pick a different reviewer, helping us to meet the SLO. diff --git a/doc/development/contributing/style_guides.md b/doc/development/contributing/style_guides.md index bfaee407cb8..c316d50c88c 100644 --- a/doc/development/contributing/style_guides.md +++ b/doc/development/contributing/style_guides.md @@ -112,14 +112,14 @@ the `.rubocop_todo.yml`. This also allows us greater visibility into the excepti which are currently being resolved. One way to generate the initial list is to run the todo auto generation, -with `exclude limit` set to a high number. +with `exclude limit` set to a high number. ```shell bundle exec rubocop --auto-gen-config --auto-gen-only-exclude --exclude-limit=10000 ``` -You can then move the list from the freshly generated `.rubocop_todo.yml` for the Cop being actively -resolved and place it in the `.rubocop_manual_todo.yml`. In this scenario, do not commit auto generated +You can then move the list from the freshly generated `.rubocop_todo.yml` for the Cop being actively +resolved and place it in the `.rubocop_manual_todo.yml`. In this scenario, do not commit auto generated changes to the `.rubocop_todo.yml` as an `exclude limit` that is higher than 15 will make the `.rubocop_todo.yml` hard to parse. diff --git a/doc/development/database/strings_and_the_text_data_type.md b/doc/development/database/strings_and_the_text_data_type.md index 8b839e929c7..33a0fd2ebb7 100644 --- a/doc/development/database/strings_and_the_text_data_type.md +++ b/doc/development/database/strings_and_the_text_data_type.md @@ -11,11 +11,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w When adding new columns that will be used to store strings or other textual information: 1. We always use the `text` data type instead of the `string` data type. -1. `text` columns should always have a limit set by using the `add_text_limit` migration helper. +1. `text` columns should always have a limit set, either by using the `create_table_with_constraints` helper +when creating a table, or by using the `add_text_limit` when altering an existing table. -The `text` data type can not be defined with a limit, so `add_text_limit` is enforcing that by -adding a [check constraint](https://www.postgresql.org/docs/11/ddl-constraints.html) on the -column and then validating it at a followup step. +The `text` data type can not be defined with a limit, so `create_table_with_constraints` and `add_text_limit` enforce +that by adding a [check constraint](https://www.postgresql.org/docs/11/ddl-constraints.html) on the column. ## Background information @@ -48,20 +48,15 @@ class CreateDbGuides < ActiveRecord::Migration[6.0] DOWNTIME = false - disable_ddl_transaction! - def up - unless table_exists?(:db_guides) - create_table :db_guides do |t| - t.bigint :stars, default: 0, null: false - t.text :title - t.text :notes - end - end + create_table_with_constraints :db_guides do |t| + t.bigint :stars, default: 0, null: false + t.text :title + t.text :notes - # The following add the constraints and validate them immediately (no data in the table) - add_text_limit :db_guides, :title, 128 - add_text_limit :db_guides, :notes, 1024 + t.text_limit :title, 128 + t.text_limit :notes, 1024 + end end def down @@ -71,12 +66,8 @@ class CreateDbGuides < ActiveRecord::Migration[6.0] end ``` -Adding a check constraint requires an exclusive lock while the `ALTER TABLE` that adds is running. -As we don't want the exclusive lock to be held for the duration of a transaction, `add_text_limit` -must always run in a migration with `disable_ddl_transaction!`. - -Also, note that we have to add a check that the table exists so that the migration can be repeated -in case of a failure. +Note that the `create_table_with_constraints` helper uses the `with_lock_retries` helper +internally, so we don't need to manually wrap the method call in the migration. ## Add a text column to an existing table diff --git a/doc/development/database_review.md b/doc/development/database_review.md index f0c265df9ab..da2c93cc1fd 100644 --- a/doc/development/database_review.md +++ b/doc/development/database_review.md @@ -25,9 +25,9 @@ A database review is required for: generally up to the author of a merge request to decide whether or not complex queries are being introduced and if they require a database review. -- Changes in usage data metrics that use `count` and `distinct_count`. +- Changes in usage data metrics that use `count`, `distinct_count` and `estimate_batch_distinct_count`. These metrics could have complex queries over large tables. - See the [Product Analytics Guide](https://about.gitlab.com/handbook/product/product-analytics-guide/) + See the [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) for implementation details. A database reviewer is expected to look out for obviously complex diff --git a/doc/development/documentation/feature_flags.md b/doc/development/documentation/feature_flags.md index 59298c5345f..7547ec59fb2 100644 --- a/doc/development/documentation/feature_flags.md +++ b/doc/development/documentation/feature_flags.md @@ -37,12 +37,10 @@ therefore, it indicates that it cannot be done by regular users of GitLab.com. ### Features disabled by default -For features disabled by default, if they cannot be used yet due to lack of -completeness, or if they're still under internal evaluation (for example, for -performance implications) do **not document them**: add (or merge) the docs -only when the feature is safe and ready to use and test by end-users. +For features disabled by default, add or improve the docs with every change in line with the +[definition of done](../contributing/merge_request_workflow.md#definition-of-done). -For feature flags disabled by default, if they can be used by end users: +Include details of the feature flag in the documentation: - Say that it's disabled by default. - Say whether it's enabled on GitLab.com. diff --git a/doc/development/documentation/index.md b/doc/development/documentation/index.md index 5fb5e9b433a..55f5d43b175 100644 --- a/doc/development/documentation/index.md +++ b/doc/development/documentation/index.md @@ -173,7 +173,7 @@ There are two types of redirects: - Redirect files added into the docs themselves, for users who view the docs in `/help` on self-managed instances. For example, [`/help` on GitLab.com](https://gitlab.com/help). - Redirects in a [`_redirects`](../../user/project/pages/redirects.md) file, for users - who view the docs on <http://docs.gitlab.com>. + who view the docs on <https://docs.gitlab.com>. To add a redirect: @@ -201,6 +201,9 @@ To add a redirect: 1. If the document being moved has any Disqus comments on it, follow the steps described in [Redirections for pages with Disqus comments](#redirections-for-pages-with-disqus-comments). + 1. If a documentation page you're removing includes images that aren't used + with any other documentation pages, be sure to use your MR to delete + those images from the repository. 1. Assign the MR to a technical writer for review and merge. 1. If the redirect is to one of the 4 internal docs projects (not an external URL), create an MR in [`gitlab-docs`](https://gitlab.com/gitlab-org/gitlab-docs): @@ -366,6 +369,19 @@ You can combine one or more of the following: = link_to 'Help page', help_page_path('user/permissions') ``` +#### Linking to `/help` in JavaScript + +To link to the documentation from a JavaScript or a Vue component, use the `helpPagePath` function from [`help_page_helper.js`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/assets/javascripts/helpers/help_page_helper.js): + +```javascript +import { helpPagePath } from '~/helpers/help_page_helper'; + +helpPagePath('user/permissions', { anchor: 'anchor-link' }) +// evaluates to '/help/user/permissions#anchor-link' for GitLab.com +``` + +This is preferred over static paths, as the helper also works on instances installed under a [relative URL](../../install/relative_url.md). + ### GitLab `/help` tests Several [RSpec tests](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/features/help_pages_spec.rb) diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md index 971652f76d3..bba94c7de7e 100644 --- a/doc/development/documentation/styleguide/index.md +++ b/doc/development/documentation/styleguide/index.md @@ -22,7 +22,7 @@ You can also view a list of [recent updates to this guide](https://gitlab.com/da If you can't find what you need: - View the GitLab Handbook for [writing style guidelines](https://about.gitlab.com/handbook/communication/#writing-style-guidelines) that apply to all GitLab content. -- Refer to one of the following: +- Refer to: - [Microsoft Style Guide](https://docs.microsoft.com/en-us/style-guide/welcome/). - [Google Developer Documentation Style Guide](https://developers.google.com/style). @@ -161,7 +161,7 @@ Markdown rendering engine. For a complete Kramdown reference, see the The [`gitlab-kramdown`](https://gitlab.com/gitlab-org/gitlab_kramdown) Ruby gem plans to support all [GitLab Flavored Markdown](../../../user/markdown.md) in the future, which is all Markdown supported for display in the GitLab application itself. For now, use -regular Markdown, following the rules in the linked style guide. +regular Markdown and follow the rules in the linked style guide. Kramdown-specific markup (for example, `{:.class}`) doesn't render properly on GitLab instances under [`/help`](../index.md#gitlab-help). @@ -207,9 +207,9 @@ Some examples fail if incorrect capitalization is used: Additionally, commands, parameters, values, filenames, and so on must be included in backticks. For example: -- "Change the `needs` keyword in your `.gitlab.yml`..." - - `needs` is a parameter, and `.gitlab.yml` is a file, so both need backticks. - Additionally, `.gitlab.yml` without backticks fails markdownlint because it +- "Change the `needs` keyword in your `.gitlab-ci.yml`..." + - `needs` is a parameter, and `.gitlab-ci.yml` is a file, so both need backticks. + Additionally, `.gitlab-ci.yml` without backticks fails markdownlint because it does not have capital G or L. - "Run `git clone` to clone a Git repository..." - `git clone` is a command, so it must be lowercase, while Git is the product, @@ -252,7 +252,7 @@ Put files for a specific product area into the related folder: ### Work with directories and files -Refer to the following items when working with directories and files: +When working with directories and files: 1. When you create a new directory, always start with an `index.md` file. Don't use another filename and _do not_ create `README.md` files. @@ -332,7 +332,7 @@ GitLab documentation should be clear and easy to understand. ### Trademark Only use the GitLab name and trademarks in accordance with -[GitLab Brand Guidelines](https://about.gitlab.com/handbook/marketing/inbound-marketing/digital-experience/brand-guidelines/#trademark). +[GitLab Brand Guidelines](https://about.gitlab.com/handbook/marketing/corporate-marketing/brand-activation/brand-guidelines/#trademark). Don't use the possessive form of the word GitLab (`GitLab's`). @@ -412,7 +412,7 @@ references to user interface elements. For example: ### Inclusive language We strive to create documentation that's inclusive. This section includes -guidance and examples for the following categories: +guidance and examples for these categories: - [Gender-specific wording](#avoid-gender-specific-wording). (Tested in [`InclusionGender.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/InclusionGender.yml).) @@ -481,7 +481,7 @@ more precise and functional, such as `primary` and `secondary`. <!-- vale gitlab.InclusionCultural = YES --> -For more information see the following [Internet Draft specification](https://tools.ietf.org/html/draft-knodel-terminology-02). +For more information see the [Internet Draft specification](https://tools.ietf.org/html/draft-knodel-terminology-02). ### Fake user information @@ -499,7 +499,8 @@ addresses and names, do use: When including sample URLs in the documentation, use: - `example.com` when the domain name is generic. -- `gitlab.example.com` when referring to self-managed instances of GitLab. +- `gitlab.example.com` when referring only to self-managed GitLab instances. + Use `gitlab.com` for GitLab SaaS instances. ### Fake tokens @@ -507,12 +508,11 @@ There may be times where a token is needed to demonstrate an API call using cURL or a variable used in CI. It is strongly advised not to use real tokens in documentation even if the probability of a token being exploited is low. -You can use the following fake tokens as examples: +You can use these fake tokens as examples: | Token type | Token value | |:----------------------|:-------------------------------------------------------------------| -| Private user token | `<your_access_token>` | -| Personal access token | `n671WNGecHugsdEDPsyo` | +| Personal access token | `<your_access_token>` | | Application ID | `2fcb195768c39e9a94cec2c2e32c59c0aad7a3365c10892e8116b5d83d4096b6` | | Application secret | `04f294d1eaca42b8692017b426d53bbc8fe75f827734f0260710b83a556082df` | | CI/CD variable | `Li8j-mLUVA3eZYjPfd_H` | @@ -526,11 +526,14 @@ You can use the following fake tokens as examples: ### Usage list <!-- vale off --> -| Usage | Guidance | -|-----------------------|-----| -| admin, admin area | Use **administration**, **administrator**, **administer**, or **Admin Area** instead. |. +| Usage | Guidance | +|-----------------------|----------| +| above | Try to avoid extra words when referring to an example or table in a documentation page, but if required, use **previously** instead. | +| admin, admin area | Use **administration**, **administrator**, **administer**, or **Admin Area** instead. ([Vale](../testing.md#vale) rule: [`Admin.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/Admin.yml)) | +| allow, enable | Try to avoid, unless you are talking about security-related features. For example, instead of "This feature allows you to create a pipeline," use "Use this feature to create a pipeline." This phrasing is more active and is from the user perspective, rather than the person who implemented the feature. [View details](https://docs.microsoft.com/en-us/style-guide/a-z-word-list-term-collections/a/allow-allows). | | and/or | Use **or** instead, or another sensible construction. | -| currently | Do not use when talking about the product or its features. The documentation describes the product as it is today. | +| below | Try to avoid extra words when referring to an example or table in a documentation page, but if required, use **following** instead. | +| currently | Do not use when talking about the product or its features. The documentation describes the product as it is today. ([Vale](../testing.md#vale) rule: [`CurrentStatus.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/CurrentStatus.yml)) | | easily | Do not use. If the user doesn't find the process to be these things, we lose their trust. | | e.g. | Do not use Latin abbreviations. Use **for example**, **such as**, **for instance**, or **like** instead. ([Vale](../testing.md#vale) rule: [`LatinTerms.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/LatinTerms.yml)) | | future tense | When possible, use present tense instead. For example, use `after you execute this command, GitLab displays the result` instead of `after you execute this command, GitLab will display the result`. ([Vale](../testing.md#vale) rule: [`FutureTense.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FutureTense.yml)) | @@ -865,7 +868,7 @@ Consider installing a plugin or extension in your editor for formatting tables: When creating tables of lists of features (such the features available to each role on the [Permissions](../../../user/permissions.md#project-members-permissions) -page), use the following phrases: +page), use these phrases: | Option | Markdown | Displayed result | |--------|--------------------------|------------------------| @@ -967,7 +970,7 @@ Links are important in GitLab documentation. They allow you to [link instead of summarizing](#link-instead-of-summarize) to help preserve a [single source of truth](#why-a-single-source-of-truth) in GitLab documentation. -We include guidance for links in the following categories: +We include guidance for links in these categories: - How to set up [anchor links](#anchor-links) for headings. - How to set up [criteria](#basic-link-criteria) for configuring a link. @@ -1137,14 +1140,14 @@ When documenting navigation through the user interface: - Use the exact wording as shown in the UI, including any capital letters as-is. - Use bold text for navigation items and the char "greater than" (`>`) as a - separator. For example: `Navigate to your project's **Settings > CI/CD**`. + separator. For example: `From your project, go to **Settings > CI/CD**`. - If there are any expandable menus, make sure to mention that the user needs to expand the tab to find the settings you're referring to. For example: - `Navigate to your project's **Settings > CI/CD** and expand **General pipelines**`. + `From your group, go to **Settings > CI/CD** and expand **General pipelines**`. ### Navigational elements -Use the following terms when referring to the main GitLab user interface +Use these terms when referring to the main GitLab user interface elements: - **Top menu**: This is the top menu that spans the width of the user interface. @@ -1183,7 +1186,7 @@ When you take screenshots: - Save the image with a lowercase filename that's descriptive of the feature or concept in the image. If the image is of the GitLab interface, append the - GitLab version to the filename, based on the following format: + GitLab version to the filename, based on this format: `image_name_vX_Y.png`. For example, for a screenshot taken from the pipelines page of GitLab 11.1, a valid name is `pipelines_v11_1.png`. If you're adding an illustration that doesn't include parts of the user interface, add the release @@ -1365,7 +1368,7 @@ hidden on the documentation site, but is displayed by `/help`. <!-- vale on --> Syntax highlighting is required for fenced code blocks added to the GitLab -documentation. Refer to the following table for the most common language classes, +documentation. Refer to this table for the most common language classes, or check the [complete list](https://github.com/rouge-ruby/rouge/wiki/List-of-supported-languages-and-lexers) of available language classes: @@ -1433,15 +1436,15 @@ Usage examples: Icons should be used sparingly, and only in ways that aid and do not hinder the readability of the text. -For example, the following adds little to the accompanying text: +For example, this Markdown adds little to the accompanying text: ```markdown -1. Go to **{home}** **Project overview > Details** +1. Go to **{home}** **Project overview > Details**. ``` -1. Go to **{home}** **Project overview > Details** +1. Go to **{home}** **Project overview > Details**. -However, the following might help the reader connect the text to the user +However, these tables might help the reader connect the text to the user interface: ```markdown @@ -1555,14 +1558,12 @@ It renders on the GitLab documentation site as: ## Terms -To maintain consistency through GitLab documentation, the following guides -documentation authors on agreed styles and usage of terms. +To maintain consistency through GitLab documentation, use these styles and terms. ### Merge requests (MRs) Merge requests allow you to exchange changes you made to source code and -collaborate with other people on the same project. This term is used in -the following ways: +collaborate with other people on the same project. - Use lowercase _merge requests_ regardless of whether referring to the feature or individual merge requests. @@ -1580,7 +1581,7 @@ Examples: ### Describe UI elements -The following are styles to follow when describing user interface elements in an +Follow these styles when you're describing user interface elements in an application: - For elements with a visible label, use that label in bold with matching case. @@ -1590,7 +1591,7 @@ application: ### Verbs for UI elements -The following are recommended verbs for specific uses with user interface +Use these verbs for specific uses with user interface elements: | Recommended | Used for | Replaces | @@ -1637,7 +1638,7 @@ displayed for the page or feature. #### Version text in the **Version History** -If all content in a section is related, add version text following the header +If all content in a section is related, add version text after the header for the section. The version information must be surrounded by blank lines, and each entry should be on its own line. @@ -1670,8 +1671,8 @@ the blockquote to use a bulleted list: If a feature is moved to another tier: ```markdown -> - [Moved](<link-to-issue>) from [GitLab Premium](https://about.gitlab.com/pricing/) to [GitLab Starter](https://about.gitlab.com/pricing/) in 11.8. -> - [Moved](<link-to-issue>) from [GitLab Starter](https://about.gitlab.com/pricing/) to GitLab Core in 12.0. +> - [Moved](<link-to-issue>) from GitLab Premium to GitLab Starter in 11.8. +> - [Moved](<link-to-issue>) from GitLab Starter to GitLab Core in 12.0. ``` If a feature is deprecated, include a link to a replacement (when available): @@ -1709,7 +1710,7 @@ voters to agree. #### End-of-life for features or products When a feature or product enters its end-of-life, indicate its status by -creating a [warning alert](#alert-boxes) directly following its relevant header. +creating a [warning alert](#alert-boxes) directly after its relevant header. If possible, link to its deprecation and removal issues. For example: diff --git a/doc/development/documentation/testing.md b/doc/development/documentation/testing.md index d2e3f473532..561727648f0 100644 --- a/doc/development/documentation/testing.md +++ b/doc/development/documentation/testing.md @@ -183,7 +183,8 @@ Vale configuration is found in the following projects: - [`charts`](https://gitlab.com/gitlab-org/charts/gitlab/-/tree/master/doc/.vale/gitlab) - [`gitlab-development-kit`](https://gitlab.com/gitlab-org/gitlab-development-kit/-/tree/master/doc/.vale/gitlab) -This configuration is also used within build pipelines. +This configuration is also used within build pipelines, where +[error-level rules](#vale-result-types) are enforced. You can use Vale: @@ -197,14 +198,17 @@ You can use Vale: Vale returns three types of results: `suggestion`, `warning`, and `error`: - **Suggestion**-level results are writing tips and aren't displayed in CI - job output. Suggestions don't break CI. + job output. Suggestions don't break CI. See a list of + [suggestion-level rules](https://gitlab.com/search?utf8=✓&snippets=false&scope=&repository_ref=master&search=path%3Adoc%2F.vale%2Fgitlab+Suggestion%3A&group_id=9970&project_id=278964). - **Warning**-level results are [Style Guide](styleguide/index.md) violations, aren't displayed in CI job output, and should contain clear explanations of how to resolve the warning. Warnings may be technical debt, or can be future error-level test items - (after the Technical Writing team completes its cleanup). Warnings don't break CI. + (after the Technical Writing team completes its cleanup). Warnings don't break CI. See a list of + [warning-level rules](https://gitlab.com/search?utf8=✓&snippets=false&scope=&repository_ref=master&search=path%3Adoc%2F.vale%2Fgitlab+Warning%3A&group_id=9970&project_id=278964). - **Error**-level results are Style Guide violations, and should contain clear explanations about how to resolve the error. Errors break CI and are displayed in CI job output. - of how to resolve the error. Errors break CI and are displayed in CI job output. + of how to resolve the error. Errors break CI and are displayed in CI job output. See a list of + [error-level rules](https://gitlab.com/search?utf8=✓&snippets=false&scope=&repository_ref=master&search=path%3Adoc%2F.vale%2Fgitlab+Error%3A&group_id=9970&project_id=278964). ### Install linters diff --git a/doc/development/elasticsearch.md b/doc/development/elasticsearch.md index 1c92601dde9..8bf8a5fccb8 100644 --- a/doc/development/elasticsearch.md +++ b/doc/development/elasticsearch.md @@ -216,6 +216,9 @@ cron worker sequentially. Any update to the Elastic index mappings should be replicated in [`Elastic::Latest::Config`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/lib/elastic/latest/config.rb). +Migrations can be built with a retry limit and have the ability to be [failed and marked as halted](https://gitlab.com/gitlab-org/gitlab/-/blob/66e899b6637372a4faf61cfd2f254cbdd2fb9f6d/ee/lib/elastic/migration.rb#L40). +Any data or index cleanup needed to support migration retries should be handled within the migration. + ### Migration options supported by the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb) - `batched!` - Allow the migration to run in batches. If set, the [`Elastic::MigrationWorker`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/app/workers/elastic/migration_worker.rb) @@ -337,3 +340,48 @@ cluster.routing.allocation.disk.watermark.high: 10gb Restart Elasticsearch, and the `read_only_allow_delete` will clear on it's own. _from "Disk-based Shard Allocation | Elasticsearch Reference" [5.6](https://www.elastic.co/guide/en/elasticsearch/reference/5.6/disk-allocator.html#disk-allocator) and [6.x](https://www.elastic.co/guide/en/elasticsearch/reference/6.7/disk-allocator.html)_ + +### Disaster recovery/data loss/backups + +The use of Elasticsearch in GitLab is only ever as a secondary data store. +This means that all of the data stored in Elasticsearch can always be derived +again from other data sources, specifically PostgreSQL and Gitaly. Therefore if +the Elasticsearch data store is ever corrupted for whatever reason you can +simply reindex everything from scratch. + +If your Elasticsearch index is incredibly large it may be too time consuming or +cause too much downtime to reindex from scratch. There aren't any built in +mechanisms for automatically finding discrepencies and resyncing an +Elasticsearch index if it gets out of sync but one tool that may be useful is +looking at the logs for all the updates that occurred in a time range you +believe may have been missed. This information is very low level and only +useful for operators that are familiar with the GitLab codebase. It is +documented here in case it is useful for others. The relevant logs that could +theoretically be used to figure out what needs to be replayed are: + +1. All non-repository updates that were synced can be found in + [`elasticsearch.log`](../administration/logs.md#elasticsearchlog) by + searching for + [`track_items`](https://gitlab.com/gitlab-org/gitlab/-/blob/1e60ea99bd8110a97d8fc481e2f41cab14e63d31/ee/app/services/elastic/process_bookkeeping_service.rb#L25) + and these can be replayed by sending these items again through + `::Elastic::ProcessBookkeepingService.track!` +1. All repository updates that occurred can be found in + [`elasticsearch.log`](../administration/logs.md#elasticsearchlog) by + searching for + [`indexing_commit_range`](https://gitlab.com/gitlab-org/gitlab/-/blob/6f9d75dd3898536b9ec2fb206e0bd677ab59bd6d/ee/lib/gitlab/elastic/indexer.rb#L41). + Replaying these requires resetting the + [`IndexStatus#last_commit/last_wiki_commit`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/models/index_status.rb) + to the oldest `from_sha` in the logs and then triggering another index of + the project using + [`ElasticCommitIndexerWorker`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/elastic_commit_indexer_worker.rb) +1. All project deletes that occurred can be found in + [`sidekiq.log`](../administration/logs.md#sidekiqlog) by searching for + [`ElasticDeleteProjectWorker`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/app/workers/elastic_delete_project_worker.rb). + These updates can be replayed by triggering another + `ElasticDeleteProjectWorker`. + +With the above methods and taking regular [Elasticsearch +snapshots](https://www.elastic.co/guide/en/elasticsearch/reference/current/snapshot-restore.html) +we should be able to recover from different kinds of data loss issues in a +relatively short period of time compared to indexing everything from +scratch. diff --git a/doc/development/event_tracking/backend.md b/doc/development/event_tracking/backend.md index 24e83ffc524..e8b8e0c4885 100644 --- a/doc/development/event_tracking/backend.md +++ b/doc/development/event_tracking/backend.md @@ -1,8 +1,8 @@ --- -redirect_to: '../product_analytics/index.md' +redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/' --- -This document was moved to [another location](../product_analytics/index.md). +This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/). -<!-- This redirect file can be deleted after February 1, 2021. --> +<!-- This redirect file can be deleted after December 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/event_tracking/frontend.md b/doc/development/event_tracking/frontend.md index 24e83ffc524..e8b8e0c4885 100644 --- a/doc/development/event_tracking/frontend.md +++ b/doc/development/event_tracking/frontend.md @@ -1,8 +1,8 @@ --- -redirect_to: '../product_analytics/index.md' +redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/' --- -This document was moved to [another location](../product_analytics/index.md). +This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/). -<!-- This redirect file can be deleted after February 1, 2021. --> +<!-- This redirect file can be deleted after December 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/event_tracking/index.md b/doc/development/event_tracking/index.md index 24e83ffc524..e8b8e0c4885 100644 --- a/doc/development/event_tracking/index.md +++ b/doc/development/event_tracking/index.md @@ -1,8 +1,8 @@ --- -redirect_to: '../product_analytics/index.md' +redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/' --- -This document was moved to [another location](../product_analytics/index.md). +This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/). -<!-- This redirect file can be deleted after February 1, 2021. --> +<!-- This redirect file can be deleted after December 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/experiment_guide/index.md b/doc/development/experiment_guide/index.md index 35cd55b199c..a1899ab5f18 100644 --- a/doc/development/experiment_guide/index.md +++ b/doc/development/experiment_guide/index.md @@ -145,7 +145,7 @@ addressed. To determine whether the experiment is a success or not, we must implement tracking events to acquire data for analyzing. We can send events to Snowplow via either the backend or frontend. -Read the [product analytics guide](https://about.gitlab.com/handbook/product/product-analytics-guide/) for more details. +Read the [product intelligence guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) for more details. #### Track backend events @@ -281,13 +281,19 @@ Note that this data is completely separate from the [events tracking data](#impl #### Add context -You can add arbitrary context data in a hash which gets stored as part of the experiment user record. +You can add arbitrary context data in a hash which gets stored as part of the experiment user record. New calls to the `record_experiment_user` with newer contexts get merged deeply into the existing context. + This data can then be used by data analytics dashboards. ```ruby before_action do - record_experiment_user(:signup_flow, foo: 42) + record_experiment_user(:signup_flow, foo: 42, bar: { a: 22}) + # context is { "foo" => 42, "bar" => { "a" => 22 }} end + +# Additional contexts for newer record calls are merged deeply +record_experiment_user(:signup_flow, foo: 40, bar: { b: 2 }, thor: 3) +# context becomes { "foo" => 40, "bar" => { "a" => 22, "b" => 2 }, "thor" => 3} ``` ### Record experiment conversion event @@ -337,6 +343,27 @@ to the URL: https://gitlab.com/<EXPERIMENT_ENTRY_URL>?force_experiment=<EXPERIMENT_KEY> ``` +### A cookie-based approach to force an experiment + +It's possible to force the current user to be in the experiment group for `<EXPERIMENT_KEY>` +during the browser session by using your browser's developer tools: + +```javascript +document.cookie = "force_experiment=<EXPERIMENT_KEY>; path=/"; +``` + +Use a comma to list more than one experiment to be forced: + +```javascript +document.cookie = "force_experiment=<EXPERIMENT_KEY>,<ANOTHER_EXPERIMENT_KEY>; path=/"; +``` + +Clear the experiments by unsetting the `force_experiment` cookie: + +```javascript +document.cookie = "force_experiment=; path=/"; +``` + ### Testing and test helpers #### RSpec diff --git a/doc/development/fe_guide/dependencies.md b/doc/development/fe_guide/dependencies.md index 0ec10399ae0..b036819cde1 100644 --- a/doc/development/fe_guide/dependencies.md +++ b/doc/development/fe_guide/dependencies.md @@ -8,12 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w ## Package manager -We use [Yarn](https://yarnpkg.com/) to manage frontend dependencies. There are a few exceptions: - -- [FontAwesome](https://fontawesome.com/), installed via the `font-awesome-rails` gem: we are working to replace it with - [GitLab SVGs](https://gitlab-org.gitlab.io/gitlab-svgs/) icons library. -- [ACE](https://ace.c9.io/) editor, installed via the `ace-rails-ap` gem. -- Other dependencies found under `vendor/assets/`. +We use [Yarn](https://yarnpkg.com/) to manage frontend dependencies. There are a few exceptions, stored in `vendor/assets/`. ## Updating dependencies diff --git a/doc/development/fe_guide/editor_lite.md b/doc/development/fe_guide/editor_lite.md index 465d64ff63c..47ef85d8737 100644 --- a/doc/development/fe_guide/editor_lite.md +++ b/doc/development/fe_guide/editor_lite.md @@ -104,7 +104,14 @@ someActionFunction() { ## Extensions -Editor Lite has been built to provide a universal, extensible editing tool to the whole product, which would not depend on any particular group. Even though the Editor Lite's core is owned by [Create::Editor FE Team](https://about.gitlab.com/handbook/engineering/development/dev/create-editor-fe/), the main functional elements — extensions — can be owned by any group. Editor Lite extensions' main idea is that the core of the editor remains very slim and stable. At the same time, whatever new functionality is needed can be added as an extension to this core, without touching the core itself. It allows any group to build and own any new editing functionality without being afraid of it being broken or overridden with the Editor Lite changes. +Editor Lite has been built to provide a universal, extensible editing tool to the whole product, +which would not depend on any particular group. Even though the Editor Lite's core is owned by +[Create::Editor FE Team](https://about.gitlab.com/handbook/engineering/development/dev/create-editor/), +the main functional elements — extensions — can be owned by any group. Editor Lite extensions' main idea +is that the core of the editor remains very slim and stable. At the same time, whatever new functionality +is needed can be added as an extension to this core, without touching the core itself. It allows any group +to build and own any new editing functionality without being afraid of it being broken or overridden with +the Editor Lite changes. Structurally, the complete implementation of Editor Lite could be presented as the following diagram: diff --git a/doc/development/fe_guide/event_tracking.md b/doc/development/fe_guide/event_tracking.md index 24e83ffc524..e8b8e0c4885 100644 --- a/doc/development/fe_guide/event_tracking.md +++ b/doc/development/fe_guide/event_tracking.md @@ -1,8 +1,8 @@ --- -redirect_to: '../product_analytics/index.md' +redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/' --- -This document was moved to [another location](../product_analytics/index.md). +This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/). -<!-- This redirect file can be deleted after February 1, 2021. --> +<!-- This redirect file can be deleted after December 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/fe_guide/graphql.md b/doc/development/fe_guide/graphql.md index b1896863af9..cbaa648570c 100644 --- a/doc/development/fe_guide/graphql.md +++ b/doc/development/fe_guide/graphql.md @@ -815,7 +815,7 @@ it('calls mutation on submitting form ', () => { ### Testing with mocked Apollo Client -To test the logic of Apollo cache updates, we might want to mock an Apollo Client in our unit tests. We use [`mock-apollo-client`](https://www.npmjs.com/package/mock-apollo-client) library to mock Apollo client and [`createMockApollo` helper](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/frontend/helpers/mock_apollo_helper.js) we created on top of it. +To test the logic of Apollo cache updates, we might want to mock an Apollo Client in our unit tests. We use [`mock-apollo-client`](https://www.npmjs.com/package/mock-apollo-client) library to mock Apollo client and [`createMockApollo` helper](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/frontend/__helpers__/mock_apollo_helper.js) we created on top of it. To separate tests with mocked client from 'usual' unit tests, it's recommended to create an additional factory and pass the created `mockApollo` as an option to the `createComponent`-factory. This way we only create Apollo Client instance when it's necessary. @@ -887,7 +887,7 @@ describe('Some component with Apollo mock', () => { After this, we need to create a mock Apollo Client instance using a helper: ```javascript -import createMockApollo from 'jest/helpers/mock_apollo_helper'; +import createMockApollo from 'helpers/mock_apollo_helper'; describe('Some component', () => { let wrapper; @@ -1031,7 +1031,6 @@ the following Apollo Client warning when passing only handlers: ```shell Unexpected call of console.warn() with: - Warning: mock-apollo-client - The query is entirely client-side (using @client directives) and resolvers have been configured. The request handler will not be called. ``` diff --git a/doc/development/fe_guide/icons.md b/doc/development/fe_guide/icons.md index 1468e886220..af587a31bbb 100644 --- a/doc/development/fe_guide/icons.md +++ b/doc/development/fe_guide/icons.md @@ -18,8 +18,6 @@ We are using SVG Icons in GitLab with a SVG Sprite. This means the icons are only loaded once, and are referenced through an ID. The sprite SVG is located under `/assets/icons.svg`. -Our goal is to replace one by one all inline SVG Icons (as those currently bloat the HTML) and also all Font Awesome icons. - ### Usage in HAML/Rails To use a sprite Icon in HAML or Rails we use a specific helper function: @@ -90,11 +88,6 @@ Please use the following function inside JS to render an icon: ### Usage in HAML/Rails -WARNING: -Do not use the `spinner` or `icon('spinner spin')` rails helpers to insert -loading icons. These helpers rely on the Font Awesome icon library which is -deprecated. - To insert a loading spinner in HAML or Rails use the `loading_icon` helper: ```haml diff --git a/doc/development/fe_guide/performance.md b/doc/development/fe_guide/performance.md index 7825c89b7cf..aac2258f3a3 100644 --- a/doc/development/fe_guide/performance.md +++ b/doc/development/fe_guide/performance.md @@ -43,7 +43,7 @@ It takes several arguments of which the measurement’s name is the only one req performance.measure('My component', 'my-component-start', 'my-component-end') ``` -- Duration between a mark and the moment the measurement is taken. The end mark is omitted in +- Duration between a mark and the moment the measurement is taken. The end mark is omitted in this case. ```javascript @@ -197,7 +197,7 @@ app-*-end // for an end ‘mark’ app-* // for ‘measure’ ``` -For example, `'webide-init-editor-start`, `mr-diffs-mark-file-tree-end`, and so on. We do it to +For example, `'webide-init-editor-start`, `mr-diffs-mark-file-tree-end`, and so on. We do it to help identify marks and measures coming from the different apps on the same page. ## Best Practices diff --git a/doc/development/fe_guide/style/javascript.md b/doc/development/fe_guide/style/javascript.md index 8e3538e891d..faf03a03101 100644 --- a/doc/development/fe_guide/style/javascript.md +++ b/doc/development/fe_guide/style/javascript.md @@ -7,7 +7,7 @@ disqus_identifier: 'https://docs.gitlab.com/ee/development/fe_guide/style_guide_ # JavaScript style guide -We use [Airbnb's JavaScript Style Guide](https://github.com/airbnb/javascript) and it's accompanying +We use [Airbnb's JavaScript Style Guide](https://github.com/airbnb/javascript) and its accompanying linter to manage most of our JavaScript style guidelines. In addition to the style guidelines set by Airbnb, we also have a few specific rules diff --git a/doc/development/fe_guide/style/vue.md b/doc/development/fe_guide/style/vue.md index b85c1b1de35..0288238a9e5 100644 --- a/doc/development/fe_guide/style/vue.md +++ b/doc/development/fe_guide/style/vue.md @@ -119,7 +119,8 @@ Please check this [rules](https://github.com/vuejs/eslint-plugin-vue#bulb-rules) ## Naming -1. **Extensions**: Use `.vue` extension for Vue components. Do not use `.js` as file extension ([#34371](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34371)). +1. **Extensions**: Use `.vue` extension for Vue components. Do not use `.js` as file extension +([#34371](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/34371)). 1. **Reference Naming**: Use PascalCase for their instances: ```javascript @@ -402,7 +403,8 @@ When using `v-for` you need to provide a *unique* `:key` attribute for each item </div> ``` -1. When using `v-for` with `template` and there is more than one child element, the `:key` values must be unique. It's advised to use `kebab-case` namespaces. +1. When using `v-for` with `template` and there is more than one child element, the `:key` values +must be unique. It's advised to use `kebab-case` namespaces. ```html <template v-for="(item, index) in items"> @@ -468,9 +470,10 @@ Useful links: ## Vue testing -Over time, a number of programming patterns and style preferences have emerged in our efforts to effectively test Vue components. -The following guide describes some of these. **These are not strict guidelines**, but rather a collection of suggestions and -good practices that aim to provide insight into how we write Vue tests at GitLab. +Over time, a number of programming patterns and style preferences have emerged in our efforts to +effectively test Vue components. The following guide describes some of these. +**These are not strict guidelines**, but rather a collection of suggestions and good practices that +aim to provide insight into how we write Vue tests at GitLab. ### Mounting a component @@ -479,8 +482,10 @@ Typically, when testing a Vue component, the component should be "re-mounted" in To achieve this: 1. Create a mutable `wrapper` variable inside the top-level `describe` block. -1. Mount the component using [`mount`](https://vue-test-utils.vuejs.org/api/#mount)/[`shallowMount`](https://vue-test-utils.vuejs.org/api/#shallowMount). -1. Reassign the resulting [`Wrapper`](https://vue-test-utils.vuejs.org/api/wrapper/#wrapper) instance to our `wrapper` variable. +1. Mount the component using [`mount`](https://vue-test-utils.vuejs.org/api/#mount)/ +[`shallowMount`](https://vue-test-utils.vuejs.org/api/#shallowMount). +1. Reassign the resulting [`Wrapper`](https://vue-test-utils.vuejs.org/api/wrapper/#wrapper) +instance to our `wrapper` variable. Creating a global, mutable wrapper provides a number of advantages, including the ability to: @@ -497,14 +502,16 @@ Creating a global, mutable wrapper provides a number of advantages, including th }) ``` -- Use a `beforeEach` block to mount the component (see [the `createComponent` factory](#the-createcomponent-factory) for more information). +- Use a `beforeEach` block to mount the component (see +[the `createComponent` factory](#the-createcomponent-factory) for more information). - Use an `afterEach` block to destroy the component, for example, `wrapper.destroy()`. #### The `createComponent` factory To avoid duplicating our mounting logic, it's useful to define a `createComponent` factory function that we can reuse in each test block. This is a closure which should reassign our `wrapper` variable -to the result of [`mount`](https://vue-test-utils.vuejs.org/api/#mount) and [`shallowMount`](https://vue-test-utils.vuejs.org/api/#shallowMount): +to the result of [`mount`](https://vue-test-utils.vuejs.org/api/#mount) and +[`shallowMount`](https://vue-test-utils.vuejs.org/api/#shallowMount): ```javascript import MyComponent from '~/path/to/my_component.vue'; @@ -568,7 +575,8 @@ describe('MyComponent', () => { 1. Consider using a single (or a limited number of) object arguments over many arguments. Defining single parameters for common data like `props` is okay, - but keep in mind our [JavaScript style guide](javascript.md#limit-number-of-parameters) and stay within the parameter number limit: + but keep in mind our [JavaScript style guide](javascript.md#limit-number-of-parameters) and + stay within the parameter number limit: ```javascript // bad @@ -591,6 +599,19 @@ the mounting function (`mount` or `shallowMount`) to be used to mount the compon function createComponent({ mountFn = shallowMount } = {}) { } ``` +1. Wrap calls to `mount` and `shallowMount` in `extendedWrapper`, this exposes `wrapper.findByTestId()`: + + ```javascript + import { shallowMount } from '@vue/test-utils'; + import { extendedWrapper } from 'helpers/vue_test_utils_helper'; + import { SomeComponent } from 'components/some_component.vue'; + + let wrapper; + + const createWrapper = () => { wrapper = extendedWrapper(shallowMount(SomeComponent)); }; + const someButton = () => wrapper.findByTestId('someButtonTestId'); + ``` + ### Setting component state 1. Avoid using [`setProps`](https://vue-test-utils.vuejs.org/api/wrapper/#setprops) to set @@ -609,12 +630,13 @@ component state wherever possible. Instead, set the component's ``` The exception here is when you wish to test component reactivity in some way. - For example, you may want to test the output of a component when after a particular watcher has executed. - Using `setProps` to test such behavior is okay. + For example, you may want to test the output of a component when after a particular watcher has + executed. Using `setProps` to test such behavior is okay. ### Accessing component state -1. When accessing props or attributes, prefer the `wrapper.props('myProp')` syntax over `wrapper.props().myProp`: +1. When accessing props or attributes, prefer the `wrapper.props('myProp')` syntax over +`wrapper.props().myProp` or `wrapper.vm.myProp`: ```javascript // good @@ -626,7 +648,8 @@ component state wherever possible. Instead, set the component's expect(wrapper.attributes('myAttr')).toBe(true); ``` -1. When asserting multiple props, check the deep equality of the `props()` object with [`toEqual`](https://jestjs.io/docs/en/expect#toequalvalue): +1. When asserting multiple props, check the deep equality of the `props()` object with +[`toEqual`](https://jestjs.io/docs/en/expect#toequalvalue): ```javascript // good @@ -642,8 +665,9 @@ component state wherever possible. Instead, set the component's }); ``` -1. If you are only interested in some of the props, you can use [`toMatchObject`](https://jestjs.io/docs/en/expect#tomatchobjectobject). -Prefer `toMatchObject` over [`expect.objectContaining`](https://jestjs.io/docs/en/expect#expectobjectcontainingobject): +1. If you are only interested in some of the props, you can use +[`toMatchObject`](https://jestjs.io/docs/en/expect#tomatchobjectobject). Prefer `toMatchObject` +over [`expect.objectContaining`](https://jestjs.io/docs/en/expect#expectobjectcontainingobject): ```javascript // good @@ -664,12 +688,24 @@ Prefer `toMatchObject` over [`expect.objectContaining`](https://jestjs.io/docs/e The goal of this accord is to make sure we are all on the same page. 1. When writing Vue, you may not use jQuery in your application. - 1. If you need to grab data from the DOM, you may query the DOM 1 time while bootstrapping your application to grab data attributes using `dataset`. You can do this without jQuery. + 1. If you need to grab data from the DOM, you may query the DOM 1 time while bootstrapping your + application to grab data attributes using `dataset`. You can do this without jQuery. 1. You may use a jQuery dependency in Vue.js following [this example from the docs](https://vuejs.org/v2/examples/select2.html). - 1. If an outside jQuery Event needs to be listen to inside the Vue application, you may use jQuery event listeners. - 1. We avoid adding new jQuery events when they are not required. Instead of adding new jQuery events take a look at [different methods to do the same task](https://vuejs.org/v2/api/#vm-emit). -1. You may query the `window` object one time, while bootstrapping your application for application specific data (e.g. `scrollTo` is ok to access anytime). Do this access during the bootstrapping of your application. -1. You may have a temporary but immediate need to create technical debt by writing code that does not follow our standards, to be refactored later. Maintainers need to be ok with the tech debt in the first place. An issue should be created for that tech debt to evaluate it further and discuss. In the coming months you should fix that tech debt, with its priority to be determined by maintainers. -1. When creating tech debt you must write the tests for that code before hand and those tests may not be rewritten. e.g. jQuery tests rewritten to Vue tests. -1. You may choose to use VueX as a centralized state management. If you choose not to use VueX, you must use the *store pattern* which can be found in the [Vue.js documentation](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch). -1. Once you have chosen a centralized state-management solution you must use it for your entire application. i.e. Don't mix and match your state-management solutions. + 1. If an outside jQuery Event needs to be listen to inside the Vue application, you may use + jQuery event listeners. + 1. We avoid adding new jQuery events when they are not required. Instead of adding new jQuery + events take a look at [different methods to do the same task](https://vuejs.org/v2/api/#vm-emit). +1. You may query the `window` object one time, while bootstrapping your application for application +specific data (for example, `scrollTo` is ok to access anytime). Do this access during the +bootstrapping of your application. +1. You may have a temporary but immediate need to create technical debt by writing code that does +not follow our standards, to be refactored later. Maintainers need to be ok with the tech debt in +the first place. An issue should be created for that tech debt to evaluate it further and discuss. +In the coming months you should fix that tech debt, with its priority to be determined by maintainers. +1. When creating tech debt you must write the tests for that code before hand and those tests may +not be rewritten. For example, jQuery tests rewritten to Vue tests. +1. You may choose to use VueX as a centralized state management. If you choose not to use VueX, you +must use the *store pattern* which can be found in the +[Vue.js documentation](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch). +1. Once you have chosen a centralized state-management solution you must use it for your entire +application. Don't mix and match your state-management solutions. diff --git a/doc/development/fe_guide/vue.md b/doc/development/fe_guide/vue.md index 41fbd128631..b3fbb9556a9 100644 --- a/doc/development/fe_guide/vue.md +++ b/doc/development/fe_guide/vue.md @@ -22,7 +22,8 @@ All new features built with Vue.js must follow a [Flux architecture](https://fac The main goal we are trying to achieve is to have only one data flow and only one data entry. In order to achieve this goal we use [vuex](#vuex). -You can also read about this architecture in Vue docs about [state management](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch) +You can also read about this architecture in Vue docs about +[state management](https://vuejs.org/v2/guide/state-management.html#Simple-State-Management-from-Scratch) and about [one way data flow](https://vuejs.org/v2/guide/components.html#One-Way-Data-Flow). ### Components and Store @@ -62,14 +63,15 @@ Be sure to read about [page-specific JavaScript](performance.md#page-specific-ja While mounting a Vue application, you might need to provide data from Rails to JavaScript. To do that, you can use the `data` attributes in the HTML element and query them while mounting the application. -You should only do this while initializing the application, because the mounted element is replaced with a Vue-generated DOM. +You should only do this while initializing the application, because the mounted element is replaced +with a Vue-generated DOM. -The advantage of providing data from the DOM to the Vue instance through `props` in the `render` function -instead of querying the DOM inside the main Vue component is avoiding the need to create a fixture or an HTML element in the unit test, -which makes the tests easier. +The advantage of providing data from the DOM to the Vue instance through `props` in the `render` +function instead of querying the DOM inside the main Vue component is avoiding the need to create a +fixture or an HTML element in the unit test, which makes the tests easier. -See the following example, also, please refer to our [Vue style guide](style/vue.md#basic-rules) for additional -information on why we explicitly declare the data being passed into the Vue app; +See the following example, also, please refer to our [Vue style guide](style/vue.md#basic-rules) for +additional information on why we explicitly declare the data being passed into the Vue app; ```javascript // haml @@ -94,13 +96,15 @@ return new Vue({ }); ``` -> When adding an `id` attribute to mount a Vue application, please make sure this `id` is unique across the codebase +> When adding an `id` attribute to mount a Vue application, please make sure this `id` is unique +across the codebase. #### Accessing the `gl` object -When we need to query the `gl` object for data that doesn't change during the application's life cycle, we should do it in the same place where we query the DOM. -By following this practice, we can avoid the need to mock the `gl` object, which makes tests easier. -It should be done while initializing our Vue instance, and the data should be provided as `props` to the main component: +When we need to query the `gl` object for data that doesn't change during the application's life +cycle, we should do it in the same place where we query the DOM. By following this practice, we can +avoid the need to mock the `gl` object, which makes tests easier. It should be done while +initializing our Vue instance, and the data should be provided as `props` to the main component: ```javascript return new Vue({ @@ -192,13 +196,18 @@ Check this [page](vuex.md) for more details. In the [Vue documentation](https://vuejs.org/v2/api/#Options-Data) the Data function/object is defined as follows: -> The data object for the Vue instance. Vue recursively converts its properties into getter/setters to make it “reactive”. The object must be plain: native objects such as browser API objects and prototype properties are ignored. A rule of thumb is that data should just be data - it is not recommended to observe objects with their own stateful behavior. +> The data object for the Vue instance. Vue recursively converts its properties into getter/setters +to make it “reactive”. The object must be plain: native objects such as browser API objects and +prototype properties are ignored. A rule of thumb is that data should just be data - it is not +recommended to observe objects with their own stateful behavior. Based on the Vue guidance: -- **Do not** use or create a JavaScript class in your [data function](https://vuejs.org/v2/api/#data), such as `user: new User()`. +- **Do not** use or create a JavaScript class in your [data function](https://vuejs.org/v2/api/#data), +such as `user: new User()`. - **Do not** add new JavaScript class implementations. -- **Do** use [GraphQL](../api_graphql_styleguide.md), [Vuex](vuex.md) or a set of components if cannot use simple primitives or objects. +- **Do** use [GraphQL](../api_graphql_styleguide.md), [Vuex](vuex.md) or a set of components if +cannot use simple primitives or objects. - **Do** maintain existing implementations using such approaches. - **Do** Migrate components to a pure object model when there are substantial changes to it. - **Do** add business logic to helpers or utils, so you can test them separately from your component. @@ -209,7 +218,8 @@ There are additional reasons why having a JavaScript class presents maintainabil - Once a class is created, it is easy to extend it in a way that can infringe Vue reactivity and best practices. - A class adds a layer of abstraction, which makes the component API and its inner workings less clear. -- It makes it harder to test. Since the class is instantiated by the component data function, it is harder to 'manage' component and class separately. +- It makes it harder to test. Since the class is instantiated by the component data function, it is +harder to 'manage' component and class separately. - Adding OOP to a functional codebase adds yet another way of writing code, reducing consistency and clarity. ## Style guide @@ -231,6 +241,7 @@ Here's an example of a well structured unit test for [this Vue component](#appen ```javascript import { shallowMount } from '@vue/test-utils'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; import { GlLoadingIcon } from '@gitlab/ui'; import MockAdapter from 'axios-mock-adapter'; import axios from '~/lib/utils/axios_utils'; @@ -263,19 +274,21 @@ describe('~/todos/app.vue', () => { }); // It is very helpful to separate setting up the component from - // its collaborators (i.e. Vuex, axios, etc.) + // its collaborators (for example, Vuex and axios). const createWrapper = (props = {}) => { - wrapper = shallowMount(App, { - propsData: { - path: TEST_TODO_PATH, - ...props, - }, - }); + wrapper = extendedWrapper( + shallowMount(App, { + propsData: { + path: TEST_TODO_PATH, + ...props, + }, + }) + ); }; // Helper methods greatly help test maintainability and readability. const findLoader = () => wrapper.find(GlLoadingIcon); - const findAddButton = () => wrapper.find('[data-testid="add-button"]'); - const findTextInput = () => wrapper.find('[data-testid="text-input"]'); + const findAddButton = () => wrapper.findByTestId('add-button'); + const findTextInput = () => wrapper.findByTestId('text-input'); const findTodoData = () => wrapper.findAll('[data-testid="todo-item"]').wrappers.map(wrapper => ({ text: wrapper.text() })); describe('when mounted and loading', () => { @@ -323,11 +336,41 @@ describe('~/todos/app.vue', () => { The main return value of a Vue component is the rendered output. In order to test the component we need to test the rendered output. Visit the [Vue testing guide](https://vuejs.org/v2/guide/testing.html#Unit-Testing). +### Child components + +1. Test any directive that defines if/how child component is rendered (for example, `v-if` and `v-for`). +1. Test any props we are passing to child components (especially if the prop is calculated in the +component under test, with the `computed` property, for example). Remember to use `.props()` and not `.vm.someProp`. +1. Test we react correctly to any events emitted from child components: + + ```javascript + const checkbox = wrapper.findByTestId('checkboxTestId'); + + expect(checkbox.attributes('disabled')).not.toBeDefined(); + + findChildComponent().vm.$emit('primary'); + await nextTick(); + + expect(checkbox.attributes('disabled')).toBeDefined(); + ``` + +1. **Do not** test the internal implementation of the child components: + + ```javascript + // bad + expect(findChildComponent().find('.error-alert').exists()).toBe(false); + + // good + expect(findChildComponent().props('withAlertContainer')).toBe(false); + ``` + ### Events -We should test for events emitted in response to an action within our component, this is useful to verify the correct events are being fired with the correct arguments. +We should test for events emitted in response to an action within our component, this is useful to +verify the correct events are being fired with the correct arguments. -For any DOM events we should use [`trigger`](https://vue-test-utils.vuejs.org/api/wrapper/#trigger) to fire out event. +For any DOM events we should use [`trigger`](https://vue-test-utils.vuejs.org/api/wrapper/#trigger) +to fire out event. ```javascript // Assuming SomeButton renders: <button>Some button</button> @@ -342,7 +385,8 @@ it('should fire the click event', () => { }) ``` -When we need to fire a Vue event, we should use [`emit`](https://vuejs.org/v2/guide/components-custom-events.html) to fire our event. +When we need to fire a Vue event, we should use [`emit`](https://vuejs.org/v2/guide/components-custom-events.html) +to fire our event. ```javascript wrapper = shallowMount(DropdownItem); @@ -355,7 +399,8 @@ it('should fire the itemClicked event', () => { }) ``` -We should verify an event has been fired by asserting against the result of the [`emitted()`](https://vue-test-utils.vuejs.org/api/wrapper/#emitted) method +We should verify an event has been fired by asserting against the result of the +[`emitted()`](https://vue-test-utils.vuejs.org/api/wrapper/#emitted) method. ## Vue.js Expert Role @@ -371,7 +416,8 @@ You should only apply to be a Vue.js expert when your own merge requests and you > This section is added temporarily to support the efforts to migrate the codebase from Vue 2.x to Vue 3.x -Currently, we recommend to minimize adding certain features to the codebase to prevent increasing the tech debt for the eventual migration: +Currently, we recommend to minimize adding certain features to the codebase to prevent increasing +the tech debt for the eventual migration: - filters; - event buses; @@ -382,7 +428,8 @@ You can find more details on [Migration to Vue 3](vue3_migration.md) ## Appendix - Vue component subject under test -This is the template for the example component which is tested in the [Testing Vue components](#testing-vue-components) section: +This is the template for the example component which is tested in the +[Testing Vue components](#testing-vue-components) section: ```html <template> diff --git a/doc/development/feature_categorization/index.md b/doc/development/feature_categorization/index.md index dd69d7bcf80..2f0f8101b53 100644 --- a/doc/development/feature_categorization/index.md +++ b/doc/development/feature_categorization/index.md @@ -122,7 +122,7 @@ the actions used in configuration still exist as routes. ## API endpoints The [GraphQL API](../../api/graphql/index.md) is currently categorized -as `not_owned`. For now, no extra specification is needed. For more +as `not_owned`. For now, no extra specification is needed. For more information, see [`gitlab-com/gl-infra/scalability#583`](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/583/). diff --git a/doc/development/feature_flags/controls.md b/doc/development/feature_flags/controls.md index 7551199aa58..adcf3175c45 100644 --- a/doc/development/feature_flags/controls.md +++ b/doc/development/feature_flags/controls.md @@ -250,6 +250,7 @@ Changes to the issue format can be submitted in the Any feature flag change that affects any GitLab instance is automatically logged in [features_json.log](../../administration/logs.md#features_jsonlog). You can search the change history in [Kibana](https://about.gitlab.com/handbook/support/workflows/kibana.html). +You can access the feature flag change history for GitLab.com [here](https://log.gprd.gitlab.net/goto/d060337c017723084c6d97e09e591fc6). ## Cleaning up diff --git a/doc/development/feature_flags/development.md b/doc/development/feature_flags/development.md index 7c5333c9aa6..dd732a08c72 100644 --- a/doc/development/feature_flags/development.md +++ b/doc/development/feature_flags/development.md @@ -378,6 +378,18 @@ You can also enable a feature flag for a given gate: Feature.enable(:feature_flag_name, Project.find_by_full_path("root/my-project")) ``` +### Removing a feature flag locally (in development) + +When manually enabling or disabling a feature flag from the Rails console, its default value gets overwritten. +This can cause confusion when changing the flag's `default_enabled` attribute. + +To reset the feature flag to the default status, you can remove it in the rails console (`rails c`) +as follows: + +```ruby +Feature.remove(:feature_flag_name) +``` + ## Feature flags in tests Introducing a feature flag into the codebase creates an additional code path that should be tested. diff --git a/doc/development/feature_flags/index.md b/doc/development/feature_flags/index.md index 270e07ed755..e93a5b3de1b 100644 --- a/doc/development/feature_flags/index.md +++ b/doc/development/feature_flags/index.md @@ -6,24 +6,34 @@ info: "See the Technical Writers assigned to Development Guidelines: https://abo # Feature flags in development of GitLab +**NOTE**: +The documentation below covers feature flags used by GitLab to deploy its own features, which **is not** the same +as the [feature flags offered as part of the product](../../operations/feature_flags.md). + ## When to use feature flags -Starting with GitLab 11.4, developers are required to use feature flags for -non-trivial changes. Such changes include: +Developers are required to use feature flags for changes that could affect availability of existing GitLab functionality (if it only affects the new feature you're making that is probably acceptable). +Such changes include: + +1. New features in high traffic areas (e.g. a new merge request widget, new option in issues/epics, new CI functionality). +1. Complex performance improvements that may require additional testing in production (e.g. rewriting complex queries, changes to frequently used API endpoints). +1. Invasive changes to the user interface (e.g. introducing a new navigation bar, removal of a sidebar, UI element change in issues or MR interface). +1. Introducing dependencies on third-party services (e.g. adding support for importing projects). +1. Changes to features that can cause data corruption or cause data loss (e.g. features processing repository data or user uploaded content). + +Situations where you might consider not using a feature flag: + +1. Adding a new API endpoint +1. Introducing new features in low traffic areas (e.g. adding a new export functionality in the admin area/group settings/project settings) +1. Non-invasive frontend changes (e.g. changing the color of a button, or moving a UI element in a low traffic area) + +In all cases, those working on the changes should ask themselves: -- New features (e.g. a new merge request widget, epics, etc). -- Complex performance improvements that may require additional testing in - production, such as rewriting complex queries. -- Invasive changes to the user interface, such as a new navigation bar or the - removal of a sidebar. -- Adding support for importing projects from a third-party service. -- Risk of data loss +> Why do I need to add a feature flag? If I don't add one, what options do I have to control the impact on application reliability, and user experience? -In all cases, those working on the changes can best decide if a feature flag is -necessary. For example, changing the color of a button doesn't need a feature -flag, while changing the navigation bar definitely needs one. In case you are -uncertain if a feature flag is necessary, simply ask about this in the merge -request, and those reviewing the changes will likely provide you with an answer. +For perspective on why we limit our use of feature flags please see the following [video](https://www.youtube.com/watch?v=DQaGqyolOd8). + +In case you are uncertain if a feature flag is necessary, simply ask about this in an early merge request, and those reviewing the changes will likely provide you with an answer. When using a feature flag for UI elements, make sure to _also_ use a feature flag for the underlying backend code, if there is any. This ensures there is @@ -36,35 +46,29 @@ they are new features or performance improvements. By using feature flags, you can determine the impact of GitLab-directed changes, while still being able to disable those changes without having to revert an entire release. -Before using feature flags for GitLab development, review the following development guides: - -NOTE: -The feature flags used by GitLab to deploy its own features **are not** the same -as the [feature flags offered as part of the product](../../operations/feature_flags.md). - For an overview about starting with feature flags in GitLab development, use this [training template](https://gitlab.com/gitlab-com/www-gitlab-com/-/blob/master/.gitlab/issue_templates/feature-flag-training.md). -Development guides: +Before using feature flags for GitLab development, review the following development guides: -- [Process for using features flags](process.md): When you should use +1. [Process for using features flags](process.md): When you should use feature flags in the development of GitLab, what's the cost of using them, and how to include them in a release. -- [Developing with feature flags](development.md): Learn about the types of +1. [Developing with feature flags](development.md): Learn about the types of feature flags, their definition and validation, how to create them, frontend and backend details, and other information. -- [Documenting features deployed behind feature flags](../documentation/feature_flags.md): +1. [Documenting features deployed behind feature flags](../documentation/feature_flags.md): How to document features deployed behind feature flags, and how to update the documentation for features' flags when their states change. -- [Controlling feature flags](controls.md): Learn the process for deploying +1. [Controlling feature flags](controls.md): Learn the process for deploying a new feature, enabling it on GitLab.com, communicating the change, logging, and cleaning up. User guides: -- [How GitLab administrators can enable and disable features behind flags](../../administration/feature_flags.md): +1. [How GitLab administrators can enable and disable features behind flags](../../administration/feature_flags.md): An explanation for GitLab administrators about how they can enable or disable GitLab features behind feature flags. -- [What "features deployed behind flags" means to the GitLab user](../../user/feature_flags.md): +1. [What "features deployed behind flags" means to the GitLab user](../../user/feature_flags.md): An explanation for GitLab users regarding how certain features might not be available to them until they are enabled. diff --git a/doc/development/feature_flags/process.md b/doc/development/feature_flags/process.md index 2e3680bb103..7e6299c193c 100644 --- a/doc/development/feature_flags/process.md +++ b/doc/development/feature_flags/process.md @@ -148,3 +148,30 @@ they speed up the process as managing incidents now becomes _much_ easier. Once continuous deployments are easier to perform, the time to iterate on a feature is reduced even further, as you no longer need to wait weeks before your changes are available on GitLab.com. + +### The benefits of feature flags + +It may seem like feature flags are configuration, which goes against our [convention-over-configuration](https://about.gitlab.com/handbook/product/product-principles/#convention-over-configuration) +principle. However, configuration is by definition something that is user-manageable. +Feature flags are not intended to be user-editable. Instead, they are intended as a tool for Engineers +and Site Reliability Engineers to use to de-risk their changes. Feature flags are the shim that gets us +to Continuous Delivery with our mono repo and without having to deploy the entire codebase on every change. +Feature flags are created to ensure that we can safely rollout our work on our terms. +If we use Feature Flags as a configuration, we are doing it wrong and are indeed in violation of our +principles. If something needs to be configured, we should intentionally make it configuration from the +first moment. + +Some of the benefits of using development-type feature flags are: + +1. It enables Continuous Delivery for GitLab.com. +1. It significantly reduces Mean-Time-To-Recovery. +1. It helps engineers to monitor and reduce the impact of their changes gradually, at any scale, + allowing us to be more metrics-driven and execute good DevOps practices, [shifting some responsibility "left"](https://devops.com/why-its-time-for-site-reliability-engineering-to-shift-left/). +1. Controlled feature rollout timing: without feature flags, we would need to wait until a specific + deployment was complete (which at GitLab could be at any time). +1. Increased psychological safety: when a feature flag is used, an engineer has the confidence that if anything goes wrong they can quickly disable the code and minimize the impact of a change that might be risky. +1. Improved throughput: when a change is less risky because a flag exists, theoretical tests about + scalability can potentially become unnecessary or less important. This allows an engineer to + potentially test a feature on a small project, monitor the impact, and proceed. The alternative might + be to build complex benchmarks locally, or on staging, or on another GitLab deployment, which has an + outsized impact on the time it can take to build and release a feature. diff --git a/doc/development/foreign_keys.md b/doc/development/foreign_keys.md index 0f100c6b66e..37764a12f97 100644 --- a/doc/development/foreign_keys.md +++ b/doc/development/foreign_keys.md @@ -105,6 +105,8 @@ create_table :user_configs, id: false do |t| end ``` +Setting `default: nil` will ensure a primary key sequence is not created, and since the primary key +will automatically get an index, we set `index: false` to avoid creating a duplicate. You will also need to add the new primary key to the model: ```ruby diff --git a/doc/development/geo/framework.md b/doc/development/geo/framework.md index e4518ce1b57..148953dc418 100644 --- a/doc/development/geo/framework.md +++ b/doc/development/geo/framework.md @@ -287,7 +287,7 @@ For example, to add support for files referenced by a `Widget` model with a t.datetime_with_timezone :created_at, null: false t.text :last_sync_failure - t.index :widget_id, name: :index_widget_registry_on_widget_id + t.index :widget_id, name: :index_widget_registry_on_widget_id, unique: true t.index :retry_at t.index :state end @@ -743,6 +743,8 @@ available in the Admin UI. #### Releasing the feature +1. In `ee/config/feature_flags/development/geo_widget_replication.yml`, set `default_enabled: true` + 1. In `ee/app/replicators/geo/widget_replicator.rb`, delete the `self.replication_enabled_by_default?` method: ```ruby @@ -770,3 +772,260 @@ available in the Admin UI. description: 'Find widget registries on this Geo node', feature_flag: :geo_widget_replication # REMOVE THIS LINE ``` + +### Repository Replicator Strategy + +Models that refer to any repository on the disk +can be easily supported by Geo with the `Geo::RepositoryReplicatorStrategy` module. + +For example, to add support for files referenced by a `Gizmos` model with a +`gizmos` table, you would perform the following steps. + +#### Replication + +1. Include `Gitlab::Geo::ReplicableModel` in the `Gizmo` class, and specify + the Replicator class `with_replicator Geo::GizmoReplicator`. + + At this point the `Gizmo` class should look like this: + + ```ruby + # frozen_string_literal: true + + class Gizmo < ApplicationRecord + include ::Gitlab::Geo::ReplicableModel + + with_replicator Geo::GizmoReplicator + + # @param primary_key_in [Range, Gizmo] arg to pass to primary_key_in scope + # @return [ActiveRecord::Relation<Gizmo>] everything that should be synced to this node, restricted by primary key + def self.replicables_for_current_secondary(primary_key_in) + # Should be implemented. The idea of the method is to restrict + # the set of synced items depending on synchronization settings + end + + # Geo checks this method in FrameworkRepositorySyncService to avoid + # snapshotting repositories using object pools + def pool_repository + nil + end + ... + end + ``` + + Pay some attention to method `pool_repository`. Not every repository type uses + repository pooling. As Geo prefers to use repository snapshotting, it can lead to data loss. + Make sure to overwrite `pool_repository` so it returns nil for repositories that do not + have pools. + + If there is a common constraint for records to be available for replication, + make sure to also overwrite the `available_replicables` scope. + +1. Create `ee/app/replicators/geo/gizmo_replicator.rb`. Implement the + `#repository` method which should return a `<Repository>` instance, + and implement the class method `.model` to return the `Gizmo` class: + + ```ruby + # frozen_string_literal: true + + module Geo + class GizmoReplicator < Gitlab::Geo::Replicator + include ::Geo::RepositoryReplicatorStrategy + + def self.model + ::Gizmo + end + + def repository + model_record.repository + end + + def self.git_access_class + ::Gitlab::GitAccessGizmo + end + + # The feature flag follows the format `geo_#{replicable_name}_replication`, + # so here it would be `geo_gizmo_replication` + def self.replication_enabled_by_default? + false + end + end + end + ``` + +1. Generate the feature flag definition file by running the feature flag command + and running through the steps: + + ```shell + bin/feature-flag --ee geo_gizmo_replication --type development --group 'group::geo' + ``` + +1. Make sure Geo push events are created. Usually it needs some + change in the `app/workers/post_receive.rb` file. Example: + + ```ruby + def replicate_gizmo_changes(gizmo) + if ::Gitlab::Geo.primary? + gizmo.replicator.handle_after_update if gizmo + end + end + ``` + + See `app/workers/post_receive.rb` for more examples. + +1. Make sure the repository removal is also handled. You may need to add something + like the following in the destroy service of the repository: + + ```ruby + gizmo.replicator.handle_after_destroy if gizmo.repository + ``` + +1. Add this replicator class to the method `replicator_classes` in + `ee/lib/gitlab/geo.rb`: + + ```ruby + REPLICATOR_CLASSES = [ + ... + ::Geo::PackageFileReplicator, + ::Geo::GizmoReplicator + ] + end + ``` + +1. Create `ee/spec/replicators/geo/gizmo_replicator_spec.rb` and perform + the necessary setup to define the `model_record` variable for the shared + examples: + + ```ruby + # frozen_string_literal: true + + require 'spec_helper' + + RSpec.describe Geo::GizmoReplicator do + let(:model_record) { build(:gizmo) } + + include_examples 'a repository replicator' + end + ``` + +1. Create the `gizmo_registry` table, with columns ordered according to [our guidelines](../ordering_table_columns.md) so Geo secondaries can track the sync and + verification state of each Gizmo. This migration belongs in `ee/db/geo/migrate`: + + ```ruby + # frozen_string_literal: true + + class CreateGizmoRegistry < ActiveRecord::Migration[6.0] + include Gitlab::Database::MigrationHelpers + + DOWNTIME = false + + disable_ddl_transaction! + + def up + create_table :gizmo_registry, id: :bigserial, force: :cascade do |t| + t.datetime_with_timezone :retry_at + t.datetime_with_timezone :last_synced_at + t.datetime_with_timezone :created_at, null: false + t.bigint :gizmo_id, null: false + t.integer :state, default: 0, null: false, limit: 2 + t.integer :retry_count, default: 0, limit: 2 + t.text :last_sync_failure + t.boolean :force_to_redownload + t.boolean :missing_on_primary + + t.index :gizmo_id, name: :index_gizmo_registry_on_gizmo_id, unique: true + t.index :retry_at + t.index :state + end + + add_text_limit :gizmo_registry, :last_sync_failure, 255 + end + + def down + drop_table :gizmo_registry + end + end + ``` + +1. Create `ee/app/models/geo/gizmo_registry.rb`: + + ```ruby + # frozen_string_literal: true + + class Geo::GizmoRegistry < Geo::BaseRegistry + include Geo::ReplicableRegistry + + MODEL_CLASS = ::Gizmo + MODEL_FOREIGN_KEY = :gizmo_id + + belongs_to :gizmo, class_name: 'Gizmo' + end + ``` + +1. Update `REGISTRY_CLASSES` in `ee/app/workers/geo/secondary/registry_consistency_worker.rb`. +1. Add `gizmo_registry` to `ActiveSupport::Inflector.inflections` in `config/initializers_before_autoloader/000_inflections.rb`. +1. Create `ee/spec/factories/geo/gizmo_registry.rb`: + + ```ruby + # frozen_string_literal: true + + FactoryBot.define do + factory :geo_gizmo_registry, class: 'Geo::GizmoRegistry' do + gizmo + state { Geo::GizmoRegistry.state_value(:pending) } + + trait :synced do + state { Geo::GizmoRegistry.state_value(:synced) } + last_synced_at { 5.days.ago } + end + + trait :failed do + state { Geo::GizmoRegistry.state_value(:failed) } + last_synced_at { 1.day.ago } + retry_count { 2 } + last_sync_failure { 'Random error' } + end + + trait :started do + state { Geo::GizmoRegistry.state_value(:started) } + last_synced_at { 1.day.ago } + retry_count { 0 } + end + end + end + ``` + +1. Create `ee/spec/models/geo/gizmo_registry_spec.rb`: + + ```ruby + # frozen_string_literal: true + + require 'spec_helper' + + RSpec.describe Geo::GizmoRegistry, :geo, type: :model do + let_it_be(:registry) { create(:geo_gizmo_registry) } + + specify 'factory is valid' do + expect(registry).to be_valid + end + + include_examples 'a Geo framework registry' + end + ``` + +1. Make sure the newly added repository type can be accessed by a secondary. + You may need to make some changes to one of the Git access classes. + + Gizmos should now be replicated by Geo. + +#### Metrics + +You need to make the same changes as for Blob Replicator Strategy. +You need to make the same changes for the [metrics as in the Blob Replicator Strategy](#metrics). + +#### GraphQL API + +You need to make the same changes for the GraphQL API [as in the Blob Replicator Strategy](#graphql-api). + +#### Releasing the feature + +You need to make the same changes for [releasing the feature as in the Blob Replicator Strategy](#releasing-the-feature). diff --git a/doc/development/gitaly.md b/doc/development/gitaly.md index 57a4e24679c..5d062d7404e 100644 --- a/doc/development/gitaly.md +++ b/doc/development/gitaly.md @@ -27,8 +27,9 @@ have changed since then, it should still serve as a good introduction. ## Beginner's guide Start by reading the Gitaly repository's -[Beginner's guide to Gitaly contributions](https://gitlab.com/gitlab-org/gitaly/blob/master/doc/beginners_guide.md). -It describes how to set up Gitaly, the various components of Gitaly and what they do, and how to run its test suites. +[Beginner's guide to Gitaly contributions](https://gitlab.com/gitlab-org/gitaly/-/blob/master/doc/beginners_guide.md). +It describes how to set up Gitaly, the various components of Gitaly and what +they do, and how to run its test suites. ## Developing new Git features @@ -36,33 +37,17 @@ To read or write Git data, a request has to be made to Gitaly. This means that if you're developing a new feature where you need data that's not yet available in `lib/gitlab/git` changes have to be made to Gitaly. -> This is a new process that is not clearly defined yet. If you want -to contribute a Git feature and you're getting stuck, reach out to the -Gitaly team or `@jacobvosmaer-gitlab`. +There should be no new code that touches Git repositories via disk access (for example, +Rugged, `git`, `rm -rf`) anywhere in the `gitlab` repository. Anything that +needs direct access to the Git repository *must* be implemented in Gitaly, and +exposed via an RPC. -By 'new feature' we mean any method or class in `lib/gitlab/git` that is -called from outside `lib/gitlab/git`. For new methods that are called -from inside `lib/gitlab/git`, see 'Modifying existing Git features' -below. +It's often easier to develop a new feature in Gitaly if you make the changes to +GitLab that will use the new feature in a separate merge request, to be merged +immediately after the Gitaly one. This allows you to test your changes before +they are merged. -There should be no new code that touches Git repositories via -disk access (e.g. Rugged, `git`, `rm -rf`) anywhere outside -`lib/gitlab/git`. - -The process for adding new Gitaly features is: - -- exploration / prototyping -- design and create a new Gitaly RPC in [`gitaly-proto`](https://gitlab.com/gitlab-org/gitaly-proto) -- release a new version of `gitaly-proto` -- write implementation and tests for the RPC [in Gitaly](https://gitlab.com/gitlab-org/gitaly), in Go or Ruby -- release a new version of Gitaly -- write client code in GitLab CE/EE, GitLab Workhorse or GitLab Shell that calls the new Gitaly RPC - -These steps often overlap. It is possible to use an unreleased version -of Gitaly and `gitaly-proto` during testing and development. - -- See the [Gitaly repository](https://gitlab.com/gitlab-org/gitaly/blob/master/CONTRIBUTING.md#development-and-testing-with-a-custom-gitaly-proto) for instructions on writing server side code with an unreleased protocol. -- See [below](#running-tests-with-a-locally-modified-version-of-gitaly) for instructions on running GitLab CE tests with a modified version of Gitaly. +- See [below](#running-tests-with-a-locally-modified-version-of-gitaly) for instructions on running GitLab tests with a modified version of Gitaly. - In GDK run `gdk install` and restart `gdk run` (or `gdk run app`) to use a locally modified Gitaly version for development ### `gitaly-ruby` @@ -208,7 +193,7 @@ to manually run `make` again. Note that CI tests do not use your locally modified version of Gitaly. To use a custom Gitaly version in CI you need to update -GITALY_SERVER_VERSION as described at the beginning of this paragraph. +GITALY_SERVER_VERSION as described at the beginning of this section. To use a different Gitaly repository, e.g., if your changes are present on a fork, you can specify a `GITALY_REPO_URL` environment variable when @@ -244,6 +229,9 @@ the branch with the changes (`new-feature-branch`, for example): 1. Run `bundle install` to use the modified RPC client. +Re-run `bundle install` in the `gitlab` project each time the Gitaly branch +changes to embed a new SHA in the `Gemfile.lock` file. + --- [Return to Development documentation](README.md) diff --git a/doc/development/go_guide/index.md b/doc/development/go_guide/index.md index b2405f4ce2a..68210c08a00 100644 --- a/doc/development/go_guide/index.md +++ b/doc/development/go_guide/index.md @@ -171,7 +171,7 @@ sure to use at least this version to avoid `checksum mismatch` errors. We don't use object-relational mapping libraries (ORMs) at GitLab (except [ActiveRecord](https://guides.rubyonrails.org/active_record_basics.html) in Ruby on Rails). Projects can be structured with services to avoid them. -[PQ](https://github.com/lib/pq) should be enough to interact with PostgreSQL +[pgx](https://github.com/jackc/pgx) should be enough to interact with PostgreSQL databases. ### Migrations @@ -449,11 +449,10 @@ changes between minor versions can expose bugs or cause problems in our projects Once you've picked a new Go version to use, the steps to update Omnibus and CNG are: -- [Create a merge request in the CNG project](https://gitlab.com/gitlab-org/build/CNG/edit/master/ci_files/variables.yml?branch_name=update-go-version), +- [Create a merge request in the CNG project](https://gitlab.com/gitlab-org/build/CNG/-/edit/master/ci_files/variables.yml?branch_name=update-go-version), updating the `GO_VERSION` in `ci_files/variables.yml`. -- Create a merge request in the [`gitlab-omnibus-builder` project](https://gitlab.com/gitlab-org/gitlab-omnibus-builder), - updating every file in the `docker/` directory so the `GO_VERSION` is set - appropriately. [Here's an example](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/merge_requests/125/diffs). +- [Create a merge request in the `gitlab-omnibus-builder` project](https://gitlab.com/gitlab-org/gitlab-omnibus-builder/-/edit/master/docker/VERSIONS?branch_name=update-go-version), + updating the `GO_VERSION` in `docker/VERSIONS`. - Tag a new release of `gitlab-omnibus-builder` containing the change. - [Create a merge request in the `omnibus-gitlab` project](https://gitlab.com/gitlab-org/omnibus-gitlab/edit/master/.gitlab-ci.yml?branch_name=update-gitlab-omnibus-builder-version), updating the `BUILDER_IMAGE_REVISION` to match the newly-created tag. diff --git a/doc/development/gotchas.md b/doc/development/gotchas.md index 2b34aedddf6..a506b67d89d 100644 --- a/doc/development/gotchas.md +++ b/doc/development/gotchas.md @@ -270,7 +270,7 @@ This problem disappears as soon as we upgrade to Rails 6 and use the Zeitwerk au ### Further reading - Rails Guides: [Autoloading and Reloading Constants (Classic Mode)](https://guides.rubyonrails.org/autoloading_and_reloading_constants_classic_mode.html) -- Ruby Constant lookup: [Everything you ever wanted to know about constant lookup in Ruby](http://cirw.in/blog/constant-lookup) +- Ruby Constant lookup: [Everything you ever wanted to know about constant lookup in Ruby](https://cirw.in/blog/constant-lookup) - Rails 6 and Zeitwerk autoloader: [Understanding Zeitwerk in Rails 6](https://medium.com/cedarcode/understanding-zeitwerk-in-rails-6-f168a9f09a1f) ## Storing assets that do not require pre-compiling diff --git a/doc/development/img/snowplow_flow.png b/doc/development/img/snowplow_flow.png Binary files differindex 5996cf01537..aae597edc13 100644 --- a/doc/development/img/snowplow_flow.png +++ b/doc/development/img/snowplow_flow.png diff --git a/doc/development/img/stage_group_dashboards_annotation.png b/doc/development/img/stage_group_dashboards_annotation.png Binary files differnew file mode 100644 index 00000000000..3776d87e5bb --- /dev/null +++ b/doc/development/img/stage_group_dashboards_annotation.png diff --git a/doc/development/img/stage_group_dashboards_debug_1.png b/doc/development/img/stage_group_dashboards_debug_1.png Binary files differnew file mode 100644 index 00000000000..309fad89120 --- /dev/null +++ b/doc/development/img/stage_group_dashboards_debug_1.png diff --git a/doc/development/img/stage_group_dashboards_debug_2.png b/doc/development/img/stage_group_dashboards_debug_2.png Binary files differnew file mode 100644 index 00000000000..2aad9ab5592 --- /dev/null +++ b/doc/development/img/stage_group_dashboards_debug_2.png diff --git a/doc/development/img/stage_group_dashboards_debug_3.png b/doc/development/img/stage_group_dashboards_debug_3.png Binary files differnew file mode 100644 index 00000000000..38647410ffd --- /dev/null +++ b/doc/development/img/stage_group_dashboards_debug_3.png diff --git a/doc/development/img/stage_group_dashboards_filters.png b/doc/development/img/stage_group_dashboards_filters.png Binary files differnew file mode 100644 index 00000000000..27a836bc36d --- /dev/null +++ b/doc/development/img/stage_group_dashboards_filters.png diff --git a/doc/development/img/stage_group_dashboards_metrics.png b/doc/development/img/stage_group_dashboards_metrics.png Binary files differnew file mode 100644 index 00000000000..6b6faff6e3b --- /dev/null +++ b/doc/development/img/stage_group_dashboards_metrics.png diff --git a/doc/development/img/stage_group_dashboards_time_customization.png b/doc/development/img/stage_group_dashboards_time_customization.png Binary files differnew file mode 100644 index 00000000000..49e61183b7c --- /dev/null +++ b/doc/development/img/stage_group_dashboards_time_customization.png diff --git a/doc/development/img/stage_group_dashboards_time_filter.png b/doc/development/img/stage_group_dashboards_time_filter.png Binary files differnew file mode 100644 index 00000000000..81a3dc789f1 --- /dev/null +++ b/doc/development/img/stage_group_dashboards_time_filter.png diff --git a/doc/development/instrumentation.md b/doc/development/instrumentation.md index 8fb7f29c86c..94b56e10d9e 100644 --- a/doc/development/instrumentation.md +++ b/doc/development/instrumentation.md @@ -11,7 +11,7 @@ blocks of Ruby code. Method instrumentation is the primary form of instrumentation with block-based instrumentation only being used when we want to drill down to specific regions of code within a method. -Please refer to [Product Analytics](https://about.gitlab.com/handbook/product/product-analytics-guide/) if you are tracking product usage patterns. +Please refer to [Product Intelligence](https://about.gitlab.com/handbook/product/product-intelligence-guide/) if you are tracking product usage patterns. ## Instrumenting Methods diff --git a/doc/development/integrations/codesandbox.md b/doc/development/integrations/codesandbox.md index 1641f4656a0..faa1ec0ee3f 100644 --- a/doc/development/integrations/codesandbox.md +++ b/doc/development/integrations/codesandbox.md @@ -1,7 +1,7 @@ # Set up local Codesandbox development environment -This guide walks through setting up a local [Codesandbox repository](https://github.com/codesandbox/codesandbox-client) and integrating it with a local GitLab instance. Codesandbox -is used to power the Web IDE's [Live Preview feature](../../user/project/web_ide/index.md#live-preview). Having a local Codesandbox setup is useful for debugging upstream issues or +This guide walks through setting up a local [Codesandbox repository](https://github.com/codesandbox/codesandbox-client) and integrating it with a local GitLab instance. Codesandbox +is used to power the Web IDE's [Live Preview feature](../../user/project/web_ide/index.md#live-preview). Having a local Codesandbox setup is useful for debugging upstream issues or creating upstream contributions like [this one](https://github.com/codesandbox/codesandbox-client/pull/5137). ## Initial setup @@ -59,7 +59,7 @@ to use a locally-built module. To build and use a local `smooshpack` module: yarn run start ``` - Now, in the GitLab project, you can run `yarn link "smooshpack"`. `yarn` looks + Now, in the GitLab project, you can run `yarn link "smooshpack"`. `yarn` looks for `smooshpack` **on disk** as opposed to the one hosted remotely. 1. In the `gitlab` project directory, run: @@ -110,7 +110,7 @@ npx http-server --proxy http://localhost:3000 -S -C $PATH_TO_CERT_PEM -K $PATH_T ### Update `bundler_url` setting in GitLab -We need to update our `application_setting_implementation.rb` to point to the server that hosts the +We need to update our `application_setting_implementation.rb` to point to the server that hosts the Codesandbox `sandpack` assets. For instance, if these assets are hosted by a server at `https://sandpack.local:8044`: ```patch @@ -125,7 +125,7 @@ index 6eed627b502..1824669e881 100644 - 'https://sandbox-prod.gitlab-static.net' + 'https://sandpack.local:8044' end - + private ``` diff --git a/doc/development/integrations/jenkins.md b/doc/development/integrations/jenkins.md index c87b15e192a..a9a1026f1a8 100644 --- a/doc/development/integrations/jenkins.md +++ b/doc/development/integrations/jenkins.md @@ -90,7 +90,7 @@ option because the Jenkins plugin updates the build status on GitLab. In a **Pip ## Configure your GitLab project -To activate the Jenkins service you must have a Starter subscription or higher. +To activate the Jenkins service: 1. Go to your project's page, then **Settings > Integrations > Jenkins CI**. 1. Check the **Active** checkbox and the triggers for **Push** and **Merge request**. diff --git a/doc/development/integrations/jira_connect.md b/doc/development/integrations/jira_connect.md index 408b0e6068e..48beb526774 100644 --- a/doc/development/integrations/jira_connect.md +++ b/doc/development/integrations/jira_connect.md @@ -10,13 +10,20 @@ The following are required to install and test the app: - A Jira Cloud instance. Atlassian provides [free instances for development and testing](https://developer.atlassian.com/platform/marketplace/getting-started/#free-developer-instances-to-build-and-test-your-app). - A GitLab instance available over the internet. For the app to work, Jira Cloud should - be able to connect to the GitLab instance through the internet. To easily expose your - local development environment, you can use tools like: - - [serveo](https://medium.com/automationmaster/how-to-forward-my-local-port-to-public-using-serveo-4979f352a3bf) - - [ngrok](https://ngrok.com). + be able to connect to the GitLab instance through the internet. For this we + recommend using Gitpod or a similar cloud development environment. For more + information on using Gitpod with GDK, see the: - These also take care of SSL for you because Jira requires all connections to the app - host to be over SSL. + - [GDK in Gitpod](https://www.loom.com/share/9c9711d4876a40869b9294eecb24c54d) + video. + - [GDK with Gitpod](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/gitpod.md) + documentation. + + You **must not** use tunneling tools such as Serveo or `ngrok`. These are + security risks, and must not be run on developer laptops. + + Jira requires all connections to the app host to be over SSL, so if you set up + your own environment, remember to enable SSL and an appropriate certificate. ## Install the app in Jira @@ -38,7 +45,7 @@ To install the app in Jira: For example: ```plaintext - https://xxxx.serveo.net/-/jira_connect/app_descriptor.json + https://xxxx.gitpod.io/-/jira_connect/app_descriptor.json ``` 1. Click **Upload**. diff --git a/doc/development/internal_api.md b/doc/development/internal_api.md index 4971e4d629d..43655c37048 100644 --- a/doc/development/internal_api.md +++ b/doc/development/internal_api.md @@ -448,3 +448,22 @@ Example Request: ```shell curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Content-Type: application/json" --data '{"gitops_sync_count":1}' "http://localhost:3000/api/v4/internal/kubernetes/usage_metrics" ``` + +### Kubernetes agent alert metrics + +Called from GitLab Kubernetes Agent Server (KAS) to save alerts derived from Cilium on Kubernetes +Cluster. + +| Attribute | Type | Required | Description | +|:----------|:-------|:---------|:------------| +| `alert` | Hash | yes | Alerts detail. Currently same format as [3rd party alert](../operations/incident_management/alert_integrations.md#customize-the-alert-payload-outside-of-gitlab). | + +```plaintext +POST internal/kubernetes/modules/cilium_alert +``` + +Example Request: + +```shell +curl --request POST --header "Gitlab-Kas-Api-Request: <JWT token>" --header "Authorization: Bearer <agent token>" --header "Content-Type: application/json" --data '"{\"alert\":{\"title\":\"minimal\",\"message\":\"network problem\",\"evalMatches\":[{\"value\":1,\"metric\":\"Count\",\"tags\":{}}]}}"' "http://localhost:3000/api/v4/internal/kubernetes/modules/cilium_alert" +``` diff --git a/doc/development/iterating_tables_in_batches.md b/doc/development/iterating_tables_in_batches.md index 3953e7097dd..43d7f32ad7f 100644 --- a/doc/development/iterating_tables_in_batches.md +++ b/doc/development/iterating_tables_in_batches.md @@ -42,6 +42,29 @@ The API of this method is similar to `in_batches`, though it doesn't support all of the arguments that `in_batches` supports. You should always use `each_batch` _unless_ you have a specific need for `in_batches`. +## Avoid iterating over non-unique columns + +One should proceed with extra caution, and possibly avoid iterating over a column that can contain duplicate values. +When you iterate over an attribute that is not unique, even with the applied max batch size, there is no guarantee that the resulting batches will not surpass it. +The following snippet demonstrates this situation, whe one attempt to select `Ci::Build` entries for users with `id` between `1` and `10,s000`, database returns `1 215 178` +matching rows + +```ruby +[ gstg ] production> Ci::Build.where(user_id: (1..10_000)).size +=> 1215178 +``` + +This happens because built relation is translated into following query + +```ruby +[ gstg ] production> puts Ci::Build.where(user_id: (1..10_000)).to_sql +SELECT "ci_builds".* FROM "ci_builds" WHERE "ci_builds"."type" = 'Ci::Build' AND "ci_builds"."user_id" BETWEEN 1 AND 10000 +=> nil +``` + +And queries which filters non-unique column by range `WHERE "ci_builds"."user_id" BETWEEN ? AND ?`, even though the range size is limited to certain threshold (`10,000` in previous example) this threshold does not translates to the size of returned dataset. That happens because when taking `n` possible values of attributes, +one can't tell for sure that the number of records that contains them will be less than `n`. + ## Column definition `EachBatch` uses the primary key of the model by default for the iteration. This works most of the cases, however in some cases, you might want to use a different column for the iteration. @@ -55,7 +78,7 @@ end The query above iterates over the project creators and prints them out without duplications. NOTE: -In case the column is not unique (no unique index definition), calling the `distinct` method on the relation is necessary. +In case the column is not unique (no unique index definition), calling the `distinct` method on the relation is necessary. Using not unique column without `distinct` may result in `each_batch` falling into endless loop as described at following [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/285097) ## `EachBatch` in data migrations diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md index 8cdfbd558ca..e1205346585 100644 --- a/doc/development/migration_style_guide.md +++ b/doc/development/migration_style_guide.md @@ -516,12 +516,14 @@ class MyMigration < ActiveRecord::Migration[6.0] disable_ddl_transaction! + INDEX_NAME = 'index_name' + def up - add_concurrent_index :table, :column + add_concurrent_index :table, :column, name: INDEX_NAME end def down - remove_concurrent_index :table, :column, name: index_name + remove_concurrent_index :table, :column, name: INDEX_NAME end end ``` diff --git a/doc/development/new_fe_guide/development/accessibility.md b/doc/development/new_fe_guide/development/accessibility.md index 81f3773dd5c..65485104efe 100644 --- a/doc/development/new_fe_guide/development/accessibility.md +++ b/doc/development/new_fe_guide/development/accessibility.md @@ -42,7 +42,7 @@ In forms we should use the `for` attribute in the label statement: ## Testing -1. On MacOS you can use [VoiceOver](http://www.apple.com/accessibility/vision/) by pressing `cmd+F5`. +1. On MacOS you can use [VoiceOver](https://www.apple.com/accessibility/vision/) by pressing `cmd+F5`. 1. On Windows you can use [Narrator](https://www.microsoft.com/en-us/accessibility/windows) by pressing Windows logo key + Control + Enter. ## Online resources diff --git a/doc/development/packages.md b/doc/development/packages.md index 689dc6b4141..aadd71c9ffa 100644 --- a/doc/development/packages.md +++ b/doc/development/packages.md @@ -242,6 +242,24 @@ create the package record. Workhorse provides a variety of file metadata such as For testing purposes, you may want to [enable object storage](https://gitlab.com/gitlab-org/gitlab-development-kit/blob/master/doc/howto/object_storage.md) in your local development environment. +#### Rate Limits on GitLab.com + +Package manager clients can make rapid requests that exceed the +[GitLab.com standard API rate limits](../user/gitlab_com/index.md#gitlabcom-specific-rate-limits). +This results in a `429 Too Many Requests` error. + +We have opened a set of paths to allow higher rate limits. Unless it is not possible, +new package managers should follow these conventions so they can take advantage of the +expanded package rate limit. + +These route prefixes guarantee a higher rate limit: + +```plaintext +/api/v4/packages/ +/api/v4/projects/:project_id/packages/ +/api/v4/groups/:group_id/-/packages/ +``` + ### Future Work While working on the MVC, contributors might find features that are not mandatory for the MVC but can provide a better user experience. It's generally a good idea to keep an eye on those and open issues. diff --git a/doc/development/pipelines.md b/doc/development/pipelines.md index 3243c7ec753..0354e703357 100644 --- a/doc/development/pipelines.md +++ b/doc/development/pipelines.md @@ -60,7 +60,7 @@ Reference pipeline: <https://gitlab.com/gitlab-org/gitlab/pipelines/135236627> ```mermaid graph LR subgraph "No needed jobs"; - 1-1["danger-review (3.5 minutes)"]; + 1-1["danger-review (2.3 minutes)"]; click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0" 1-50["docs lint (9 minutes)"]; click 1-50 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356757&udv=0" @@ -76,23 +76,23 @@ graph RL; classDef criticalPath fill:#f66; subgraph "No needed jobs"; - 1-1["danger-review (3.5 minutes)"]; + 1-1["danger-review (2.3 minutes)"]; click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0" - 1-2["build-qa-image (2.4 minutes)"]; + 1-2["build-qa-image (1.6 minutes)"]; click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914325&udv=0" - 1-3["compile-test-assets (8.5 minutes)"]; + 1-3["compile-test-assets (7 minutes)"]; click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0" - 1-4["compile-test-assets as-if-foss (8.35 minutes)"]; + 1-4["compile-test-assets as-if-foss (7 minutes)"]; click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0" 1-5["compile-production-assets (19 minutes)"]; click 1-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914312&udv=0" - 1-6["setup-test-env (7.4 minutes)"]; + 1-6["setup-test-env (9 minutes)"]; click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0" 1-7["review-stop-failed-deployment"]; 1-8["dependency_scanning"]; 1-9["qa:internal, qa:internal-as-if-foss"]; 1-11["qa:selectors, qa:selectors-as-if-foss"]; - 1-14["retrieve-tests-metadata (1.9 minutes)"]; + 1-14["retrieve-tests-metadata (1 minutes)"]; click 1-14 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356697&udv=0" 1-15["code_quality"]; 1-16["brakeman-sast"]; @@ -100,7 +100,7 @@ graph RL; 1-18["kubesec-sast"]; 1-19["nodejs-scan-sast"]; 1-20["secrets-sast"]; - 1-21["static-analysis (17 minutes)"]; + 1-21["static-analysis (30 minutes)"]; click 1-21 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914471&udv=0" class 1-3 criticalPath; @@ -111,26 +111,26 @@ graph RL; click 2_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356715&udv=0" 2_1-2["memory-static (4.75 minutes)"]; click 2_1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356721&udv=0" - 2_1-3["run-dev-fixtures (5 minutes)"]; + 2_1-3["run-dev-fixtures (6 minutes)"]; click 2_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356729&udv=0" - 2_1-4["run-dev-fixtures-ee (5 minutes)"]; + 2_1-4["run-dev-fixtures-ee (6.75 minutes)"]; click 2_1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356731&udv=0" subgraph "Needs `setup-test-env`"; 2_1-1 & 2_1-2 & 2_1-3 & 2_1-4 --> 1-6; end - 2_2-2["frontend-fixtures (16.5 minutes)"]; + 2_2-2["rspec frontend_fixture/rspec-ee frontend_fixture (12 minutes)"]; class 2_2-2 criticalPath; click 2_2-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910143&udv=0" - 2_2-4["memory-on-boot (7.19 minutes)"]; + 2_2-4["memory-on-boot (6 minutes)"]; click 2_2-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356727&udv=0" - 2_2-5["webpack-dev-server (6.1 minutes)"]; + 2_2-5["webpack-dev-server (4.5 minutes)"]; click 2_2-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8404303&udv=0" subgraph "Needs `setup-test-env` & `compile-test-assets`"; 2_2-2 & 2_2-4 & 2_2-5 --> 1-6 & 1-3; end - 2_3-1["build-assets-image (2.5 minutes)"]; + 2_3-1["build-assets-image (1.6 minutes)"]; subgraph "Needs `compile-production-assets`"; 2_3-1 --> 1-5 end @@ -153,17 +153,17 @@ graph RL; click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0" 3_1-2["karma (4 minutes)"]; click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914200&udv=0" - subgraph "Needs `frontend-fixtures`"; + subgraph "Needs `rspec frontend_fixture/rspec-ee frontend_fixture`"; 3_1-1 & 3_1-2 --> 2_2-2; end - 3_2-1["rspec:coverage (7.5 minutes)"]; + 3_2-1["rspec:coverage (4.6 minutes)"]; subgraph "Depends on `rspec` jobs"; 3_2-1 -.->|"(don't use needs because of limitations)"| 2_5-1; click 3_2-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7248745&udv=0" end - 4_1-1["coverage-frontend (3.6 minutes)"]; + 4_1-1["coverage-frontend (2.75 minutes)"]; subgraph "Needs `jest`"; 4_1-1 --> 3_1-1; class 4_1-1 criticalPath; @@ -180,23 +180,23 @@ graph RL; classDef criticalPath fill:#f66; subgraph "No needed jobs"; - 1-1["danger-review (3.5 minutes)"]; + 1-1["danger-review (2.3 minutes)"]; click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0" - 1-2["build-qa-image (2.4 minutes)"]; + 1-2["build-qa-image (1.6 minutes)"]; click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914325&udv=0" - 1-3["compile-test-assets (8.5 minutes)"]; + 1-3["compile-test-assets (7 minutes)"]; click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0" - 1-4["compile-test-assets as-if-foss (8.35 minutes)"]; + 1-4["compile-test-assets as-if-foss (7 minutes)"]; click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0" 1-5["compile-production-assets (19 minutes)"]; click 1-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914312&udv=0" - 1-6["setup-test-env (7.4 minutes)"]; + 1-6["setup-test-env (9 minutes)"]; click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0" 1-7["review-stop-failed-deployment"]; 1-8["dependency_scanning"]; 1-9["qa:internal, qa:internal-as-if-foss"]; 1-11["qa:selectors, qa:selectors-as-if-foss"]; - 1-14["retrieve-tests-metadata (1.9 minutes)"]; + 1-14["retrieve-tests-metadata (1 minutes)"]; click 1-14 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356697&udv=0" 1-15["code_quality"]; 1-16["brakeman-sast"]; @@ -204,7 +204,7 @@ graph RL; 1-18["kubesec-sast"]; 1-19["nodejs-scan-sast"]; 1-20["secrets-sast"]; - 1-21["static-analysis (17 minutes)"]; + 1-21["static-analysis (30 minutes)"]; click 1-21 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914471&udv=0" class 1-3 criticalPath; @@ -216,26 +216,26 @@ graph RL; click 2_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356715&udv=0" 2_1-2["memory-static (4.75 minutes)"]; click 2_1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356721&udv=0" - 2_1-3["run-dev-fixtures (5 minutes)"]; + 2_1-3["run-dev-fixtures (6 minutes)"]; click 2_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356729&udv=0" - 2_1-4["run-dev-fixtures-ee (5 minutes)"]; + 2_1-4["run-dev-fixtures-ee (6.75 minutes)"]; click 2_1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356731&udv=0" subgraph "Needs `setup-test-env`"; 2_1-1 & 2_1-2 & 2_1-3 & 2_1-4 --> 1-6; end - 2_2-2["frontend-fixtures (16.5 minutes)"]; + 2_2-2["rspec frontend_fixture/rspec-ee frontend_fixture (12 minutes)"]; class 2_2-2 criticalPath; click 2_2-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7910143&udv=0" - 2_2-4["memory-on-boot (7.19 minutes)"]; + 2_2-4["memory-on-boot (6 minutes)"]; click 2_2-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356727&udv=0" - 2_2-5["webpack-dev-server (6.1 minutes)"]; + 2_2-5["webpack-dev-server (4.5 minutes)"]; click 2_2-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8404303&udv=0" subgraph "Needs `setup-test-env` & `compile-test-assets`"; 2_2-2 & 2_2-4 & 2_2-5 --> 1-6 & 1-3; end - 2_3-1["build-assets-image (2.5 minutes)"]; + 2_3-1["build-assets-image (1.6 minutes)"]; class 2_3-1 criticalPath; subgraph "Needs `compile-production-assets`"; 2_3-1 --> 1-5 @@ -266,17 +266,17 @@ graph RL; click 3_1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914204&udv=0" 3_1-2["karma (4 minutes)"]; click 3_1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914200&udv=0" - subgraph "Needs `frontend-fixtures`"; + subgraph "Needs `rspec frontend_fixture/rspec-ee frontend_fixture`"; 3_1-1 & 3_1-2 --> 2_2-2; end - 3_2-1["rspec:coverage (7.5 minutes)"]; + 3_2-1["rspec:coverage (4.6 minutes)"]; subgraph "Depends on `rspec` jobs"; 3_2-1 -.->|"(don't use needs because of limitations)"| 2_5-1; click 3_2-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=7248745&udv=0" end - 4_1-1["coverage-frontend (3.6 minutes)"]; + 4_1-1["coverage-frontend (2.75 minutes)"]; subgraph "Needs `jest`"; 4_1-1 --> 3_1-1; class 4_1-1 criticalPath; @@ -311,23 +311,23 @@ graph RL; classDef criticalPath fill:#f66; subgraph "No needed jobs"; - 1-1["danger-review (3.5 minutes)"]; + 1-1["danger-review (2.3 minutes)"]; click 1-1 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8100542&udv=0" - 1-2["build-qa-image (2.4 minutes)"]; + 1-2["build-qa-image (1.6 minutes)"]; click 1-2 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914325&udv=0" - 1-3["compile-test-assets (8.5 minutes)"]; + 1-3["compile-test-assets (7 minutes)"]; click 1-3 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914317&udv=0" - 1-4["compile-test-assets as-if-foss (8.35 minutes)"]; + 1-4["compile-test-assets as-if-foss (7 minutes)"]; click 1-4 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356616&udv=0" 1-5["compile-production-assets (19 minutes)"]; click 1-5 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914312&udv=0" - 1-6["setup-test-env (7.4 minutes)"]; + 1-6["setup-test-env (9 minutes)"]; click 1-6 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914315&udv=0" 1-7["review-stop-failed-deployment"]; 1-8["dependency_scanning"]; 1-9["qa:internal, qa:internal-as-if-foss"]; 1-11["qa:selectors, qa:selectors-as-if-foss"]; - 1-14["retrieve-tests-metadata (1.9 minutes)"]; + 1-14["retrieve-tests-metadata (1 minutes)"]; click 1-14 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=8356697&udv=0" 1-15["code_quality"]; 1-16["brakeman-sast"]; @@ -335,7 +335,7 @@ graph RL; 1-18["kubesec-sast"]; 1-19["nodejs-scan-sast"]; 1-20["secrets-sast"]; - 1-21["static-analysis (17 minutes)"]; + 1-21["static-analysis (30 minutes)"]; click 1-21 "https://app.periscopedata.com/app/gitlab/652085/Engineering-Productivity---Pipeline-Build-Durations?widget=6914471&udv=0" class 1-5 criticalPath; @@ -347,13 +347,13 @@ graph RL; 2_1-1 --> 1-6; end - 2_3-1["build-assets-image (2.5 minutes)"]; + 2_3-1["build-assets-image (1.6 minutes)"]; subgraph "Needs `compile-production-assets`"; 2_3-1 --> 1-5 class 2_3-1 criticalPath; end - 2_4-1["package-and-qa (108 minutes)"]; + 2_4-1["package-and-qa (105 minutes)"]; subgraph "Needs `build-qa-image` & `build-assets-image`"; 2_4-1 --> 1-2 & 2_3-1; class 2_4-1 criticalPath; @@ -422,24 +422,29 @@ We are using a custom mapping between source file to test files, maintained in t ### PostgreSQL versions testing +Even though [Omnibus defaults to PG12 for new installs and upgrades](https://docs.gitlab.com/omnibus/package-information/postgresql_versions.md), +our test suite is currently running against PG11, since GitLab.com still runs on PG11. + +We do run our test suite against PG12 on nightly scheduled pipelines as well as upon specific +database library changes in MRs and `master` pipelines (with the `rspec db-library-code pg12` job). + #### Current versions testing | Where? | PostgreSQL version | -| ------ | ------ | -| MRs | 11 | -| `master` (non-scheduled pipelines) | 11 | -| 2-hourly scheduled pipelines | 11 | +| ------ | ------------------ | +| MRs | 11, 12 for DB library changes | +| `master` (non-scheduled pipelines) | 11, 12 for DB library changes | +| 2-hourly scheduled pipelines | 11, 12 for DB library changes | | `nightly` scheduled pipelines | 11, 12 | #### Long-term plan We follow the [PostgreSQL versions shipped with Omnibus GitLab](https://docs.gitlab.com/omnibus/package-information/postgresql_versions.html): -| PostgreSQL version | 13.0 (May 2020) | 13.1 (June 2020) | 13.2 (July 2020) | 13.3 (August 2020) | 13.4, 13.5 | [13.7 (December 2020)](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5722) | 14.0 (May 2021?) | -| ------ | --------------- | ---------------- | ---------------- | ------------------ | ------------ | -------------------- | ---------------- | -| PG11 | MRs/`master`/`2-hour`/`nightly` | MRs/`master`/`2-hour`/`nightly` | MRs/`master`/`2-hour`/`nightly` | MRs/`master`/`2-hour`/`nightly` | MRs/`master`/`2-hour`/`nightly` | `nightly` | - | -| PG12 | - | - | `nightly` | `2-hour`/`nightly` | `2-hour`/`nightly` | MRs/`2-hour`/`nightly` | `2-hour`/`nightly` | -| PG13 | - | - | - | - | - | - | MRs/`2-hour`/`nightly` | +| PostgreSQL version | 13.7 (December 2020) | 13.8 (January 2021) | 13.9 (February 2021) | 13.10 (March 2021) | 13.11 (April 2021) | 14.0 (May 2021?) | +| -------------------| -------------------- | ------------------- | -------------------- | ------------------ | ------------------ | ---------------- | +| PG11 | MRs/`2-hour`/`nightly` | MRs/`2-hour`/`nightly` | MRs/`2-hour`/`nightly` | MRs/`2-hour`/`nightly` | MRs/`2-hour`/`nightly` | MRs/`2-hour`/`nightly` | +| PG12 | `nightly` | `nightly` | `nightly` | `nightly` | `nightly` | `nightly` | ### Test jobs @@ -504,6 +509,10 @@ request, be sure to start the `dont-interrupt-me` job before pushing. - `update-yarn-cache`, defined in [`.gitlab/ci/frontend.gitlab-ci.yml`](https://gitlab.com/gitlab-org/gitlab/blob/master/.gitlab/ci/frontend.gitlab-ci.yml). 1. These jobs run in merge requests whose title include `UPDATE CACHE`. +### Artifacts strategy + +We limit the artifacts that are saved and retrieved by jobs to the minimum in order to reduce the upload/download time and costs, as well as the artifacts storage. + ### Pre-clone step The `gitlab-org/gitlab` project on GitLab.com uses a [pre-clone step](https://gitlab.com/gitlab-org/gitlab/-/issues/39134) @@ -671,7 +680,7 @@ and included in `rules` definitions via [YAML anchors](../ci/yaml/README.md#anch | `if-master-refs` | Matches if the current branch is `master`. | | | `if-master-push` | Matches if the current branch is `master` and pipeline source is `push`. | | | `if-master-schedule-2-hourly` | Matches if the current branch is `master` and pipeline runs on a 2-hourly schedule. | | -| `if-master-schedule-2-nightly` | Matches if the current branch is `master` and pipeline runs on a nightly schedule. | | +| `if-master-schedule-nightly` | Matches if the current branch is `master` and pipeline runs on a nightly schedule. | | | `if-auto-deploy-branches` | Matches if the current branch is an auto-deploy one. | | | `if-master-or-tag` | Matches if the pipeline is for the `master` branch or for a tag. | | | `if-merge-request` | Matches if the pipeline is for a merge request. | | diff --git a/doc/development/product_analytics/event_dictionary.md b/doc/development/product_analytics/event_dictionary.md index 9c363f08cb4..e8b8e0c4885 100644 --- a/doc/development/product_analytics/event_dictionary.md +++ b/doc/development/product_analytics/event_dictionary.md @@ -1,8 +1,8 @@ --- -redirect_to: 'https://about.gitlab.com/handbook/product/product-analytics-guide/' +redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/' --- -This document was moved to [another location](https://about.gitlab.com/handbook/product/product-analytics-guide/). +This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/). -<!-- This redirect file can be deleted after February 1, 2021. --> +<!-- This redirect file can be deleted after December 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/product_analytics/index.md b/doc/development/product_analytics/index.md index 9c363f08cb4..4d2168cf304 100644 --- a/doc/development/product_analytics/index.md +++ b/doc/development/product_analytics/index.md @@ -1,8 +1,13 @@ --- -redirect_to: 'https://about.gitlab.com/handbook/product/product-analytics-guide/' +redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/' --- -This document was moved to [another location](https://about.gitlab.com/handbook/product/product-analytics-guide/). +This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/). -<!-- This redirect file can be deleted after February 1, 2021. --> +<!-- Needed by the Product Intelligence group + +Since our new standard for redirects otherwise lies within the gitlab-docs repo, +as long as we need a redirect to the handbook, we need to retain this file. + --> +<!-- This redirect file can be deleted after December 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/product_analytics/snowplow.md b/doc/development/product_analytics/snowplow.md index 48b816f0b83..bb056ffddfe 100644 --- a/doc/development/product_analytics/snowplow.md +++ b/doc/development/product_analytics/snowplow.md @@ -1,616 +1,8 @@ --- -stage: Growth -group: Product Analytics -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +redirect_to: '../snowplow.md' --- -# Snowplow Guide +This document was moved to [another location](../snowplow.md). -This guide provides an overview of how Snowplow works, and implementation details. - -For more information about Product Analytics, see: - -- [Product Analytics Guide](https://about.gitlab.com/handbook/product/product-analytics-guide/) -- [Usage Ping Guide](usage_ping.md) - -More useful links: - -- [Product Analytics Direction](https://about.gitlab.com/direction/product-analytics/) -- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/) -- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/) -- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) - -## What is Snowplow - -Snowplow is an enterprise-grade marketing and product analytics platform which helps track the way users engage with our website and application. - -[Snowplow](https://github.com/snowplow/snowplow) consists of the following loosely-coupled sub-systems: - -- **Trackers** fire Snowplow events. Snowplow has 12 trackers, covering web, mobile, desktop, server, and IoT. -- **Collectors** receive Snowplow events from trackers. We have three different event collectors, synchronizing events either to Amazon S3, Apache Kafka, or Amazon Kinesis. -- **Enrich** cleans up the raw Snowplow events, enriches them and puts them into storage. We have an Hadoop-based enrichment process, and a Kinesis-based or Kafka-based process. -- **Storage** is where the Snowplow events live. We store the Snowplow events in a flat file structure on S3, and in the Redshift and PostgreSQL databases. -- **Data modeling** is where event-level data is joined with other data sets and aggregated into smaller data sets, and business logic is applied. This produces a clean set of tables which make it easier to perform analysis on the data. We have data models for Redshift and Looker. -- **Analytics** are performed on the Snowplow events or on the aggregate tables. - -![snowplow_flow](../img/snowplow_flow.png) - -## Snowplow schema - -We have many definitions of Snowplow's schema. We have an active issue to [standardize this schema](https://gitlab.com/gitlab-org/gitlab/-/issues/207930) including the following definitions: - -- Frontend and backend taxonomy as listed below -- [Structured event taxonomy](#structured-event-taxonomy) -- [Self describing events](https://github.com/snowplow/snowplow/wiki/Custom-events#self-describing-events) -- [Iglu schema](https://gitlab.com/gitlab-org/iglu/) -- [Snowplow authored events](https://github.com/snowplow/snowplow/wiki/Snowplow-authored-events) - -## Enabling Snowplow - -Tracking can be enabled at: - -- The instance level, which enables tracking on both the frontend and backend layers. -- User level, though user tracking can be disabled on a per-user basis. GitLab tracking respects the [Do Not Track](https://www.eff.org/issues/do-not-track) standard, so any user who has enabled the Do Not Track option in their browser is not tracked at a user level. - -We use Snowplow for the majority of our tracking strategy and it is enabled on GitLab.com. On a self-managed instance, Snowplow can be enabled by navigating to: - -- **Admin Area > Settings > General** in the UI. -- `admin/application_settings/integrations` in your browser. - -The following configuration is required: - -| Name | Value | -|---------------|---------------------------| -| Collector | `snowplow.trx.gitlab.net` | -| Site ID | `gitlab` | -| Cookie domain | `.gitlab.com` | - -## Snowplow request flow - -The following example shows a basic request/response flow between the following components: - -- Snowplow JS / Ruby Trackers on GitLab.com -- [GitLab.com Snowplow Collector](https://gitlab.com/gitlab-com/gl-infra/readiness/-/blob/master/library/snowplow/index.md) -- The GitLab S3 Bucket -- The GitLab Snowflake Data Warehouse -- Sisense: - -```mermaid -sequenceDiagram - participant Snowplow JS (Frontend) - participant Snowplow Ruby (Backend) - participant GitLab.com Snowplow Collector - participant S3 Bucket - participant Snowflake DW - participant Sisense Dashboards - Snowplow JS (Frontend) ->> GitLab.com Snowplow Collector: FE Tracking event - Snowplow Ruby (Backend) ->> GitLab.com Snowplow Collector: BE Tracking event - loop Process using Kinesis Stream - GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Log raw events - GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Enrich events - GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Write to disk - end - GitLab.com Snowplow Collector ->> S3 Bucket: Kinesis Firehose - S3 Bucket->>Snowflake DW: Import data - Snowflake DW->>Snowflake DW: Transform data using dbt - Snowflake DW->>Sisense Dashboards: Data available for querying -``` - -## Structured event taxonomy - -When adding new click events, we should add them in a way that's internally consistent. If we don't, it is very painful to perform analysis across features since each feature captures events differently. - -The current method provides several attributes that are sent on each click event. Please try to follow these guidelines when specifying events to capture: - -| attribute | type | required | description | -| --------- | ------- | -------- | ----------- | -| category | text | true | The page or backend area of the application. Unless infeasible, please use the Rails page attribute by default in the frontend, and namespace + classname on the backend. | -| action | text | true | The action the user is taking, or aspect that's being instrumented. The first word should always describe the action or aspect: clicks should be `click`, activations should be `activate`, creations should be `create`, etc. Use underscores to describe what was acted on; for example, activating a form field would be `activate_form_input`. An interface action like clicking on a dropdown would be `click_dropdown`, while a behavior like creating a project record from the backend would be `create_project` | -| label | text | false | The specific element, or object that's being acted on. This is either the label of the element (e.g. a tab labeled 'Create from template' may be `create_from_template`) or a unique identifier if no text is available (e.g. closing the Groups dropdown in the top navbar might be `groups_dropdown_close`), or it could be the name or title attribute of a record being created. | -| property | text | false | Any additional property of the element, or object being acted on. | -| value | decimal | false | Describes a numeric value or something directly related to the event. This could be the value of an input (e.g. `10` when clicking `internal` visibility). | - -### Web-specific parameters - -Snowplow JS adds many [web-specific parameters](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/snowplow-tracker-protocol/#Web-specific_parameters) to all web events by default. - -## Implementing Snowplow JS (Frontend) tracking - -GitLab provides `Tracking`, an interface that wraps the [Snowplow JavaScript Tracker](https://github.com/snowplow/snowplow/wiki/javascript-tracker) for tracking custom events. There are a few ways to use tracking, but each generally requires at minimum, a `category` and an `action`. Additional data can be provided that adheres to our [Structured event taxonomy](#structured-event-taxonomy). - -| field | type | default value | description | -|:-----------|:-------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `category` | string | document.body.dataset.page | Page or subsection of a page that events are being captured within. | -| `action` | string | 'generic' | Action the user is taking. Clicks should be `click` and activations should be `activate`, so for example, focusing a form field would be `activate_form_input`, and clicking a button would be `click_button`. | -| `data` | object | {} | Additional data such as `label`, `property`, `value`, and `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). | - -### Tracking in HAML (or Vue Templates) - -When working within HAML (or Vue templates) we can add `data-track-*` attributes to elements of interest. All elements that have a `data-track-event` attribute automatically have event tracking bound on clicks. - -Below is an example of `data-track-*` attributes assigned to a button: - -```haml -%button.btn{ data: { track: { event: "click_button", label: "template_preview", property: "my-template" } } } -``` - -```html -<button class="btn" - data-track-event="click_button" - data-track-label="template_preview" - data-track-property="my-template" -/> -``` - -Event listeners are bound at the document level to handle click events on or within elements with these data attributes. This allows them to be properly handled on re-rendering and changes to the DOM. Note that because of the way these events are bound, click events should not be stopped from propagating up the DOM tree. If for any reason click events are being stopped from propagating, you need to implement your own listeners and follow the instructions in [Tracking in raw JavaScript](#tracking-in-raw-javascript). - -Below is a list of supported `data-track-*` attributes: - -| attribute | required | description | -|:----------------------|:---------|:------------| -| `data-track-event` | true | Action the user is taking. Clicks must be prepended with `click` and activations must be prepended with `activate`. For example, focusing a form field would be `activate_form_input` and clicking a button would be `click_button`. | -| `data-track-label` | false | The `label` as described in our [Structured event taxonomy](#structured-event-taxonomy). | -| `data-track-property` | false | The `property` as described in our [Structured event taxonomy](#structured-event-taxonomy). | -| `data-track-value` | false | The `value` as described in our [Structured event taxonomy](#structured-event-taxonomy). If omitted, this is the element's `value` property or an empty string. For checkboxes, the default value is the element's checked attribute or `false` when unchecked. | -| `data-track-context` | false | The `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). | - -#### Caveats - -When using the GitLab helper method [`nav_link`](https://gitlab.com/gitlab-org/gitlab/-/blob/898b286de322e5df6a38d257b10c94974d580df8/app/helpers/tab_helper.rb#L69) be sure to wrap `html_options` under the `html_options` keyword argument. -Be careful, as this behavior can be confused with the `ActionView` helper method [`link_to`](https://api.rubyonrails.org/v5.2.3/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to) that does not require additional wrapping of `html_options` - -`nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { data: { track_label: "groups_dropdown", track_event: "click_dropdown" } })` - -vs - -`link_to assigned_issues_dashboard_path, title: _('Issues'), data: { track_label: 'main_navigation', track_event: 'click_issues_link' }` - -### Tracking within Vue components - -There's a tracking Vue mixin that can be used in components if more complex tracking is required. To use it, first import the `Tracking` library and request a mixin. - -```javascript -import Tracking from '~/tracking'; -const trackingMixin = Tracking.mixin({ label: 'right_sidebar' }); -``` - -You can provide default options that are passed along whenever an event is tracked from within your component. For instance, if all events within a component should be tracked with a given `label`, you can provide one at this time. Available defaults are `category`, `label`, `property`, and `value`. If no category is specified, `document.body.dataset.page` is used as the default. - -You can then use the mixin normally in your component with the `mixin` Vue declaration. The mixin also provides the ability to specify tracking options in `data` or `computed`. These override any defaults and allow the values to be dynamic from props, or based on state. - -```javascript -export default { - mixins: [trackingMixin], - // ...[component implementation]... - data() { - return { - expanded: false, - tracking: { - label: 'left_sidebar' - } - }; - }, -} -``` - -The mixin provides a `track` method that can be called within the template, or from component methods. An example of the whole implementation might look like the following. - -```javascript -export default { - mixins: [Tracking.mixin({ label: 'right_sidebar' })], - data() { - return { - expanded: false, - }; - }, - methods: { - toggle() { - this.expanded = !this.expanded; - this.track('click_toggle', { value: this.expanded }) - } - } -}; -``` - -And if needed within the template, you can use the `track` method directly as well. - -```html -<template> - <div> - <a class="toggle" @click.prevent="toggle">Toggle</a> - <div v-if="expanded"> - <p>Hello world!</p> - <a @click.prevent="track('click_action')">Track an event</a> - </div> - </div> -</template> -``` - -### Tracking in raw JavaScript - -Custom event tracking and instrumentation can be added by directly calling the `Tracking.event` static function. The following example demonstrates tracking a click on a button by calling `Tracking.event` manually. - -```javascript -import Tracking from '~/tracking'; - -const button = document.getElementById('create_from_template_button'); -button.addEventListener('click', () => { - Tracking.event('dashboard:projects:index', 'click_button', { - label: 'create_from_template', - property: 'template_preview', - value: 'rails', - }); -}) -``` - -### Tests and test helpers - -In Jest particularly in Vue tests, you can use the following: - -```javascript -import { mockTracking } from 'helpers/tracking_helper'; - -describe('MyTracking', () => { - let spy; - - beforeEach(() => { - spy = mockTracking('_category_', wrapper.element, jest.spyOn); - }); - - it('tracks an event when clicked on feedback', () => { - wrapper.find('.discover-feedback-icon').trigger('click'); - - expect(spy).toHaveBeenCalledWith('_category_', 'click_button', { - label: 'security-discover-feedback-cta', - property: '0', - }); - }); -}); -``` - -In obsolete Karma tests it's used as below: - -```javascript -import { mockTracking, triggerEvent } from 'spec/helpers/tracking_helper'; - -describe('my component', () => { - let trackingSpy; - - beforeEach(() => { - trackingSpy = mockTracking('_category_', vm.$el, spyOn); - }); - - const triggerEvent = () => { - // action which should trigger a event - }; - - it('tracks an event when toggled', () => { - expect(trackingSpy).not.toHaveBeenCalled(); - - triggerEvent('a.toggle'); - - expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_edit_button', { - label: 'right_sidebar', - property: 'confidentiality', - }); - }); -}); -``` - -## Implementing Snowplow Ruby (Backend) tracking - -GitLab provides `Gitlab::Tracking`, an interface that wraps the [Snowplow Ruby Tracker](https://github.com/snowplow/snowplow/wiki/ruby-tracker) for tracking custom events. - -Custom event tracking and instrumentation can be added by directly calling the `GitLab::Tracking.event` class method, which accepts the following arguments: - -| argument | type | default value | description | -|:-----------|:-------|:--------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| -| `category` | string | 'application' | Area or aspect of the application. This could be `HealthCheckController` or `Lfs::FileTransformer` for instance. | -| `action` | string | 'generic' | The action being taken, which can be anything from a controller action like `create` to something like an Active Record callback. | -| `data` | object | {} | Additional data such as `label`, `property`, `value`, and `context` as described in [Structured event taxonomy](#structured-event-taxonomy). These are set as empty strings if you don't provide them. | - -Tracking can be viewed as either tracking user behavior, or can be used for instrumentation to monitor and visualize performance over time in an area or aspect of code. - -For example: - -```ruby -class Projects::CreateService < BaseService - def execute - project = Project.create(params) - - Gitlab::Tracking.event('Projects::CreateService', 'create_project', - label: project.errors.full_messages.to_sentence, - value: project.valid? - ) - end -end -``` - -### Unit testing - -Use the `expect_snowplow_event` helper when testing backend Snowplow events. See [testing best practices]( -https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#test-snowplow-events) for details. - -### Performance - -We use the [AsyncEmitter](https://github.com/snowplow/snowplow/wiki/Ruby-Tracker#52-the-asyncemitter-class) when tracking events, which allows for instrumentation calls to be run in a background thread. This is still an active area of development. - -## Developing and testing Snowplow - -There are several tools for developing and testing Snowplow Event - -| Testing Tool | Frontend Tracking | Backend Tracking | Local Development Environment | Production Environment | Production Environment | -|----------------------------------------------|--------------------|---------------------|-------------------------------|------------------------|------------------------| -| Snowplow Analytics Debugger Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** | -| Snowplow Inspector Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** | -| Snowplow Micro | **{check-circle}** | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{dotted-circle}** | -| Snowplow Mini | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{status_preparing}** | **{status_preparing}** | - -**Legend** - -**{check-circle}** Available, **{status_preparing}** In progress, **{dotted-circle}** Not Planned - -### Preparing your MR for Review - -1. For frontend events, in the MR description section, add a screenshot of the event's relevant section using the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension. -1. For backend events, please use Snowplow Micro and add the output of the Snowplow Micro good events `GET http://localhost:9090/micro/good`. - -### Snowplow Analytics Debugger Chrome Extension - -Snowplow Analytics Debugger is a browser extension for testing frontend events. This works on production, staging and local development environments. - -1. Install the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension. -1. Open Chrome DevTools to the Snowplow Analytics Debugger tab. -1. Learn more at [Igloo Analytics](https://www.iglooanalytics.com/blog/snowplow-analytics-debugger-chrome-extension.html). - -### Snowplow Inspector Chrome Extension - -Snowplow Inspector Chrome Extension is a browser extension for testing frontend events. This works on production, staging and local development environments. - -1. Install [Snowplow Inspector](https://chrome.google.com/webstore/detail/snowplow-inspector/maplkdomeamdlngconidoefjpogkmljm?hl=en). -1. Open the Chrome extension by pressing the Snowplow Inspector icon beside the address bar. -1. Click around on a webpage with Snowplow and you should see JavaScript events firing in the inspector window. - -### Snowplow Micro - -Snowplow Micro is a very small version of a full Snowplow data collection pipeline: small enough that it can be launched by a test suite. Events can be recorded into Snowplow Micro just as they can a full Snowplow pipeline. Micro then exposes an API that can be queried. - -Snowplow Micro is a Docker-based solution for testing frontend and backend events in a local development environment. You need to modify GDK using the instructions below to set this up. - -- Read [Introducing Snowplow Micro](https://snowplowanalytics.com/blog/2019/07/17/introducing-snowplow-micro/) -- Look at the [Snowplow Micro repository](https://github.com/snowplow-incubator/snowplow-micro) -- Watch our [installation guide recording](https://www.youtube.com/watch?v=OX46fo_A0Ag) - -1. Ensure Docker is installed and running. - -1. Install [Snowplow Micro](https://github.com/snowplow-incubator/snowplow-micro) by cloning the settings in [this project](https://gitlab.com/gitlab-org/snowplow-micro-configuration): -1. Navigate to the directory with the cloned project, and start the appropriate Docker - container with the following script: - - ```shell - ./snowplow-micro.sh - ``` - -1. Update your instance's settings to enable Snowplow events and point to the Snowplow Micro collector: - - ```shell - gdk psql -d gitlabhq_development - update application_settings set snowplow_collector_hostname='localhost:9090', snowplow_enabled=true, snowplow_cookie_domain='.gitlab.com'; - ``` - -1. Update `DEFAULT_SNOWPLOW_OPTIONS` in `app/assets/javascripts/tracking.js` to remove `forceSecureTracker: true`: - - ```diff - diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js - index 0a1211d0a76..3b98c8f28f2 100644 - --- a/app/assets/javascripts/tracking.js - +++ b/app/assets/javascripts/tracking.js - @@ -7,7 +7,6 @@ const DEFAULT_SNOWPLOW_OPTIONS = { - appId: '', - userFingerprint: false, - respectDoNotTrack: true, - - forceSecureTracker: true, - eventMethod: 'post', - contexts: { webPage: true, performanceTiming: true }, - formTracking: false, - - ``` - -1. Update `snowplow_options` in `lib/gitlab/tracking.rb` to add `protocol` and `port`: - - ```diff - diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb - index 618e359211b..e9084623c43 100644 - --- a/lib/gitlab/tracking.rb - +++ b/lib/gitlab/tracking.rb - @@ -41,7 +41,9 @@ def snowplow_options(group) - cookie_domain: Gitlab::CurrentSettings.snowplow_cookie_domain, - app_id: Gitlab::CurrentSettings.snowplow_app_id, - form_tracking: additional_features, - - link_click_tracking: additional_features - + link_click_tracking: additional_features, - + protocol: 'http', - + port: 9090 - }.transform_keys! { |key| key.to_s.camelize(:lower).to_sym } - end - ``` - -1. Update `emitter` in `lib/gitlab/tracking/destinations/snowplow.rb` to change `protocol`: - - ```diff - diff --git a/lib/gitlab/tracking/destinations/snowplow.rb b/lib/gitlab/tracking/destinations/snowplow.rb - index 4fa844de325..5dd9d0eacfb 100644 - --- a/lib/gitlab/tracking/destinations/snowplow.rb - +++ b/lib/gitlab/tracking/destinations/snowplow.rb - @@ -40,7 +40,7 @@ def tracker - def emitter - SnowplowTracker::AsyncEmitter.new( - Gitlab::CurrentSettings.snowplow_collector_hostname, - - protocol: 'https' - + protocol: 'http' - ) - end - end - - ``` - -1. Restart GDK: - - ```shell - `gdk restart` - ``` - -1. Send a test Snowplow event from the Rails console: - - ```ruby - Gitlab::Tracking.self_describing_event('iglu:com.gitlab/pageview_context/jsonschema/1-0-0', data: { page_type: 'MY_TYPE' }, context: nil) - ``` - -1. Navigate to `localhost:9090/micro/good` to see the event. - -### Snowplow Mini - -[Snowplow Mini](https://github.com/snowplow/snowplow-mini) is an easily-deployable, single-instance version of Snowplow. - -Snowplow Mini can be used for testing frontend and backend events on a production, staging and local development environment. - -For GitLab.com, we're setting up a [QA and Testing environment](https://gitlab.com/gitlab-org/telemetry/-/issues/266) using Snowplow Mini. - -## Snowplow Schemas - -### Default Schema - -| Field Name | Required | Type | Description | -|--------------------------|---------------------|-----------|----------------------------------------------------------------------------------------------------------------------------------| -| app_id | **{check-circle}** | string | Unique identifier for website / application | -| base_currency | **{dotted-circle}** | string | Reporting currency | -| br_colordepth | **{dotted-circle}** | integer | Browser color depth | -| br_cookies | **{dotted-circle}** | boolean | Does the browser permit cookies? | -| br_family | **{dotted-circle}** | string | Browser family | -| br_features_director | **{dotted-circle}** | boolean | Director plugin installed? | -| br_features_flash | **{dotted-circle}** | boolean | Flash plugin installed? | -| br_features_gears | **{dotted-circle}** | boolean | Google gears installed? | -| br_features_java | **{dotted-circle}** | boolean | Java plugin installed? | -| br_features_pdf | **{dotted-circle}** | boolean | Adobe PDF plugin installed? | -| br_features_quicktime | **{dotted-circle}** | boolean | Quicktime plugin installed? | -| br_features_realplayer | **{dotted-circle}** | boolean | Realplayer plugin installed? | -| br_features_silverlight | **{dotted-circle}** | boolean | Silverlight plugin installed? | -| br_features_windowsmedia | **{dotted-circle}** | boolean | Windows media plugin installed? | -| br_lang | **{dotted-circle}** | string | Language the browser is set to | -| br_name | **{dotted-circle}** | string | Browser name | -| br_renderengine | **{dotted-circle}** | string | Browser rendering engine | -| br_type | **{dotted-circle}** | string | Browser type | -| br_version | **{dotted-circle}** | string | Browser version | -| br_viewheight | **{dotted-circle}** | string | Browser viewport height | -| br_viewwidth | **{dotted-circle}** | string | Browser viewport width | -| collector_tstamp | **{dotted-circle}** | timestamp | Time stamp for the event recorded by the collector | -| contexts | **{dotted-circle}** | | | -| derived_contexts | **{dotted-circle}** | | Contexts derived in the Enrich process | -| derived_tstamp | **{dotted-circle}** | timestamp | Timestamp making allowance for innaccurate device clock | -| doc_charset | **{dotted-circle}** | string | Web page’s character encoding | -| doc_height | **{dotted-circle}** | string | Web page height | -| doc_width | **{dotted-circle}** | string | Web page width | -| domain_sessionid | **{dotted-circle}** | string | Unique identifier (UUID) for this visit of this user_id to this domain | -| domain_sessionidx | **{dotted-circle}** | integer | Index of number of visits that this user_id has made to this domain (The first visit is `1`) | -| domain_userid | **{dotted-circle}** | string | Unique identifier for a user, based on a first party cookie (so domain specific) | -| dvce_created_tstamp | **{dotted-circle}** | timestamp | Timestamp when event occurred, as recorded by client device | -| dvce_ismobile | **{dotted-circle}** | boolean | Indicates whether device is mobile | -| dvce_screenheight | **{dotted-circle}** | string | Screen / monitor resolution | -| dvce_screenwidth | **{dotted-circle}** | string | Screen / monitor resolution | -| dvce_sent_tstamp | **{dotted-circle}** | timestamp | Timestamp when event was sent by client device to collector | -| dvce_type | **{dotted-circle}** | string | Type of device | -| etl_tags | **{dotted-circle}** | string | JSON of tags for this ETL run | -| etl_tstamp | **{dotted-circle}** | timestamp | Timestamp event began ETL | -| event | **{dotted-circle}** | string | Event type | -| event_fingerprint | **{dotted-circle}** | string | Hash client-set event fields | -| event_format | **{dotted-circle}** | string | Format for event | -| event_id | **{dotted-circle}** | string | Event UUID | -| event_name | **{dotted-circle}** | string | Event name | -| event_vendor | **{dotted-circle}** | string | The company who developed the event model | -| event_version | **{dotted-circle}** | string | Version of event schema | -| geo_city | **{dotted-circle}** | string | City of IP origin | -| geo_country | **{dotted-circle}** | string | Country of IP origin | -| geo_latitude | **{dotted-circle}** | string | An approximate latitude | -| geo_longitude | **{dotted-circle}** | string | An approximate longitude | -| geo_region | **{dotted-circle}** | string | Region of IP origin | -| geo_region_name | **{dotted-circle}** | string | Region of IP origin | -| geo_timezone | **{dotted-circle}** | string | Timezone of IP origin | -| geo_zipcode | **{dotted-circle}** | string | Zip (postal) code of IP origin | -| ip_domain | **{dotted-circle}** | string | Second level domain name associated with the visitor’s IP address | -| ip_isp | **{dotted-circle}** | string | Visitor’s ISP | -| ip_netspeed | **{dotted-circle}** | string | Visitor’s connection type | -| ip_organization | **{dotted-circle}** | string | Organization associated with the visitor’s IP address – defaults to ISP name if none is found | -| mkt_campaign | **{dotted-circle}** | string | The campaign ID | -| mkt_clickid | **{dotted-circle}** | string | The click ID | -| mkt_content | **{dotted-circle}** | string | The content or ID of the ad. | -| mkt_medium | **{dotted-circle}** | string | Type of traffic source | -| mkt_network | **{dotted-circle}** | string | The ad network to which the click ID belongs | -| mkt_source | **{dotted-circle}** | string | The company / website where the traffic came from | -| mkt_term | **{dotted-circle}** | string | Keywords associated with the referrer | -| name_tracker | **{dotted-circle}** | string | The tracker namespace | -| network_userid | **{dotted-circle}** | string | Unique identifier for a user, based on a cookie from the collector (so set at a network level and shouldn’t be set by a tracker) | -| os_family | **{dotted-circle}** | string | Operating system family | -| os_manufacturer | **{dotted-circle}** | string | Manufacturers of operating system | -| os_name | **{dotted-circle}** | string | Name of operating system | -| os_timezone | **{dotted-circle}** | string | Client operating system timezone | -| page_referrer | **{dotted-circle}** | string | Referrer URL | -| page_title | **{dotted-circle}** | string | Page title | -| page_url | **{dotted-circle}** | string | Page URL | -| page_urlfragment | **{dotted-circle}** | string | Fragment aka anchor | -| page_urlhost | **{dotted-circle}** | string | Host aka domain | -| page_urlpath | **{dotted-circle}** | string | Path to page | -| page_urlport | **{dotted-circle}** | integer | Port if specified, 80 if not | -| page_urlquery | **{dotted-circle}** | string | Query string | -| page_urlscheme | **{dotted-circle}** | string | Scheme (protocol name) | -| platform | **{dotted-circle}** | string | The platform the app runs on | -| pp_xoffset_max | **{dotted-circle}** | integer | Maximum page x offset seen in the last ping period | -| pp_xoffset_min | **{dotted-circle}** | integer | Minimum page x offset seen in the last ping period | -| pp_yoffset_max | **{dotted-circle}** | integer | Maximum page y offset seen in the last ping period | -| pp_yoffset_min | **{dotted-circle}** | integer | Minimum page y offset seen in the last ping period | -| refr_domain_userid | **{dotted-circle}** | string | The Snowplow domain_userid of the referring website | -| refr_dvce_tstamp | **{dotted-circle}** | timestamp | The time of attaching the domain_userid to the inbound link | -| refr_medium | **{dotted-circle}** | string | Type of referer | -| refr_source | **{dotted-circle}** | string | Name of referer if recognised | -| refr_term | **{dotted-circle}** | string | Keywords if source is a search engine | -| refr_urlfragment | **{dotted-circle}** | string | Referer URL fragment | -| refr_urlhost | **{dotted-circle}** | string | Referer host | -| refr_urlpath | **{dotted-circle}** | string | Referer page path | -| refr_urlport | **{dotted-circle}** | integer | Referer port | -| refr_urlquery | **{dotted-circle}** | string | Referer URL querystring | -| refr_urlscheme | **{dotted-circle}** | string | Referer scheme | -| se_action | **{dotted-circle}** | string | The action / event itself | -| se_category | **{dotted-circle}** | string | The category of event | -| se_label | **{dotted-circle}** | string | A label often used to refer to the ‘object’ the action is performed on | -| se_property | **{dotted-circle}** | string | A property associated with either the action or the object | -| se_value | **{dotted-circle}** | decimal | A value associated with the user action | -| ti_category | **{dotted-circle}** | string | Item category | -| ti_currency | **{dotted-circle}** | string | Currency | -| ti_name | **{dotted-circle}** | string | Item name | -| ti_orderid | **{dotted-circle}** | string | Order ID | -| ti_price | **{dotted-circle}** | decimal | Item price | -| ti_price_base | **{dotted-circle}** | decimal | Item price in base currency | -| ti_quantity | **{dotted-circle}** | integer | Item quantity | -| ti_sku | **{dotted-circle}** | string | Item SKU | -| tr_affiliation | **{dotted-circle}** | string | Transaction affiliation (such as channel) | -| tr_city | **{dotted-circle}** | string | Delivery address: city | -| tr_country | **{dotted-circle}** | string | Delivery address: country | -| tr_currency | **{dotted-circle}** | string | Transaction Currency | -| tr_orderid | **{dotted-circle}** | string | Order ID | -| tr_shipping | **{dotted-circle}** | decimal | Delivery cost charged | -| tr_shipping_base | **{dotted-circle}** | decimal | Shipping cost in base currency | -| tr_state | **{dotted-circle}** | string | Delivery address: state | -| tr_tax | **{dotted-circle}** | decimal | Transaction tax value (such as amount of VAT included) | -| tr_tax_base | **{dotted-circle}** | decimal | Tax applied in base currency | -| tr_total | **{dotted-circle}** | decimal | Transaction total value | -| tr_total_base | **{dotted-circle}** | decimal | Total amount of transaction in base currency | -| true_tstamp | **{dotted-circle}** | timestamp | User-set exact timestamp | -| txn_id | **{dotted-circle}** | string | Transaction ID | -| unstruct_event | **{dotted-circle}** | JSON | The properties of the event | -| uploaded_at | **{dotted-circle}** | | | -| user_fingerprint | **{dotted-circle}** | integer | User identifier based on (hopefully unique) browser features | -| user_id | **{dotted-circle}** | string | Unique identifier for user, set by the business using setUserId | -| user_ipaddress | **{dotted-circle}** | string | IP address | -| useragent | **{dotted-circle}** | string | User agent (expressed as a browser string) | -| v_collector | **{dotted-circle}** | string | Collector version | -| v_etl | **{dotted-circle}** | string | ETL version | -| v_tracker | **{dotted-circle}** | string | Identifier for Snowplow tracker | +<!-- This redirect file can be deleted after February 1, 2021. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/product_analytics/usage_ping.md b/doc/development/product_analytics/usage_ping.md index 37363bbabbc..5fbdb508bb1 100644 --- a/doc/development/product_analytics/usage_ping.md +++ b/doc/development/product_analytics/usage_ping.md @@ -1,1059 +1,8 @@ --- -stage: Growth -group: Product Analytics -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +redirect_to: '../usage_ping.md' --- -# Usage Ping Guide +This document was moved to [another location](../usage_ping.md). -> - Introduced in GitLab Enterprise Edition 8.10. -> - More statistics were added in GitLab Enterprise Edition 8.12. -> - Moved to GitLab Core in 9.1. -> - More statistics were added in GitLab Ultimate 11.2. - -This guide describes Usage Ping's purpose and how it's implemented. - -For more information about Product Analytics, see: - -- [Product Analytics Guide](https://about.gitlab.com/handbook/product/product-analytics-guide/) -- [Snowplow Guide](snowplow.md) - -More useful links: - -- [Product Analytics Direction](https://about.gitlab.com/direction/product-analytics/) -- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/) -- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/) -- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) - -## What is Usage Ping? - -- GitLab sends a weekly payload containing usage data to GitLab Inc. Usage Ping provides high-level data to help our product, support, and sales teams. It does not send any project names, usernames, or any other specific data. The information from the usage ping is not anonymous, it is linked to the hostname of the instance. Sending usage ping is optional, and any instance can disable analytics. -- The usage data is primarily composed of row counts for different tables in the instance’s database. By comparing these counts month over month (or week over week), we can get a rough sense for how an instance is using the different features within the product. In addition to counts, other facts - that help us classify and understand GitLab installations are collected. -- Usage ping is important to GitLab as we use it to calculate our Stage Monthly Active Users (SMAU) which helps us measure the success of our stages and features. -- While usage ping is enabled, GitLab gathers data from the other instances and can show usage statistics of your instance to your users. - -### Why should we enable Usage Ping? - -- The main purpose of Usage Ping is to build a better GitLab. Data about how GitLab is used is collected to better understand feature/stage adoption and usage, which helps us understand how GitLab is adding value and helps our team better understand the reasons why people use GitLab and with this knowledge we're able to make better product decisions. -- As a benefit of having the usage ping active, GitLab lets you analyze the users’ activities over time of your GitLab installation. -- As a benefit of having the usage ping active, GitLab provides you with The DevOps Report,which gives you an overview of your entire instance’s adoption of Concurrent DevOps from planning to monitoring. -- You get better, more proactive support. (assuming that our TAMs and support organization used the data to deliver more value) -- You get insight and advice into how to get the most value out of your investment in GitLab. Wouldn't you want to know that a number of features or values are not being adopted in your organization? -- You get a report that illustrates how you compare against other similar organizations (anonymized), with specific advice and recommendations on how to improve your DevOps processes. -- Usage Ping is enabled by default. To disable it, see [Disable Usage Ping](#disable-usage-ping). - -### Limitations - -- Usage Ping does not track frontend events things like page views, link clicks, or user sessions, and only focuses on aggregated backend events. -- Because of these limitations we recommend instrumenting your products with Snowplow for more detailed analytics on GitLab.com and use Usage Ping to track aggregated backend events on self-managed. - -## Usage Ping payload - -You can view the exact JSON payload sent to GitLab Inc. in the administration panel. To view the payload: - -1. Navigate to **Admin Area > Settings > Metrics and profiling**. -1. Expand the **Usage statistics** section. -1. Click the **Preview payload** button. - -For an example payload, see [Example Usage Ping payload](#example-usage-ping-payload). - -## Disable Usage Ping - -To disable Usage Ping in the GitLab UI, go to the **Settings** page of your administration panel and uncheck the **Usage Ping** checkbox. - -To disable Usage Ping and prevent it from being configured in the future through the administration panel, Omnibus installs can set the following in [`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html#configuration-options): - -```ruby -gitlab_rails['usage_ping_enabled'] = false -``` - -Source installations can set the following in `gitlab.yml`: - -```yaml -production: &base - # ... - gitlab: - # ... - usage_ping_enabled: false -``` - -## Usage Ping request flow - -The following example shows a basic request/response flow between a GitLab instance, the Versions Application, the License Application, Salesforce, the GitLab S3 Bucket, the GitLab Snowflake Data Warehouse, and Sisense: - -```mermaid -sequenceDiagram - participant GitLab Instance - participant Versions Application - participant Licenses Application - participant Salesforce - participant S3 Bucket - participant Snowflake DW - participant Sisense Dashboards - GitLab Instance->>Versions Application: Send Usage Ping - loop Process usage data - Versions Application->>Versions Application: Parse usage data - Versions Application->>Versions Application: Write to database - Versions Application->>Versions Application: Update license ping time - end - loop Process data for Salesforce - Versions Application-xLicenses Application: Request Zuora subscription id - Licenses Application-xVersions Application: Zuora subscription id - Versions Application-xSalesforce: Request Zuora account id by Zuora subscription id - Salesforce-xVersions Application: Zuora account id - Versions Application-xSalesforce: Usage data for the Zuora account - end - Versions Application->>S3 Bucket: Export Versions database - S3 Bucket->>Snowflake DW: Import data - Snowflake DW->>Snowflake DW: Transform data using dbt - Snowflake DW->>Sisense Dashboards: Data available for querying - Versions Application->>GitLab Instance: DevOps Report (Conversational Development Index) -``` - -## How Usage Ping works - -1. The Usage Ping [cron job](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/gitlab_usage_ping_worker.rb#L30) is set in Sidekiq to run weekly. -1. When the cron job runs, it calls [`GitLab::UsageData.to_json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L22). -1. `GitLab::UsageData.to_json` [cascades down](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L22) to ~400+ other counter method calls. -1. The response of all methods calls are [merged together](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L14) into a single JSON payload in `GitLab::UsageData.to_json`. -1. The JSON payload is then [posted to the Versions application]( https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L20) - If a firewall exception is needed, the required URL depends on several things. If - the hostname is `version.gitlab.com`, the protocol is `TCP`, and the port number is `443`, - the required URL is <https://version.gitlab.com/>. - -## Implementing Usage Ping - -Usage Ping consists of two kinds of data, counters and observations. Counters track how often a certain event -happened over time, such as how many CI pipelines have run. They are monotonic and always trend up. -Observations are facts collected from one or more GitLab instances and can carry arbitrary data. There are no -general guidelines around how to collect those, due to the individual nature of that data. - -There are several types of counters which are all found in `usage_data.rb`: - -- **Ordinary Batch Counters:** Simple count of a given ActiveRecord_Relation -- **Distinct Batch Counters:** Distinct count of a given ActiveRecord_Relation on given column -- **Sum Batch Counters:** Sum the values of a given ActiveRecord_Relation on given column -- **Alternative Counters:** Used for settings and configurations -- **Redis Counters:** Used for in-memory counts. - -NOTE: -Only use the provided counter methods. Each counter method contains a built in fail safe to isolate each counter to avoid breaking the entire Usage Ping. - -### Why batch counting - -For large tables, PostgreSQL can take a long time to count rows due to MVCC [(Multi-version Concurrency Control)](https://en.wikipedia.org/wiki/Multiversion_concurrency_control). Batch counting is a counting method where a single large query is broken into multiple smaller queries. For example, instead of a single query querying 1,000,000 records, with batch counting, you can execute 100 queries of 10,000 records each. Batch counting is useful for avoiding database timeouts as each batch query is significantly shorter than one single long running query. - -For GitLab.com, there are extremely large tables with 15 second query timeouts, so we use batch counting to avoid encountering timeouts. Here are the sizes of some GitLab.com tables: - -| Table | Row counts in millions | -|------------------------------|------------------------| -| `merge_request_diff_commits` | 2280 | -| `ci_build_trace_sections` | 1764 | -| `merge_request_diff_files` | 1082 | -| `events` | 514 | - -There are two batch counting methods provided, `Ordinary Batch Counters` and `Distinct Batch Counters`. Batch counting requires indexes on columns to calculate max, min, and range queries. In some cases, a specialized index may need to be added on the columns involved in a counter. - -### Ordinary Batch Counters - -Handles `ActiveRecord::StatementInvalid` error - -Simple count of a given ActiveRecord_Relation, does a non-distinct batch count, smartly reduces batch_size and handles errors. - -Method: `count(relation, column = nil, batch: true, start: nil, finish: nil)` - -Arguments: - -- `relation` the ActiveRecord_Relation to perform the count -- `column` the column to perform the count on, by default is the primary key -- `batch`: default `true` in order to use batch counting -- `start`: custom start of the batch counting in order to avoid complex min calculations -- `end`: custom end of the batch counting in order to avoid complex min calculations - -Examples: - -```ruby -count(User.active) -count(::Clusters::Cluster.aws_installed.enabled, :cluster_id) -count(::Clusters::Cluster.aws_installed.enabled, :cluster_id, start: ::Clusters::Cluster.minimum(:id), finish: ::Clusters::Cluster.maximum(:id)) -``` - -### Distinct Batch Counters - -Handles `ActiveRecord::StatementInvalid` error - -Distinct count of a given ActiveRecord_Relation on given column, a distinct batch count, smartly reduces batch_size and handles errors. - -Method: `distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)` - -Arguments: - -- `relation` the ActiveRecord_Relation to perform the count -- `column` the column to perform the distinct count, by default is the primary key -- `batch`: default `true` in order to use batch counting -- `batch_size`: if none set it uses default value 10000 from `Gitlab::Database::BatchCounter` -- `start`: custom start of the batch counting in order to avoid complex min calculations -- `end`: custom end of the batch counting in order to avoid complex min calculations - -Examples: - -```ruby -distinct_count(::Project, :creator_id) -distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id)) -distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id') -``` - -### Sum Batch Counters - -Handles `ActiveRecord::StatementInvalid` error - -Sum the values of a given ActiveRecord_Relation on given column and handles errors. - -Method: `sum(relation, column, batch_size: nil, start: nil, finish: nil)` - -Arguments: - -- `relation` the ActiveRecord_Relation to perform the operation -- `column` the column to sum on -- `batch_size`: if none set it uses default value 1000 from `Gitlab::Database::BatchCounter` -- `start`: custom start of the batch counting in order to avoid complex min calculations -- `end`: custom end of the batch counting in order to avoid complex min calculations - -Examples: - -```ruby -sum(JiraImportState.finished, :imported_issues_count) -``` - -### Grouping & Batch Operations - -The `count`, `distinct_count`, and `sum` batch counters can accept an `ActiveRecord::Relation` -object, which groups by a specified column. With a grouped relation, the methods do batch counting, -handle errors, and returns a hash table of key-value pairs. - -Examples: - -```ruby -count(Namespace.group(:type)) -# returns => {nil=>179, "Group"=>54} - -distinct_count(Project.group(:visibility_level), :creator_id) -# returns => {0=>1, 10=>1, 20=>11} - -sum(Issue.group(:state_id), :weight)) -# returns => {1=>3542, 2=>6820} -``` - -### Redis Counters - -Handles `::Redis::CommandError` and `Gitlab::UsageDataCounters::BaseCounter::UnknownEvent` -returns -1 when a block is sent or hash with all values -1 when a `counter(Gitlab::UsageDataCounters)` is sent -different behavior due to 2 different implementations of Redis counter - -Method: `redis_usage_data(counter, &block)` - -Arguments: - -- `counter`: a counter from `Gitlab::UsageDataCounters`, that has `fallback_totals` method implemented -- or a `block`: which is evaluated - -#### Ordinary Redis Counters - -Examples of implementation: - -- Using Redis methods [`INCR`](https://redis.io/commands/incr), [`GET`](https://redis.io/commands/get), and [`Gitlab::UsageDataCounters::WikiPageCounter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/wiki_page_counter.rb) -- Using Redis methods [`HINCRBY`](https://redis.io/commands/hincrby), [`HGETALL`](https://redis.io/commands/hgetall), and [`Gitlab::UsageCounters::PodLogs`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_counters/pod_logs.rb) - -##### UsageData API Tracking - -<!-- There's nearly identical content in `##### Adding new events`. If you fix errors here, you may need to fix the same errors in the other location. --> - -1. Track event using `UsageData` API - - Increment event count using ordinary Redis counter, for given event name. - - Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default. - - API requests are protected by checking for a valid CSRF token. - - In order to be able to increment the values the related feature `usage_data_<event_name>` should be enabled. - - ```plaintext - POST /usage_data/increment_counter - ``` - - | Attribute | Type | Required | Description | - | :-------- | :--- | :------- | :---------- | - | `event` | string | yes | The event name it should be tracked | - - Response - - - `200` if event was tracked - - `400 Bad request` if event parameter is missing - - `401 Unauthorized` if user is not authenticated - - `403 Forbidden` for invalid CSRF token provided - -1. Track events using JavaScript/Vue API helper which calls the API above - - Note that `usage_data_api` and `usage_data_#{event_name}` should be enabled in order to be able to track events - - ```javascript - import api from '~/api'; - - api.trackRedisCounterEvent('my_already_defined_event_name'), - ``` - -#### Redis HLL Counters - -With `Gitlab::UsageDataCounters::HLLRedisCounter` we have available data structures used to count unique values. - -Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PFCOUNT](https://redis.io/commands/pfcount). - -##### Adding new events - -1. Define events in [`known_events`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/). - - Example event: - - ```yaml - - name: i_compliance_credential_inventory - category: compliance - redis_slot: compliance - expiry: 42 # 6 weeks - aggregation: weekly - ``` - - Keys: - - - `name`: unique event name. - - Name format `<prefix>_<redis_slot>_name`. - - Use one of the following prefixes for the event's name: - - - `g_` for group, as an event which is tracked for group. - - `p_` for project, as an event which is tracked for project. - - `i_` for instance, as an event which is tracked for instance. - - `a_` for events encompassing all `g_`, `p_`, `i_`. - - `o_` for other. - - Consider including in the event's name the Redis slot in order to be able to count totals for a specific category. - - Example names: `i_compliance_credential_inventory`, `g_analytics_contribution`. - - - `category`: event category. Used for getting total counts for events in a category, for easier - access to a group of events. - - `redis_slot`: optional Redis slot; default value: event name. Used if needed to calculate totals - for a group of metrics. Ensure keys are in the same slot. For example: - `i_compliance_credential_inventory` with `redis_slot: 'compliance'` builds Redis key - `i_{compliance}_credential_inventory-2020-34`. If `redis_slot` is not defined the Redis key will - be `{i_compliance_credential_inventory}-2020-34`. - - `expiry`: expiry time in days. Default: 29 days for daily aggregation and 6 weeks for weekly - aggregation. - - `aggregation`: may be set to a `:daily` or `:weekly` key. Defines how counting data is stored in Redis. - Aggregation on a `daily` basis does not pull more fine grained data. - - `feature_flag`: optional. For details, see our [GitLab internal Feature flags](../feature_flags/) documentation. - -1. Track event in controller using `RedisTracking` module with `track_redis_hll_event(*controller_actions, name:, feature:, feature_default_enabled: false)`. - - Arguments: - - - `controller_actions`: controller actions we want to track. - - `name`: event name. - - `feature`: feature name, all metrics we track should be under feature flag. - - `feature_default_enabled`: feature flag is disabled by default, set to `true` for it to be enabled by default. - - Example usage: - - ```ruby - # controller - class ProjectsController < Projects::ApplicationController - include RedisTracking - - skip_before_action :authenticate_user!, only: :show - track_redis_hll_event :index, :show, name: 'g_compliance_example_feature_visitors', feature: :compliance_example_feature, feature_default_enabled: true - - def index - render html: 'index' - end - - def new - render html: 'new' - end - - def show - render html: 'show' - end - end - ``` - -1. Track event in API using `increment_unique_values(event_name, values)` helper method. - - In order to be able to track the event, Usage Ping must be enabled and the event feature `usage_data_<event_name>` must be enabled. - - Arguments: - - - `event_name`: event name. - - `values`: values counted, one value or array of values. - - Example usage: - - ```ruby - get ':id/registry/repositories' do - repositories = ContainerRepositoriesFinder.new( - user: current_user, subject: user_group - ).execute - - increment_unique_values('i_list_repositories', current_user.id) - - present paginate(repositories), with: Entities::ContainerRegistry::Repository, tags: params[:tags], tags_count: params[:tags_count] - end - ``` - -1. Track event using `track_usage_event(event_name, values) in services and graphql - - Increment unique values count using Redis HLL, for given event name. - - Example: - - [Track usage event for incident created in service](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/issues/update_service.rb) - - [Track usage event for incident created in graphql](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/mutations/alert_management/update_alert_status.rb) - - ```ruby - track_usage_event(:incident_management_incident_created, current_user.id) - ``` - -<!-- There's nearly identical content in `##### UsageData API Tracking`. If you find / fix errors here, you may need to fix errors in that section too. --> - -1. Track event using `UsageData` API - - Increment unique users count using Redis HLL, for given event name. - - Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default. - - API requests are protected by checking for a valid CSRF token. - - In order to increment the values, the related feature `usage_data_<event_name>` should be - set to `default_enabled: true`. For more information, see - [Feature flags in development of GitLab](../feature_flags/index.md). - - ```plaintext - POST /usage_data/increment_unique_users - ``` - - | Attribute | Type | Required | Description | - | :-------- | :--- | :------- | :---------- | - | `event` | string | yes | The event name it should be tracked | - - Response - - Return 200 if tracking failed for any reason. - - - `200` if event was tracked or any errors - - `400 Bad request` if event parameter is missing - - `401 Unauthorized` if user is not authenticated - - `403 Forbidden` for invalid CSRF token provided - -1. Track events using JavaScript/Vue API helper which calls the API above - - Example usage for an existing event already defined in [known events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/): - - Usage Data API is behind `usage_data_api` feature flag which, as of GitLab 13.7, is - now set to `default_enabled: true`. - - Each event tracked using Usage Data API is behind a feature flag `usage_data_#{event_name}` which should be `default_enabled: true` - - ```javascript - import api from '~/api'; - - api.trackRedisHllUserEvent('my_already_defined_event_name'), - ``` - -1. Track event using base module `Gitlab::UsageDataCounters::HLLRedisCounter.track_event(values, event_name)`. - - Arguments: - - - `values`: One value or array of values we count. For example: user_id, visitor_id, user_ids. - - `event_name`: event name. - -1. Track event on context level using base module `Gitlab::UsageDataCounters::HLLRedisCounter.track_event_in_context(entity_id, event_name, context)`. - - Arguments: - - - `entity_id`: value we count. For example: user_id, visitor_id. - - `event_name`: event name. - - `context`: context value. Allowed values are `default`, `free`, `bronze`, `silver`, `gold`, `starter`, `premium`, `ultimate` - -1. Get event data using `Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names:, start_date:, end_date:, context: '')`. - - Arguments: - - - `event_names`: the list of event names. - - `start_date`: start date of the period for which we want to get event data. - - `end_date`: end date of the period for which we want to get event data. - - `context`: context of the event. Allowed values are `default`, `free`, `bronze`, `silver`, `gold`, `starter`, `premium`, `ultimate`. - -1. Testing tracking and getting unique events - -Trigger events in rails console by using `track_event` method - - ```ruby - Gitlab::UsageDataCounters::HLLRedisCounter.track_event(1, 'g_compliance_audit_events') - Gitlab::UsageDataCounters::HLLRedisCounter.track_event(2, 'g_compliance_audit_events') - ``` - -Next, get the unique events for the current week. - - ```ruby - # Get unique events for metric for current_week - Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'g_compliance_audit_events', - start_date: Date.current.beginning_of_week, end_date: Date.current.end_of_week) - ``` - -##### Recommendations - -We have the following recommendations for [Adding new events](#adding-new-events): - -- Event aggregation: weekly. -- Key expiry time: - - Daily: 29 days. - - Weekly: 42 days. -- When adding new metrics, use a [feature flag](../../operations/feature_flags.md) to control the impact. -- For feature flags triggered by another service, set `default_enabled: false`, - - Events can be triggered using the `UsageData` API, which helps when there are > 10 events per change - -##### Enable/Disable Redis HLL tracking - -Events are tracked behind [feature flags](../feature_flags/index.md) due to concerns for Redis performance and scalability. - -For a full list of events and corresponding feature flags see, [known_events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/) files. - -To enable or disable tracking for specific event within <https://gitlab.com> or <https://about.staging.gitlab.com>, run commands such as the following to -[enable or disable the corresponding feature](../feature_flags/index.md). - -```shell -/chatops run feature set <feature_name> true -/chatops run feature set <feature_name> false -``` - -##### Known events in usage data payload - -All events added in [`known_events/common.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml) are automatically added to usage data generation under the `redis_hll_counters` key. This column is stored in [version-app as a JSON](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L209). -For each event we add metrics for the weekly and monthly time frames, and totals for each where applicable: - -- `#{event_name}_weekly`: Data for 7 days for daily [aggregation](#adding-new-events) events and data for the last complete week for weekly [aggregation](#adding-new-events) events. -- `#{event_name}_monthly`: Data for 28 days for daily [aggregation](#adding-new-events) events and data for the last 4 complete weeks for weekly [aggregation](#adding-new-events) events. -- `#{category}_total_unique_counts_weekly`: Total unique counts for events in the same category for the last 7 days or the last complete week, if events are in the same Redis slot and we have more than one metric. -- `#{category}_total_unique_counts_monthly`: Total unique counts for events in same category for the last 28 days or the last 4 complete weeks, if events are in the same Redis slot and we have more than one metric. - -Example of `redis_hll_counters` data: - -```ruby -{:redis_hll_counters=> - {"compliance"=> - {"g_compliance_dashboard_weekly"=>0, - "g_compliance_dashboard_monthly"=>0, - "g_compliance_audit_events_weekly"=>0, - "g_compliance_audit_events_monthly"=>0, - "compliance_total_unique_counts_weekly"=>0, - "compliance_total_unique_counts_monthly"=>0}, - "analytics"=> - {"g_analytics_contribution_weekly"=>0, - "g_analytics_contribution_monthly"=>0, - "g_analytics_insights_weekly"=>0, - "g_analytics_insights_monthly"=>0, - "analytics_total_unique_counts_weekly"=>0, - "analytics_total_unique_counts_monthly"=>0}, - "ide_edit"=> - {"g_edit_by_web_ide_weekly"=>0, - "g_edit_by_web_ide_monthly"=>0, - "g_edit_by_sfe_weekly"=>0, - "g_edit_by_sfe_monthly"=>0, - "ide_edit_total_unique_counts_weekly"=>0, - "ide_edit_total_unique_counts_monthly"=>0}, - "search"=> - {"i_search_total_weekly"=>0, "i_search_total_monthly"=>0, "i_search_advanced_weekly"=>0, "i_search_advanced_monthly"=>0, "i_search_paid_weekly"=>0, "i_search_paid_monthly"=>0, "search_total_unique_counts_weekly"=>0, "search_total_unique_counts_monthly"=>0}, - "source_code"=>{"wiki_action_weekly"=>0, "wiki_action_monthly"=>0} - } -``` - -Example usage: - -```ruby -# Redis Counters -redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter) -redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] } - -# Define events in common.yml https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml - -# Tracking events -Gitlab::UsageDataCounters::HLLRedisCounter.track_event(visitor_id, 'expand_vulnerabilities') - -# Get unique events for metric -redis_usage_data { Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'expand_vulnerabilities', start_date: 28.days.ago, end_date: Date.current) } -``` - -### Alternative Counters - -Handles `StandardError` and fallbacks into -1 this way not all measures fail if we encounter one exception. -Mainly used for settings and configurations. - -Method: `alt_usage_data(value = nil, fallback: -1, &block)` - -Arguments: - -- `value`: a simple static value in which case the value is simply returned. -- or a `block`: which is evaluated -- `fallback: -1`: the common value used for any metrics that are failing. - -Example of usage: - -```ruby -alt_usage_data { Gitlab::VERSION } -alt_usage_data { Gitlab::CurrentSettings.uuid } -alt_usage_data(999) -``` - -### Prometheus Queries - -In those cases where operational metrics should be part of Usage Ping, a database or Redis query is unlikely -to provide useful data. Instead, Prometheus might be more appropriate, since most GitLab architectural -components publish metrics to it that can be queried back, aggregated, and included as usage data. - -NOTE: -Prometheus as a data source for Usage Ping is currently only available for single-node Omnibus installations -that are running the [bundled Prometheus](../../administration/monitoring/prometheus/index.md) instance. - -To query Prometheus for metrics, a helper method is available to `yield` a fully configured -`PrometheusClient`, given it is available as per the note above: - -```ruby -with_prometheus_client do |client| - response = client.query('<your query>') - ... -end -``` - -Please refer to [the `PrometheusClient` definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/prometheus_client.rb) -for how to use its API to query for data. - -## Developing and testing Usage Ping - -### 1. Naming and placing the metrics - -Add the metric in one of the top level keys - -- `license`: for license related metrics. -- `settings`: for settings related metrics. -- `counts_weekly`: for counters that have data for the most recent 7 days. -- `counts_monthly`: for counters that have data for the most recent 28 days. -- `counts`: for counters that have data for all time. - -### 2. Use your Rails console to manually test counters - -```ruby -# count -Gitlab::UsageData.count(User.active) -Gitlab::UsageData.count(::Clusters::Cluster.aws_installed.enabled, :cluster_id) - -# count distinct -Gitlab::UsageData.distinct_count(::Project, :creator_id) -Gitlab::UsageData.distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id)) -``` - -### 3. Generate the SQL query - -Your Rails console returns the generated SQL queries. - -Example: - -```ruby -pry(main)> Gitlab::UsageData.count(User.active) - (2.6ms) SELECT "features"."key" FROM "features" - (15.3ms) SELECT MIN("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) - (2.4ms) SELECT MAX("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) - (1.9ms) SELECT COUNT("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) AND "users"."id" BETWEEN 1 AND 100000 -``` - -### 4. Optimize queries with #database-lab - -Paste the SQL query into `#database-lab` to see how the query performs at scale. - -- `#database-lab` is a Slack channel which uses a production-sized environment to test your queries. -- GitLab.com’s production database has a 15 second timeout. -- Any single query must stay below [1 second execution time](../query_performance.md#timing-guidelines-for-queries) with cold caches. -- Add a specialized index on columns involved to reduce the execution time. - -In order to have an understanding of the query's execution we add in the MR description the following information: - -- For counters that have a `time_period` test we add information for both cases: - - `time_period = {}` for all time periods - - `time_period = { created_at: 28.days.ago..Time.current }` for last 28 days period -- Execution plan and query time before and after optimization -- Query generated for the index and time -- Migration output for up and down execution - -We also use `#database-lab` and [explain.depesz.com](https://explain.depesz.com/). For more details, see the [database review guide](../database_review.md#preparation-when-adding-or-modifying-queries). - -#### Optimization recommendations and examples - -- Use specialized indexes [example 1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26871), [example 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26445). -- Use defined `start` and `finish`, and simple queries, because these values can be memoized and reused, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37155). -- Avoid joins and write the queries as simply as possible, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36316). -- Set a custom `batch_size` for `distinct_count`, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38000). - -### 5. Add the metric definition - -When adding, changing, or updating metrics, please update the [Event Dictionary's **Usage Ping** table](https://about.gitlab.com/handbook/product/product-analytics-guide/#event-dictionary). - -### 6. Add new metric to Versions Application - -Check if new metrics need to be added to the Versions Application. See `usage_data` [schema](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L147) and usage data [parameters accepted](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/app/services/usage_ping.rb). Any metrics added under the `counts` key are saved in the `stats` column. - -### 7. Add the feature label - -Add the `feature` label to the Merge Request for new Usage Ping metrics. These are user-facing changes and are part of expanding the Usage Ping feature. - -### 8. Add a changelog file - -Ensure you comply with the [Changelog entries guide](../changelog.md). - -### 9. Ask for a Product Analytics Review - -On GitLab.com, we have DangerBot setup to monitor Product Analytics related files and DangerBot recommends a Product Analytics review. Mention `@gitlab-org/growth/product_analytics/engineers` in your MR for a review. - -### 10. Verify your metric - -On GitLab.com, the Product Analytics team regularly monitors Usage Ping. They may alert you that your metrics need further optimization to run quicker and with greater success. You may also use the [Usage Ping QA dashboard](https://app.periscopedata.com/app/gitlab/632033/Usage-Ping-QA) to check how well your metric performs. The dashboard allows filtering by GitLab version, by "Self-managed" & "Saas" and shows you how many failures have occurred for each metric. Whenever you notice a high failure rate, you may re-optimize your metric. - -### Optional: Test Prometheus based Usage Ping - -If the data submitted includes metrics [queried from Prometheus](#prometheus-queries) that you would like to inspect and verify, -then you need to ensure that a Prometheus server is running locally, and that furthermore the respective GitLab components -are exporting metrics to it. If you do not need to test data coming from Prometheus, no further action -is necessary, since Usage Ping should degrade gracefully in the absence of a running Prometheus server. - -There are currently three kinds of components that may export data to Prometheus, and which are included in Usage Ping: - -- [`node_exporter`](https://github.com/prometheus/node_exporter) - Exports node metrics from the host machine -- [`gitlab-exporter`](https://gitlab.com/gitlab-org/gitlab-exporter) - Exports process metrics from various GitLab components -- various GitLab services such as Sidekiq and the Rails server that export their own metrics - -#### Test with an Omnibus container - -This is the recommended approach to test Prometheus based Usage Ping. - -The easiest way to verify your changes is to build a new Omnibus image from your code branch via CI, then download the image -and run a local container instance: - -1. From your merge request, click on the `qa` stage, then trigger the `package-and-qa` job. This job triggers an Omnibus -build in a [downstream pipeline of the `omnibus-gitlab-mirror` project](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/-/pipelines). -1. In the downstream pipeline, wait for the `gitlab-docker` job to finish. -1. Open the job logs and locate the full container name including the version. It takes the following form: `registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>`. -1. On your local machine, make sure you are logged in to the GitLab Docker registry. You can find the instructions for this in -[Authenticate to the GitLab Container Registry](../../user/packages/container_registry/index.md#authenticate-with-the-container-registry). -1. Once logged in, download the new image via `docker pull registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>` -1. For more information about working with and running Omnibus GitLab containers in Docker, please refer to [GitLab Docker images](https://docs.gitlab.com/omnibus/docker/README.html) in the Omnibus documentation. - -#### Test with GitLab development toolkits - -This is the less recommended approach, since it comes with a number of difficulties when emulating a real GitLab deployment. - -The [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) is not currently set up to run a Prometheus server or `node_exporter` alongside other GitLab components. If you would -like to do so, [Monitoring the GDK with Prometheus](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/prometheus/index.md#monitoring-the-gdk-with-prometheus) is a good start. - -The [GCK](https://gitlab.com/gitlab-org/gitlab-compose-kit) has limited support for testing Prometheus based Usage Ping. -By default, it already comes with a fully configured Prometheus service that is set up to scrape a number of components, -but with the following limitations: - -- It does not currently run a `gitlab-exporter` instance, so several `process_*` metrics from services such as Gitaly may be missing. -- While it runs a `node_exporter`, `docker-compose` services emulate hosts, meaning that it would normally report itself to not be associated -with any of the other services that are running. That is not how node metrics are reported in a production setup, where `node_exporter` -always runs as a process alongside other GitLab components on any given node. From Usage Ping's perspective none of the node data would therefore -appear to be associated to any of the services running, since they all appear to be running on different hosts. To alleviate this problem, the `node_exporter` in GCK was arbitrarily "assigned" to the `web` service, meaning only for this service `node_*` metrics appears in Usage Ping. - -## Aggregated metrics - -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45979) in GitLab 13.6. -> - It's [deployed behind a feature flag](../../user/feature_flags.md), disabled by default. -> - It's enabled on GitLab.com. - -WARNING: -This feature is intended solely for internal GitLab use. - -In order to add data for aggregated metrics into Usage Ping payload you should add corresponding definition into [`aggregated_metrics.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics.yml) file. Each aggregate definition includes following parts: - -- name: unique name under which aggregate metric is added to Usage Ping payload -- operator: operator that defines how aggregated metric data is counted. Available operators are: - - `OR`: removes duplicates and counts all entries that triggered any of listed events - - `AND`: removes duplicates and counts all elements that were observed triggering all of following events -- events: list of events names (from [`known_events.yml`](#known-events-in-usage-data-payload)) to aggregate into metric. All events in this list must have the same `redis_slot` and `aggregation` attributes. -- feature_flag: name of [development feature flag](../feature_flags/development.md#development-type) that is checked before -metrics aggregation is performed. Corresponding feature flag should have `default_enabled` attribute set to `false`. -`feature_flag` attribute is **OPTIONAL** and can be omitted, when `feature_flag` is missing no feature flag is checked. - -Example aggregated metric entries: - -```yaml -- name: product_analytics_test_metrics_union - operator: OR - events: ['i_search_total', 'i_search_advanced', 'i_search_paid'] -- name: product_analytics_test_metrics_intersection_with_feautre_flag - operator: AND - events: ['i_search_total', 'i_search_advanced', 'i_search_paid'] - feature_flag: example_aggregated_metric -``` - -Aggregated metrics are added under `aggregated_metrics` key in both `counts_weekly` and `counts_monthly` top level keys in Usage Ping payload. - -```ruby -{ - :counts_monthly => { - :deployments => 1003, - :successful_deployments => 78, - :failed_deployments => 275, - :packages => 155, - :personal_snippets => 2106, - :project_snippets => 407, - :promoted_issues => 719, - :aggregated_metrics => { - :product_analytics_test_metrics_union => 7, - :product_analytics_test_metrics_intersection_with_feautre_flag => 2 - }, - :snippets => 2513 - } -} -``` - -## Example Usage Ping payload - -The following is example content of the Usage Ping payload. - -```json -{ - "uuid": "0000000-0000-0000-0000-000000000000", - "hostname": "example.com", - "version": "12.10.0-pre", - "installation_type": "omnibus-gitlab", - "active_user_count": 999, - "recorded_at": "2020-04-17T07:43:54.162+00:00", - "edition": "EEU", - "license_md5": "00000000000000000000000000000000", - "license_id": null, - "historical_max_users": 999, - "licensee": { - "Name": "ABC, Inc.", - "Email": "email@example.com", - "Company": "ABC, Inc." - }, - "license_user_count": 999, - "license_starts_at": "2020-01-01", - "license_expires_at": "2021-01-01", - "license_plan": "ultimate", - "license_add_ons": { - }, - "license_trial": false, - "counts": { - "assignee_lists": 999, - "boards": 999, - "ci_builds": 999, - ... - }, - "container_registry_enabled": true, - "dependency_proxy_enabled": false, - "gitlab_shared_runners_enabled": true, - "gravatar_enabled": true, - "influxdb_metrics_enabled": true, - "ldap_enabled": false, - "mattermost_enabled": false, - "omniauth_enabled": true, - "prometheus_enabled": false, - "prometheus_metrics_enabled": false, - "reply_by_email_enabled": "incoming+%{key}@incoming.gitlab.com", - "signup_enabled": true, - "web_ide_clientside_preview_enabled": true, - "ingress_modsecurity_enabled": true, - "projects_with_expiration_policy_disabled": 999, - "projects_with_expiration_policy_enabled": 999, - ... - "elasticsearch_enabled": true, - "license_trial_ends_on": null, - "geo_enabled": false, - "git": { - "version": { - "major": 2, - "minor": 26, - "patch": 1 - } - }, - "gitaly": { - "version": "12.10.0-rc1-93-g40980d40", - "servers": 56, - "clusters": 14, - "filesystems": [ - "EXT_2_3_4" - ] - }, - "gitlab_pages": { - "enabled": true, - "version": "1.17.0" - }, - "container_registry_server": { - "vendor": "gitlab", - "version": "2.9.1-gitlab" - }, - "database": { - "adapter": "postgresql", - "version": "9.6.15", - "pg_system_id": 6842684531675334351 - }, - "analytics_unique_visits": { - "g_analytics_contribution": 999, - ... - }, - "usage_activity_by_stage": { - "configure": { - "project_clusters_enabled": 999, - ... - }, - "create": { - "merge_requests": 999, - ... - }, - "manage": { - "events": 999, - ... - }, - "monitor": { - "clusters": 999, - ... - }, - "package": { - "projects_with_packages": 999 - }, - "plan": { - "issues": 999, - ... - }, - "release": { - "deployments": 999, - ... - }, - "secure": { - "user_container_scanning_jobs": 999, - ... - }, - "verify": { - "ci_builds": 999, - ... - } - }, - "usage_activity_by_stage_monthly": { - "configure": { - "project_clusters_enabled": 999, - ... - }, - "create": { - "merge_requests": 999, - ... - }, - "manage": { - "events": 999, - ... - }, - "monitor": { - "clusters": 999, - ... - }, - "package": { - "projects_with_packages": 999 - }, - "plan": { - "issues": 999, - ... - }, - "release": { - "deployments": 999, - ... - }, - "secure": { - "user_container_scanning_jobs": 999, - ... - }, - "verify": { - "ci_builds": 999, - ... - } - }, - "topology": { - "duration_s": 0.013836685999194742, - "application_requests_per_hour": 4224, - "query_apdex_weekly_average": 0.996, - "failures": [], - "nodes": [ - { - "node_memory_total_bytes": 33269903360, - "node_memory_utilization": 0.35, - "node_cpus": 16, - "node_cpu_utilization": 0.2, - "node_uname_info": { - "machine": "x86_64", - "sysname": "Linux", - "release": "4.19.76-linuxkit" - }, - "node_services": [ - { - "name": "web", - "process_count": 16, - "process_memory_pss": 233349888, - "process_memory_rss": 788220927, - "process_memory_uss": 195295487, - "server": "puma" - }, - { - "name": "sidekiq", - "process_count": 1, - "process_memory_pss": 734080000, - "process_memory_rss": 750051328, - "process_memory_uss": 731533312 - }, - ... - ], - ... - }, - ... - ] - } -} -``` - -## Notable changes - -In GitLab 13.5, `pg_system_id` was added to send the [PostgreSQL system identifier](https://www.2ndquadrant.com/en/blog/support-for-postgresqls-system-identifier-in-barman/). - -## Exporting Usage Ping SQL queries and definitions - -Two Rake tasks exist to export Usage Ping definitions. - -- The Rake tasks export the raw SQL queries for `count`, `distinct_count`, `sum`. -- The Rake tasks export the Redis counter class or the line of the Redis block for `redis_usage_data`. -- The Rake tasks calculate the `alt_usage_data` metrics. - -In the home directory of your local GitLab installation run the following Rake tasks for the YAML and JSON versions respectively: - -```shell -# for YAML export -bin/rake gitlab:usage_data:dump_sql_in_yaml - -# for JSON export -bin/rake gitlab:usage_data:dump_sql_in_json - -# You may pipe the output into a file -bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02.yaml -``` - -## Generating and troubleshooting usage ping - -To get a usage ping, or to troubleshoot caching issues on your GitLab instance, please follow [instructions to generate usage ping](../../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping). +<!-- This redirect file can be deleted after February 1, 2021. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/profiling.md b/doc/development/profiling.md index 76c89d361fc..ce9c1191648 100644 --- a/doc/development/profiling.md +++ b/doc/development/profiling.md @@ -128,8 +128,66 @@ console. As a follow up to finding `N+1` queries with Bullet, consider writing a [QueryRecoder test](query_recorder.md) to prevent a regression. +## System stats + +During or after profiling, you may want to get detailed information about the Ruby virtual machine process, +such as memory consumption, time spent on CPU, or garbage collector statistics. These are easy to produce individually +through various tools, but for convenience, a summary endpoint has been added that exports this data as a JSON payload: + +```shell +curl localhost:3000/-/metrics/system | jq +``` + +Example output: + +```json +{ + "version": "ruby 2.7.2p137 (2020-10-01 revision a8323b79eb) [x86_64-linux-gnu]", + "gc_stat": { + "count": 118, + "heap_allocated_pages": 11503, + "heap_sorted_length": 11503, + "heap_allocatable_pages": 0, + "heap_available_slots": 4688580, + "heap_live_slots": 3451712, + "heap_free_slots": 1236868, + "heap_final_slots": 0, + "heap_marked_slots": 3451450, + "heap_eden_pages": 11503, + "heap_tomb_pages": 0, + "total_allocated_pages": 11503, + "total_freed_pages": 0, + "total_allocated_objects": 32679478, + "total_freed_objects": 29227766, + "malloc_increase_bytes": 84760, + "malloc_increase_bytes_limit": 32883343, + "minor_gc_count": 88, + "major_gc_count": 30, + "compact_count": 0, + "remembered_wb_unprotected_objects": 114228, + "remembered_wb_unprotected_objects_limit": 228456, + "old_objects": 3185330, + "old_objects_limit": 6370660, + "oldmalloc_increase_bytes": 21838024, + "oldmalloc_increase_bytes_limit": 119181499 + }, + "memory_rss": 1326501888, + "memory_uss": 1048563712, + "memory_pss": 1139554304, + "time_cputime": 82.885264633, + "time_realtime": 1610459445.5579069, + "time_monotonic": 24001.23145713, + "worker_id": "puma_0" +} +``` + +NOTE: +This endpoint is only available for Rails web workers. Sidekiq workers can not be inspected this way. + ## Settings that impact performance +### Application settings + 1. `development` environment by default works with hot-reloading enabled, this makes Rails to check file changes every request, and create a potential contention lock, as hot reload is single threaded. 1. `development` environment can load code lazily once the request is fired which results in first request to always be slow. @@ -140,3 +198,34 @@ To disable those features for profiling/benchmarking set the `RAILS_PROFILE` env - restart GDK with `gdk restart` *This environment variable is only applicable for the development mode.* + +### GC settings + +Ruby's garbage collector (GC) can be tuned via a variety of environment variables that will directly impact application performance. + +The following table lists these variables along with their default values. + +| Environment variable | Default value | +|--|--| +| `RUBY_GC_HEAP_INIT_SLOTS` | `10000` | +| `RUBY_GC_HEAP_FREE_SLOTS` | `4096` | +| `RUBY_GC_HEAP_FREE_SLOTS_MIN_RATIO` | `0.20` | +| `RUBY_GC_HEAP_FREE_SLOTS_GOAL_RATIO` | `0.40` | +| `RUBY_GC_HEAP_FREE_SLOTS_MAX_RATIO` | `0.65` | +| `RUBY_GC_HEAP_GROWTH_FACTOR` | `1.8` | +| `RUBY_GC_HEAP_GROWTH_MAX_SLOTS` | `0 (disable)` | +| `RUBY_GC_HEAP_OLDOBJECT_LIMIT_FACTOR` | `2.0` | +| `RUBY_GC_MALLOC_LIMIT(_MIN)` | `(16 * 1024 * 1024 /* 16MB */)` | +| `RUBY_GC_MALLOC_LIMIT_MAX` | `(32 * 1024 * 1024 /* 32MB */)` | +| `RUBY_GC_MALLOC_LIMIT_GROWTH_FACTOR` | `1.4` | +| `RUBY_GC_OLDMALLOC_LIMIT(_MIN)` | `(16 * 1024 * 1024 /* 16MB */)` | +| `RUBY_GC_OLDMALLOC_LIMIT_MAX` | `(128 * 1024 * 1024 /* 128MB */)` | +| `RUBY_GC_OLDMALLOC_LIMIT_GROWTH_FACTOR` | `1.2` | + +([Source](https://github.com/ruby/ruby/blob/45b29754cfba8435bc4980a87cd0d32c648f8a2e/gc.c#L254-L308)) + +GitLab may decide to change these settings in order to speed up application performance, lower memory requirements, or both. + +You can see how each of these settings affect GC performance, memory use and application start-up time for an idle instance of +GitLab by runnning the `scripts/perf/gc/collect_gc_stats.rb` script. It will output GC stats and general timing data to standard +out as CSV. diff --git a/doc/development/query_performance.md b/doc/development/query_performance.md index c61d2a0864f..3cb1b10c417 100644 --- a/doc/development/query_performance.md +++ b/doc/development/query_performance.md @@ -21,7 +21,7 @@ When you are optimizing your SQL queries, there are two dimensions to pay attent | Queries in a migration | `100ms` | This is different than the total [migration time](database_review.md#timing-guidelines-for-migrations). | | Concurrent operations in a migration | `5min` | Concurrent operations do not block the database, but they block the GitLab update. This includes operations such as `add_concurrent_index` and `add_concurrent_foreign_key`. | | Background migrations | `1s` | | -| Usage Ping | `1s` | See the [usage ping docs](product_analytics/usage_ping.md#developing-and-testing-usage-ping) for more details. | +| Usage Ping | `1s` | See the [usage ping docs](usage_ping.md#developing-and-testing-usage-ping) for more details. | - When analyzing your query's performance, pay attention to if the time you are seeing is on a [cold or warm cache](#cold-and-warm-cache). These guidelines apply for both cache types. - When working with batched queries, change the range and batch size to see how it effects the query timing and caching. diff --git a/doc/development/secure_coding_guidelines.md b/doc/development/secure_coding_guidelines.md index 44a95f6e820..bd98ea170e5 100644 --- a/doc/development/secure_coding_guidelines.md +++ b/doc/development/secure_coding_guidelines.md @@ -194,7 +194,7 @@ Go's [`regexp`](https://golang.org/pkg/regexp/) package uses `re2` and isn't vul - [Rubular](https://rubular.com/) is a nice online tool to fiddle with Ruby Regexps. - [Runaway Regular Expressions](https://www.regular-expressions.info/catastrophic.html) -- [The impact of regular expression denial of service (ReDoS) in practice: an empirical study at the ecosystem scale](http://people.cs.vt.edu/~davisjam/downloads/publications/DavisCoghlanServantLee-EcosystemREDOS-ESECFSE18.pdf). This research paper discusses approaches to automatically detect ReDoS vulnerabilities. +- [The impact of regular expression denial of service (ReDoS) in practice: an empirical study at the ecosystem scale](https://people.cs.vt.edu/~davisjam/downloads/publications/DavisCoghlanServantLee-EcosystemREDOS-ESECFSE18.pdf). This research paper discusses approaches to automatically detect ReDoS vulnerabilities. - [Freezing the web: A study of redos vulnerabilities in JavaScript-based web servers](https://www.usenix.org/system/files/conference/usenixsecurity18/sec18-staicu.pdf). Another research paper about detecting ReDoS vulnerabilities. ## Server Side Request Forgery (SSRF) diff --git a/doc/development/sidekiq_style_guide.md b/doc/development/sidekiq_style_guide.md index e4f07f732cf..e290eaee7c2 100644 --- a/doc/development/sidekiq_style_guide.md +++ b/doc/development/sidekiq_style_guide.md @@ -825,7 +825,7 @@ For the same reasons that removing workers is dangerous, care should be taken when renaming queues. When renaming queues, use the `sidekiq_queue_migrate` helper migration method, -as show in this example: +as shown in this example: ```ruby class MigrateTheRenamedSidekiqQueue < ActiveRecord::Migration[5.0] diff --git a/doc/development/snowplow.md b/doc/development/snowplow.md new file mode 100644 index 00000000000..6b37936cd93 --- /dev/null +++ b/doc/development/snowplow.md @@ -0,0 +1,623 @@ +--- +stage: Growth +group: Product Intelligence +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Snowplow Guide + +This guide provides an overview of how Snowplow works, and implementation details. + +For more information about Product Intelligence, see: + +- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) +- [Usage Ping Guide](usage_ping.md) + +More useful links: + +- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/) +- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/) +- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/) +- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) + +## What is Snowplow + +Snowplow is an enterprise-grade marketing and Product Intelligence platform which helps track the way users engage with our website and application. + +[Snowplow](https://github.com/snowplow/snowplow) consists of the following loosely-coupled sub-systems: + +- **Trackers** fire Snowplow events. Snowplow has 12 trackers, covering web, mobile, desktop, server, and IoT. +- **Collectors** receive Snowplow events from trackers. We have three different event collectors, synchronizing events either to Amazon S3, Apache Kafka, or Amazon Kinesis. +- **Enrich** cleans up the raw Snowplow events, enriches them and puts them into storage. We have an Hadoop-based enrichment process, and a Kinesis-based or Kafka-based process. +- **Storage** is where the Snowplow events live. We store the Snowplow events in a flat file structure on S3, and in the Redshift and PostgreSQL databases. +- **Data modeling** is where event-level data is joined with other data sets and aggregated into smaller data sets, and business logic is applied. This produces a clean set of tables which make it easier to perform analysis on the data. We have data models for Redshift and Looker. +- **Analytics** are performed on the Snowplow events or on the aggregate tables. + +![snowplow_flow](img/snowplow_flow.png) + +## Snowplow schema + +We have many definitions of Snowplow's schema. We have an active issue to [standardize this schema](https://gitlab.com/gitlab-org/gitlab/-/issues/207930) including the following definitions: + +- Frontend and backend taxonomy as listed below +- [Structured event taxonomy](#structured-event-taxonomy) +- [Self describing events](https://github.com/snowplow/snowplow/wiki/Custom-events#self-describing-events) +- [Iglu schema](https://gitlab.com/gitlab-org/iglu/) +- [Snowplow authored events](https://github.com/snowplow/snowplow/wiki/Snowplow-authored-events) + +## Enabling Snowplow + +Tracking can be enabled at: + +- The instance level, which enables tracking on both the frontend and backend layers. +- User level, though user tracking can be disabled on a per-user basis. GitLab tracking respects the [Do Not Track](https://www.eff.org/issues/do-not-track) standard, so any user who has enabled the Do Not Track option in their browser is not tracked at a user level. + +We use Snowplow for the majority of our tracking strategy and it is enabled on GitLab.com. On a self-managed instance, Snowplow can be enabled by navigating to: + +- **Admin Area > Settings > General** in the UI. +- `admin/application_settings/integrations` in your browser. + +The following configuration is required: + +| Name | Value | +|---------------|---------------------------| +| Collector | `snowplow.trx.gitlab.net` | +| Site ID | `gitlab` | +| Cookie domain | `.gitlab.com` | + +## Snowplow request flow + +The following example shows a basic request/response flow between the following components: + +- Snowplow JS / Ruby Trackers on GitLab.com +- [GitLab.com Snowplow Collector](https://gitlab.com/gitlab-com/gl-infra/readiness/-/blob/master/library/snowplow/index.md) +- The GitLab S3 Bucket +- The GitLab Snowflake Data Warehouse +- Sisense: + +```mermaid +sequenceDiagram + participant Snowplow JS (Frontend) + participant Snowplow Ruby (Backend) + participant GitLab.com Snowplow Collector + participant S3 Bucket + participant Snowflake DW + participant Sisense Dashboards + Snowplow JS (Frontend) ->> GitLab.com Snowplow Collector: FE Tracking event + Snowplow Ruby (Backend) ->> GitLab.com Snowplow Collector: BE Tracking event + loop Process using Kinesis Stream + GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Log raw events + GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Enrich events + GitLab.com Snowplow Collector ->> GitLab.com Snowplow Collector: Write to disk + end + GitLab.com Snowplow Collector ->> S3 Bucket: Kinesis Firehose + S3 Bucket->>Snowflake DW: Import data + Snowflake DW->>Snowflake DW: Transform data using dbt + Snowflake DW->>Sisense Dashboards: Data available for querying +``` + +## Structured event taxonomy + +When adding new click events, we should add them in a way that's internally consistent. If we don't, it is very painful to perform analysis across features since each feature captures events differently. + +The current method provides several attributes that are sent on each click event. Please try to follow these guidelines when specifying events to capture: + +| attribute | type | required | description | +| --------- | ------- | -------- | ----------- | +| category | text | true | The page or backend area of the application. Unless infeasible, please use the Rails page attribute by default in the frontend, and namespace + classname on the backend. | +| action | text | true | The action the user is taking, or aspect that's being instrumented. The first word should always describe the action or aspect: clicks should be `click`, activations should be `activate`, creations should be `create`, etc. Use underscores to describe what was acted on; for example, activating a form field would be `activate_form_input`. An interface action like clicking on a dropdown would be `click_dropdown`, while a behavior like creating a project record from the backend would be `create_project` | +| label | text | false | The specific element, or object that's being acted on. This is either the label of the element (e.g. a tab labeled 'Create from template' may be `create_from_template`) or a unique identifier if no text is available (e.g. closing the Groups dropdown in the top navbar might be `groups_dropdown_close`), or it could be the name or title attribute of a record being created. | +| property | text | false | Any additional property of the element, or object being acted on. | +| value | decimal | false | Describes a numeric value or something directly related to the event. This could be the value of an input (e.g. `10` when clicking `internal` visibility). | + +### Web-specific parameters + +Snowplow JS adds many [web-specific parameters](https://docs.snowplowanalytics.com/docs/collecting-data/collecting-from-own-applications/snowplow-tracker-protocol/#Web-specific_parameters) to all web events by default. + +## Implementing Snowplow JS (Frontend) tracking + +GitLab provides `Tracking`, an interface that wraps the [Snowplow JavaScript Tracker](https://github.com/snowplow/snowplow/wiki/javascript-tracker) for tracking custom events. There are a few ways to use tracking, but each generally requires at minimum, a `category` and an `action`. Additional data can be provided that adheres to our [Structured event taxonomy](#structured-event-taxonomy). + +| field | type | default value | description | +|:-----------|:-------|:---------------------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `category` | string | document.body.dataset.page | Page or subsection of a page that events are being captured within. | +| `action` | string | 'generic' | Action the user is taking. Clicks should be `click` and activations should be `activate`, so for example, focusing a form field would be `activate_form_input`, and clicking a button would be `click_button`. | +| `data` | object | {} | Additional data such as `label`, `property`, `value`, and `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). | + +### Tracking in HAML (or Vue Templates) + +When working within HAML (or Vue templates) we can add `data-track-*` attributes to elements of interest. All elements that have a `data-track-event` attribute automatically have event tracking bound on clicks. + +Below is an example of `data-track-*` attributes assigned to a button: + +```haml +%button.btn{ data: { track: { event: "click_button", label: "template_preview", property: "my-template" } } } +``` + +```html +<button class="btn" + data-track-event="click_button" + data-track-label="template_preview" + data-track-property="my-template" +/> +``` + +Event listeners are bound at the document level to handle click events on or within elements with these data attributes. This allows them to be properly handled on re-rendering and changes to the DOM. Note that because of the way these events are bound, click events should not be stopped from propagating up the DOM tree. If for any reason click events are being stopped from propagating, you need to implement your own listeners and follow the instructions in [Tracking in raw JavaScript](#tracking-in-raw-javascript). + +Below is a list of supported `data-track-*` attributes: + +| attribute | required | description | +|:----------------------|:---------|:------------| +| `data-track-event` | true | Action the user is taking. Clicks must be prepended with `click` and activations must be prepended with `activate`. For example, focusing a form field would be `activate_form_input` and clicking a button would be `click_button`. | +| `data-track-label` | false | The `label` as described in our [Structured event taxonomy](#structured-event-taxonomy). | +| `data-track-property` | false | The `property` as described in our [Structured event taxonomy](#structured-event-taxonomy). | +| `data-track-value` | false | The `value` as described in our [Structured event taxonomy](#structured-event-taxonomy). If omitted, this is the element's `value` property or an empty string. For checkboxes, the default value is the element's checked attribute or `false` when unchecked. | +| `data-track-context` | false | The `context` as described in our [Structured event taxonomy](#structured-event-taxonomy). | + +#### Caveats + +When using the GitLab helper method [`nav_link`](https://gitlab.com/gitlab-org/gitlab/-/blob/898b286de322e5df6a38d257b10c94974d580df8/app/helpers/tab_helper.rb#L69) be sure to wrap `html_options` under the `html_options` keyword argument. +Be careful, as this behavior can be confused with the `ActionView` helper method [`link_to`](https://api.rubyonrails.org/v5.2.3/classes/ActionView/Helpers/UrlHelper.html#method-i-link_to) that does not require additional wrapping of `html_options` + +`nav_link(controller: ['dashboard/groups', 'explore/groups'], html_options: { data: { track_label: "groups_dropdown", track_event: "click_dropdown" } })` + +vs + +`link_to assigned_issues_dashboard_path, title: _('Issues'), data: { track_label: 'main_navigation', track_event: 'click_issues_link' }` + +### Tracking within Vue components + +There's a tracking Vue mixin that can be used in components if more complex tracking is required. To use it, first import the `Tracking` library and request a mixin. + +```javascript +import Tracking from '~/tracking'; +const trackingMixin = Tracking.mixin({ label: 'right_sidebar' }); +``` + +You can provide default options that are passed along whenever an event is tracked from within your component. For instance, if all events within a component should be tracked with a given `label`, you can provide one at this time. Available defaults are `category`, `label`, `property`, and `value`. If no category is specified, `document.body.dataset.page` is used as the default. + +You can then use the mixin normally in your component with the `mixin` Vue declaration. The mixin also provides the ability to specify tracking options in `data` or `computed`. These override any defaults and allow the values to be dynamic from props, or based on state. + +```javascript +export default { + mixins: [trackingMixin], + // ...[component implementation]... + data() { + return { + expanded: false, + tracking: { + label: 'left_sidebar' + } + }; + }, +} +``` + +The mixin provides a `track` method that can be called within the template, or from component methods. An example of the whole implementation might look like the following. + +```javascript +export default { + mixins: [Tracking.mixin({ label: 'right_sidebar' })], + data() { + return { + expanded: false, + }; + }, + methods: { + toggle() { + this.expanded = !this.expanded; + this.track('click_toggle', { value: this.expanded }) + } + } +}; +``` + +And if needed within the template, you can use the `track` method directly as well. + +```html +<template> + <div> + <a class="toggle" @click.prevent="toggle">Toggle</a> + <div v-if="expanded"> + <p>Hello world!</p> + <a @click.prevent="track('click_action')">Track an event</a> + </div> + </div> +</template> +``` + +### Tracking in raw JavaScript + +Custom event tracking and instrumentation can be added by directly calling the `Tracking.event` static function. The following example demonstrates tracking a click on a button by calling `Tracking.event` manually. + +```javascript +import Tracking from '~/tracking'; + +const button = document.getElementById('create_from_template_button'); +button.addEventListener('click', () => { + Tracking.event('dashboard:projects:index', 'click_button', { + label: 'create_from_template', + property: 'template_preview', + value: 'rails', + }); +}) +``` + +### Tests and test helpers + +In Jest particularly in Vue tests, you can use the following: + +```javascript +import { mockTracking } from 'helpers/tracking_helper'; + +describe('MyTracking', () => { + let spy; + + beforeEach(() => { + spy = mockTracking('_category_', wrapper.element, jest.spyOn); + }); + + it('tracks an event when clicked on feedback', () => { + wrapper.find('.discover-feedback-icon').trigger('click'); + + expect(spy).toHaveBeenCalledWith('_category_', 'click_button', { + label: 'security-discover-feedback-cta', + property: '0', + }); + }); +}); +``` + +In obsolete Karma tests it's used as below: + +```javascript +import { mockTracking, triggerEvent } from 'spec/helpers/tracking_helper'; + +describe('my component', () => { + let trackingSpy; + + beforeEach(() => { + trackingSpy = mockTracking('_category_', vm.$el, spyOn); + }); + + const triggerEvent = () => { + // action which should trigger a event + }; + + it('tracks an event when toggled', () => { + expect(trackingSpy).not.toHaveBeenCalled(); + + triggerEvent('a.toggle'); + + expect(trackingSpy).toHaveBeenCalledWith('_category_', 'click_edit_button', { + label: 'right_sidebar', + property: 'confidentiality', + }); + }); +}); +``` + +## Implementing Snowplow Ruby (Backend) tracking + +GitLab provides `Gitlab::Tracking`, an interface that wraps the [Snowplow Ruby Tracker](https://github.com/snowplow/snowplow/wiki/ruby-tracker) for tracking custom events. + +Custom event tracking and instrumentation can be added by directly calling the `GitLab::Tracking.event` class method, which accepts the following arguments: + +| argument | type | default value | description | +|:-----------|:-------|:--------------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `category` | string | 'application' | Area or aspect of the application. This could be `HealthCheckController` or `Lfs::FileTransformer` for instance. | +| `action` | string | 'generic' | The action being taken, which can be anything from a controller action like `create` to something like an Active Record callback. | +| `data` | object | {} | Additional data such as `label`, `property`, `value`, and `context` as described in [Structured event taxonomy](#structured-event-taxonomy). These are set as empty strings if you don't provide them. | + +Tracking can be viewed as either tracking user behavior, or can be used for instrumentation to monitor and visualize performance over time in an area or aspect of code. + +For example: + +```ruby +class Projects::CreateService < BaseService + def execute + project = Project.create(params) + + Gitlab::Tracking.event('Projects::CreateService', 'create_project', + label: project.errors.full_messages.to_sentence, + value: project.valid? + ) + end +end +``` + +### Unit testing + +Use the `expect_snowplow_event` helper when testing backend Snowplow events. See [testing best practices]( +https://docs.gitlab.com/ee/development/testing_guide/best_practices.html#test-snowplow-events) for details. + +### Performance + +We use the [AsyncEmitter](https://github.com/snowplow/snowplow/wiki/Ruby-Tracker#52-the-asyncemitter-class) when tracking events, which allows for instrumentation calls to be run in a background thread. This is still an active area of development. + +## Developing and testing Snowplow + +There are several tools for developing and testing Snowplow Event + +| Testing Tool | Frontend Tracking | Backend Tracking | Local Development Environment | Production Environment | Production Environment | +|----------------------------------------------|--------------------|---------------------|-------------------------------|------------------------|------------------------| +| Snowplow Analytics Debugger Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** | +| Snowplow Inspector Chrome Extension | **{check-circle}** | **{dotted-circle}** | **{check-circle}** | **{check-circle}** | **{check-circle}** | +| Snowplow Micro | **{check-circle}** | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{dotted-circle}** | +| Snowplow Mini | **{check-circle}** | **{check-circle}** | **{dotted-circle}** | **{status_preparing}** | **{status_preparing}** | + +**Legend** + +**{check-circle}** Available, **{status_preparing}** In progress, **{dotted-circle}** Not Planned + +### Preparing your MR for Review + +1. For frontend events, in the MR description section, add a screenshot of the event's relevant section using the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension. +1. For backend events, please use Snowplow Micro and add the output of the Snowplow Micro good events `GET http://localhost:9090/micro/good`. + +### Snowplow Analytics Debugger Chrome Extension + +Snowplow Analytics Debugger is a browser extension for testing frontend events. This works on production, staging and local development environments. + +1. Install the [Snowplow Analytics Debugger](https://chrome.google.com/webstore/detail/snowplow-analytics-debugg/jbnlcgeengmijcghameodeaenefieedm) Chrome browser extension. +1. Open Chrome DevTools to the Snowplow Analytics Debugger tab. +1. Learn more at [Igloo Analytics](https://www.iglooanalytics.com/blog/snowplow-analytics-debugger-chrome-extension.html). + +### Snowplow Inspector Chrome Extension + +Snowplow Inspector Chrome Extension is a browser extension for testing frontend events. This works on production, staging and local development environments. + +1. Install [Snowplow Inspector](https://chrome.google.com/webstore/detail/snowplow-inspector/maplkdomeamdlngconidoefjpogkmljm?hl=en). +1. Open the Chrome extension by pressing the Snowplow Inspector icon beside the address bar. +1. Click around on a webpage with Snowplow and you should see JavaScript events firing in the inspector window. + +### Snowplow Micro + +Snowplow Micro is a very small version of a full Snowplow data collection pipeline: small enough that it can be launched by a test suite. Events can be recorded into Snowplow Micro just as they can a full Snowplow pipeline. Micro then exposes an API that can be queried. + +Snowplow Micro is a Docker-based solution for testing frontend and backend events in a local development environment. You need to modify GDK using the instructions below to set this up. + +- Read [Introducing Snowplow Micro](https://snowplowanalytics.com/blog/2019/07/17/introducing-snowplow-micro/) +- Look at the [Snowplow Micro repository](https://github.com/snowplow-incubator/snowplow-micro) +- Watch our [installation guide recording](https://www.youtube.com/watch?v=OX46fo_A0Ag) + +1. Ensure Docker is installed and running. + +1. Install [Snowplow Micro](https://github.com/snowplow-incubator/snowplow-micro) by cloning the settings in [this project](https://gitlab.com/gitlab-org/snowplow-micro-configuration): +1. Navigate to the directory with the cloned project, and start the appropriate Docker + container with the following script: + + ```shell + ./snowplow-micro.sh + ``` + +1. Update your instance's settings to enable Snowplow events and point to the Snowplow Micro collector: + + ```shell + gdk psql -d gitlabhq_development + update application_settings set snowplow_collector_hostname='localhost:9090', snowplow_enabled=true, snowplow_cookie_domain='.gitlab.com'; + ``` + +1. Update `DEFAULT_SNOWPLOW_OPTIONS` in `app/assets/javascripts/tracking.js` to remove `forceSecureTracker: true`: + + ```diff + diff --git a/app/assets/javascripts/tracking.js b/app/assets/javascripts/tracking.js + index 0a1211d0a76..3b98c8f28f2 100644 + --- a/app/assets/javascripts/tracking.js + +++ b/app/assets/javascripts/tracking.js + @@ -7,7 +7,6 @@ const DEFAULT_SNOWPLOW_OPTIONS = { + appId: '', + userFingerprint: false, + respectDoNotTrack: true, + - forceSecureTracker: true, + eventMethod: 'post', + contexts: { webPage: true, performanceTiming: true }, + formTracking: false, + + ``` + +1. Update `snowplow_options` in `lib/gitlab/tracking.rb` to add `protocol` and `port`: + + ```diff + diff --git a/lib/gitlab/tracking.rb b/lib/gitlab/tracking.rb + index 618e359211b..e9084623c43 100644 + --- a/lib/gitlab/tracking.rb + +++ b/lib/gitlab/tracking.rb + @@ -41,7 +41,9 @@ def snowplow_options(group) + cookie_domain: Gitlab::CurrentSettings.snowplow_cookie_domain, + app_id: Gitlab::CurrentSettings.snowplow_app_id, + form_tracking: additional_features, + - link_click_tracking: additional_features + + link_click_tracking: additional_features, + + protocol: 'http', + + port: 9090 + }.transform_keys! { |key| key.to_s.camelize(:lower).to_sym } + end + ``` + +1. Update `emitter` in `lib/gitlab/tracking/destinations/snowplow.rb` to change `protocol`: + + ```diff + diff --git a/lib/gitlab/tracking/destinations/snowplow.rb b/lib/gitlab/tracking/destinations/snowplow.rb + index 4fa844de325..5dd9d0eacfb 100644 + --- a/lib/gitlab/tracking/destinations/snowplow.rb + +++ b/lib/gitlab/tracking/destinations/snowplow.rb + @@ -40,7 +40,7 @@ def tracker + def emitter + SnowplowTracker::AsyncEmitter.new( + Gitlab::CurrentSettings.snowplow_collector_hostname, + - protocol: 'https' + + protocol: 'http' + ) + end + end + + ``` + +1. Restart GDK: + + ```shell + `gdk restart` + ``` + +1. Send a test Snowplow event from the Rails console: + + ```ruby + Gitlab::Tracking.self_describing_event('iglu:com.gitlab/pageview_context/jsonschema/1-0-0', data: { page_type: 'MY_TYPE' }, context: nil) + ``` + +1. Navigate to `localhost:9090/micro/good` to see the event. + +### Snowplow Mini + +[Snowplow Mini](https://github.com/snowplow/snowplow-mini) is an easily-deployable, single-instance version of Snowplow. + +Snowplow Mini can be used for testing frontend and backend events on a production, staging and local development environment. + +For GitLab.com, we're setting up a [QA and Testing environment](https://gitlab.com/gitlab-org/telemetry/-/issues/266) using Snowplow Mini. + +## Snowplow Schemas + +### [gitlab_standard](https://gitlab.com/gitlab-org/iglu/-/blob/master/public/schemas/com.gitlab/gitlab_standard/jsonschema/1-0-0) Schema + +| Field Name | Required | Type | Description | +|--------------|---------------------|---------|--------------------------------| +| project_id | **{dotted-circle}** | integer | ID of the associated project | +| namespace_id | **{dotted-circle}** | integer | ID of the associated namespace | + +### Default Schema + +| Field Name | Required | Type | Description | +|--------------------------|---------------------|-----------|----------------------------------------------------------------------------------------------------------------------------------| +| app_id | **{check-circle}** | string | Unique identifier for website / application | +| base_currency | **{dotted-circle}** | string | Reporting currency | +| br_colordepth | **{dotted-circle}** | integer | Browser color depth | +| br_cookies | **{dotted-circle}** | boolean | Does the browser permit cookies? | +| br_family | **{dotted-circle}** | string | Browser family | +| br_features_director | **{dotted-circle}** | boolean | Director plugin installed? | +| br_features_flash | **{dotted-circle}** | boolean | Flash plugin installed? | +| br_features_gears | **{dotted-circle}** | boolean | Google gears installed? | +| br_features_java | **{dotted-circle}** | boolean | Java plugin installed? | +| br_features_pdf | **{dotted-circle}** | boolean | Adobe PDF plugin installed? | +| br_features_quicktime | **{dotted-circle}** | boolean | Quicktime plugin installed? | +| br_features_realplayer | **{dotted-circle}** | boolean | Realplayer plugin installed? | +| br_features_silverlight | **{dotted-circle}** | boolean | Silverlight plugin installed? | +| br_features_windowsmedia | **{dotted-circle}** | boolean | Windows media plugin installed? | +| br_lang | **{dotted-circle}** | string | Language the browser is set to | +| br_name | **{dotted-circle}** | string | Browser name | +| br_renderengine | **{dotted-circle}** | string | Browser rendering engine | +| br_type | **{dotted-circle}** | string | Browser type | +| br_version | **{dotted-circle}** | string | Browser version | +| br_viewheight | **{dotted-circle}** | string | Browser viewport height | +| br_viewwidth | **{dotted-circle}** | string | Browser viewport width | +| collector_tstamp | **{dotted-circle}** | timestamp | Time stamp for the event recorded by the collector | +| contexts | **{dotted-circle}** | | | +| derived_contexts | **{dotted-circle}** | | Contexts derived in the Enrich process | +| derived_tstamp | **{dotted-circle}** | timestamp | Timestamp making allowance for innaccurate device clock | +| doc_charset | **{dotted-circle}** | string | Web page’s character encoding | +| doc_height | **{dotted-circle}** | string | Web page height | +| doc_width | **{dotted-circle}** | string | Web page width | +| domain_sessionid | **{dotted-circle}** | string | Unique identifier (UUID) for this visit of this user_id to this domain | +| domain_sessionidx | **{dotted-circle}** | integer | Index of number of visits that this user_id has made to this domain (The first visit is `1`) | +| domain_userid | **{dotted-circle}** | string | Unique identifier for a user, based on a first party cookie (so domain specific) | +| dvce_created_tstamp | **{dotted-circle}** | timestamp | Timestamp when event occurred, as recorded by client device | +| dvce_ismobile | **{dotted-circle}** | boolean | Indicates whether device is mobile | +| dvce_screenheight | **{dotted-circle}** | string | Screen / monitor resolution | +| dvce_screenwidth | **{dotted-circle}** | string | Screen / monitor resolution | +| dvce_sent_tstamp | **{dotted-circle}** | timestamp | Timestamp when event was sent by client device to collector | +| dvce_type | **{dotted-circle}** | string | Type of device | +| etl_tags | **{dotted-circle}** | string | JSON of tags for this ETL run | +| etl_tstamp | **{dotted-circle}** | timestamp | Timestamp event began ETL | +| event | **{dotted-circle}** | string | Event type | +| event_fingerprint | **{dotted-circle}** | string | Hash client-set event fields | +| event_format | **{dotted-circle}** | string | Format for event | +| event_id | **{dotted-circle}** | string | Event UUID | +| event_name | **{dotted-circle}** | string | Event name | +| event_vendor | **{dotted-circle}** | string | The company who developed the event model | +| event_version | **{dotted-circle}** | string | Version of event schema | +| geo_city | **{dotted-circle}** | string | City of IP origin | +| geo_country | **{dotted-circle}** | string | Country of IP origin | +| geo_latitude | **{dotted-circle}** | string | An approximate latitude | +| geo_longitude | **{dotted-circle}** | string | An approximate longitude | +| geo_region | **{dotted-circle}** | string | Region of IP origin | +| geo_region_name | **{dotted-circle}** | string | Region of IP origin | +| geo_timezone | **{dotted-circle}** | string | Timezone of IP origin | +| geo_zipcode | **{dotted-circle}** | string | Zip (postal) code of IP origin | +| ip_domain | **{dotted-circle}** | string | Second level domain name associated with the visitor’s IP address | +| ip_isp | **{dotted-circle}** | string | Visitor’s ISP | +| ip_netspeed | **{dotted-circle}** | string | Visitor’s connection type | +| ip_organization | **{dotted-circle}** | string | Organization associated with the visitor’s IP address – defaults to ISP name if none is found | +| mkt_campaign | **{dotted-circle}** | string | The campaign ID | +| mkt_clickid | **{dotted-circle}** | string | The click ID | +| mkt_content | **{dotted-circle}** | string | The content or ID of the ad. | +| mkt_medium | **{dotted-circle}** | string | Type of traffic source | +| mkt_network | **{dotted-circle}** | string | The ad network to which the click ID belongs | +| mkt_source | **{dotted-circle}** | string | The company / website where the traffic came from | +| mkt_term | **{dotted-circle}** | string | Keywords associated with the referrer | +| name_tracker | **{dotted-circle}** | string | The tracker namespace | +| network_userid | **{dotted-circle}** | string | Unique identifier for a user, based on a cookie from the collector (so set at a network level and shouldn’t be set by a tracker) | +| os_family | **{dotted-circle}** | string | Operating system family | +| os_manufacturer | **{dotted-circle}** | string | Manufacturers of operating system | +| os_name | **{dotted-circle}** | string | Name of operating system | +| os_timezone | **{dotted-circle}** | string | Client operating system timezone | +| page_referrer | **{dotted-circle}** | string | Referrer URL | +| page_title | **{dotted-circle}** | string | Page title | +| page_url | **{dotted-circle}** | string | Page URL | +| page_urlfragment | **{dotted-circle}** | string | Fragment aka anchor | +| page_urlhost | **{dotted-circle}** | string | Host aka domain | +| page_urlpath | **{dotted-circle}** | string | Path to page | +| page_urlport | **{dotted-circle}** | integer | Port if specified, 80 if not | +| page_urlquery | **{dotted-circle}** | string | Query string | +| page_urlscheme | **{dotted-circle}** | string | Scheme (protocol name) | +| platform | **{dotted-circle}** | string | The platform the app runs on | +| pp_xoffset_max | **{dotted-circle}** | integer | Maximum page x offset seen in the last ping period | +| pp_xoffset_min | **{dotted-circle}** | integer | Minimum page x offset seen in the last ping period | +| pp_yoffset_max | **{dotted-circle}** | integer | Maximum page y offset seen in the last ping period | +| pp_yoffset_min | **{dotted-circle}** | integer | Minimum page y offset seen in the last ping period | +| refr_domain_userid | **{dotted-circle}** | string | The Snowplow domain_userid of the referring website | +| refr_dvce_tstamp | **{dotted-circle}** | timestamp | The time of attaching the domain_userid to the inbound link | +| refr_medium | **{dotted-circle}** | string | Type of referer | +| refr_source | **{dotted-circle}** | string | Name of referer if recognised | +| refr_term | **{dotted-circle}** | string | Keywords if source is a search engine | +| refr_urlfragment | **{dotted-circle}** | string | Referer URL fragment | +| refr_urlhost | **{dotted-circle}** | string | Referer host | +| refr_urlpath | **{dotted-circle}** | string | Referer page path | +| refr_urlport | **{dotted-circle}** | integer | Referer port | +| refr_urlquery | **{dotted-circle}** | string | Referer URL querystring | +| refr_urlscheme | **{dotted-circle}** | string | Referer scheme | +| se_action | **{dotted-circle}** | string | The action / event itself | +| se_category | **{dotted-circle}** | string | The category of event | +| se_label | **{dotted-circle}** | string | A label often used to refer to the ‘object’ the action is performed on | +| se_property | **{dotted-circle}** | string | A property associated with either the action or the object | +| se_value | **{dotted-circle}** | decimal | A value associated with the user action | +| ti_category | **{dotted-circle}** | string | Item category | +| ti_currency | **{dotted-circle}** | string | Currency | +| ti_name | **{dotted-circle}** | string | Item name | +| ti_orderid | **{dotted-circle}** | string | Order ID | +| ti_price | **{dotted-circle}** | decimal | Item price | +| ti_price_base | **{dotted-circle}** | decimal | Item price in base currency | +| ti_quantity | **{dotted-circle}** | integer | Item quantity | +| ti_sku | **{dotted-circle}** | string | Item SKU | +| tr_affiliation | **{dotted-circle}** | string | Transaction affiliation (such as channel) | +| tr_city | **{dotted-circle}** | string | Delivery address: city | +| tr_country | **{dotted-circle}** | string | Delivery address: country | +| tr_currency | **{dotted-circle}** | string | Transaction Currency | +| tr_orderid | **{dotted-circle}** | string | Order ID | +| tr_shipping | **{dotted-circle}** | decimal | Delivery cost charged | +| tr_shipping_base | **{dotted-circle}** | decimal | Shipping cost in base currency | +| tr_state | **{dotted-circle}** | string | Delivery address: state | +| tr_tax | **{dotted-circle}** | decimal | Transaction tax value (such as amount of VAT included) | +| tr_tax_base | **{dotted-circle}** | decimal | Tax applied in base currency | +| tr_total | **{dotted-circle}** | decimal | Transaction total value | +| tr_total_base | **{dotted-circle}** | decimal | Total amount of transaction in base currency | +| true_tstamp | **{dotted-circle}** | timestamp | User-set exact timestamp | +| txn_id | **{dotted-circle}** | string | Transaction ID | +| unstruct_event | **{dotted-circle}** | JSON | The properties of the event | +| uploaded_at | **{dotted-circle}** | | | +| user_fingerprint | **{dotted-circle}** | integer | User identifier based on (hopefully unique) browser features | +| user_id | **{dotted-circle}** | string | Unique identifier for user, set by the business using setUserId | +| user_ipaddress | **{dotted-circle}** | string | IP address | +| useragent | **{dotted-circle}** | string | User agent (expressed as a browser string) | +| v_collector | **{dotted-circle}** | string | Collector version | +| v_etl | **{dotted-circle}** | string | ETL version | +| v_tracker | **{dotted-circle}** | string | Identifier for Snowplow tracker | diff --git a/doc/development/stage_group_dashboards.md b/doc/development/stage_group_dashboards.md new file mode 100644 index 00000000000..453d71411c3 --- /dev/null +++ b/doc/development/stage_group_dashboards.md @@ -0,0 +1,148 @@ +--- +stage: Enablement +group: Infrastructure +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Dashboards for stage groups + +## Introduction + +Observability is about bringing visibility into a system to see and understand the state of each component, with context, to support performance tuning and debugging. To run a SaaS platform at scale, a rich and detailed observability platform is a necessity. We have a set of monitoring dashboards designed for [each stage group](https://about.gitlab.com/handbook/product/categories/#devops-stages). + +These dashboards are designed to give an insight, to everyone working in a feature category, into how their code operates at GitLab.com scale. They are grouped per stage group to show the impact of feature/code changes, deployments, and feature-flag toggles. + +Each stage group has a dashboard consisting of metrics at the application level, such as Rails Web Requests, Rails API Requests, Sidekiq Jobs, and so on. The metrics in each dashboard are filtered and accumulated based on the [GitLab product categories](https://about.gitlab.com/handbook/product/categories/) and [feature categories](feature_categorization/index.md). + +The list of dashboards for each stage group is accessible at <https://dashboards.gitlab.net/dashboards/f/stage-groups/stage-groups> (GitLab team members only), or at [the public mirror](https://dashboards.gitlab.com/dashboards?tag=feature_category&tag=stage-groups) (accessible to everyone with a GitLab.com account, with some limitations). + +The dashboards for stage groups are at a very early stage. All contributions are welcome. If you have any questions or suggestions, please submit an issue in the [Scalability Team issues tracker](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/new). + +## Usage + +Inside a stage group dashboard, there are some notable components. Let's take the [Source Code group's dashboard](https://dashboards.gitlab.net/d/stage-groups-source_code/stage-groups-group-dashboard-create-source-code?orgId=1) as an example. + +### Time range controls + +![Default time filter](img/stage_group_dashboards_time_filter.png) + +- By default, all the times are in UTC timezone. [We use UTC when communicating in Engineering](https://about.gitlab.com/handbook/communication/#writing-style-guidelines). +- All metrics recorded in the GitLab production system have [1-year retention](https://gitlab.com/gitlab-cookbooks/gitlab-prometheus/-/blob/31526b03fef823e2f9b3cda7c75dcd28a12418a3/attributes/prometheus.rb#L40). +- Alternatively, you can zoom in or filter the time range directly on a graph. See the [Grafana Time Range Controls](https://grafana.com/docs/grafana/latest/dashboards/time-range-controls/) documentation for more information. + +### Filters and annotations + +In each dashboard, there are two filters and some annotations switches on the top of the page. [Grafana annotations](https://grafana.com/docs/grafana/latest/dashboards/annotations/) mark some special events, which are meaningful to development and operational activities, directly on the graphs. + +![Filters and annotations](img/stage_group_dashboards_filters.png) + +| Name | Type | Description | +| ---- | ---- | ----------- | +| `PROMETHEUS_DS` | filter | Filter the selective [Prometheus data sources](https://about.gitlab.com/handbook/engineering/monitoring/#prometheus). The default value is `Global`, which aggregates the data from all available data sources. Most of the time, you don't need to care about this filter. | +| `environment` | filter | Filter the environment the metrics are fetched from. The default setting is production (`gprd`). Check [Production Environment mapping](https://about.gitlab.com/handbook/engineering/infrastructure/production/architecture/#environments) for other possibilities. | +| `deploy` | annotation | Mark a deployment event on the GitLab.com SaaS platform. | +| `canary-deploy` | annotation | Mark a [canary deployment](https://about.gitlab.com/handbook/engineering/#canary-testing) event on the GitLab.com SaaS platform. | +| `feature-flags` | annotation | Mark the time point where a feature flag is updated.| + +This is an example of a feature flag annotation displayed on a dashboard panel. + +![Annotations](img/stage_group_dashboards_annotation.png) + +### Metrics panels + +![Metrics panels](img/stage_group_dashboards_metrics.png) + +Although most of the metrics displayed in the panels are self-explanatory in their title and nearby description, note the following: + +- The events are counted, measured, accumulated, then collected, and stored as [time series](https://prometheus.io/docs/concepts/data_model/). The data are calculated using statistical methods to produce metrics. It means that metrics are approximately correct and meaningful over a time period. They help you have an overview of the stage of a system over time. They are not meant to give you precise numbers of a discrete event. If you need a higher level of accuracy, please look at another monitoring tool like [logs](https://about.gitlab.com/handbook/engineering/monitoring/#logs). Please read the following examples for more explanations. +- All the rate metrics' units are `requests per second`. The default aggregate time frame is 1 minute. For example, a panel shows the requests per second number at `2020-12-25 00:42:00` is `34.13`. It means at the minute 42 (from `2020-12-25 00:42:00` to `2020-12-25 00:42:59` ), there are approximately `34.13 * 60 = ~ 2047` requests processed by the web servers. +- You may encounter some gotchas related to decimal fraction and rounding up frequently, especially in low-traffic cases. For example, the error rate of `RepositoryUpdateMirrorWorker` at `2020-12-25 02:04:00` is `0.07`, equivalent to `4.2` jobs per minute. The raw result is `0.06666666667`, equivalent to 4 jobs per minute. +- All the rate metrics are more accurate when the data is big enough. The default floating-point precision is 2. In some extremely low panels, you would see `0.00` although there is still some real traffic. + +To inspect the raw data of the panel for further calculation, click on the Inspect button from the dropdown menu of a panel. Queries, raw data, and panel JSON structure are available. Read more at [Grafana panel inspection](https://grafana.com/docs/grafana/latest/panels/inspect-panel/). + +All the dashboards are powered by [Grafana](https://grafana.com/), a frontend for displaying metrics. Grafana consumes the data returned from queries to backend Prometheus data source, then presents them under different visualizations. The stage group dashboards are built to serve the most common use cases with a limited set of filters, and pre-built queries. Grafana provides a way to explore and visualize the metrics data with [Grafana Explore](https://grafana.com/docs/grafana/latest/explore/). This would require some knowledge about [Prometheus Promql query language](https://prometheus.io/docs/prometheus/latest/querying/basics/). + +## How to debug with the dashboards + +- A team member in the Code Review group has merged an MR which got deployed to production. +- To verify the deployment, we can check the [Code Review group's dashboard](https://dashboards.gitlab.net/d/stage-groups-code_review/stage-groups-group-dashboard-create-code-review?orgId=1). +- Sidekiq Error Rate panel shows an elevated error rate, specifically `UpdateMergeRequestsWorker`. + + ![Debug 1](img/stage_group_dashboards_debug_1.png) + +- If we click on `Kibana: Kibana Sidekiq failed request logs` link in the Extra links session, we can filter for `UpdateMergeRequestsWorker`, and read through the logs. + + ![Debug 2](img/stage_group_dashboards_debug_2.png) + +- [Sentry](https://sentry.gitlab.net/gitlab/gitlabcom/) gives us a way to find the exception where we can filter by transaction type and correlation_id from a Kibana's result item. + + ![Debug 3](img/stage_group_dashboards_debug_3.png) + +- A precise exception, including a stack trace, job arguments, and other information, should now appear. Happy debugging! + +## How to customize the dashboard + +All Grafana dashboards at GitLab are generated from the [Jsonnet files](https://github.com/grafana/grafonnet-lib) stored in [the runbook project](https://gitlab.com/gitlab-com/runbooks/-/tree/master/dashboards). Particularly, the stage group dashboards definitions are stored in [/dashboards/stage-groups](https://gitlab.com/gitlab-com/runbooks/-/tree/master/dashboards/stage-groups) subfolder in the Runbook. By convention, each group has a corresponding jsonnet file. The dashboards are synced with GitLab [stage group data](https://gitlab.com/gitlab-com/www-gitlab-com/-/raw/master/data/stages.yml) every month. Expansion and customization are one of the key principles used when we designed this system. To customize your group's dashboard, you need to edit the corresponding file and follow the [Runbook workflow](https://gitlab.com/gitlab-com/runbooks/-/tree/master/dashboards#dashboard-source). The dashboard is updated after the MR is merged. Looking at an autogenerated file, for example, [`product_planning.dashboard.jsonnet`](https://gitlab.com/gitlab-com/runbooks/-/blob/master/dashboards/stage-groups/product_planning.dashboard.jsonnet): + +```jsonnet +// This file is autogenerated using scripts/update_stage_groups_dashboards.rb +// Please feel free to customize this file. +local stageGroupDashboards = import './stage-group-dashboards.libsonnet'; + +stageGroupDashboards.dashboard('product_planning') +.stageGroupDashboardTrailer() +``` + +We provide basic customization to filter out the components essential to your group's activities. By default, all components `web`, `api`, `git`, and `sidekiq` are available in the dashboard. We can change this to only show `web` and `api`, or only show `sidekiq`: + +```jsonnet +stageGroupDashboards.dashboard('product_planning', components=['web', 'api']).stageGroupDashboardTrailer() +# Or +stageGroupDashboards.dashboard('product_planning', components=['sidekiq']).stageGroupDashboardTrailer() + +``` + +You can also append further information or custom metrics to a dashboard. This is an example that adds some links and a total request rate on the top of the page: + +```jsonnet +local stageGroupDashboards = import './stage-group-dashboards.libsonnet'; +local grafana = import 'github.com/grafana/grafonnet-lib/grafonnet/grafana.libsonnet'; +local basic = import 'grafana/basic.libsonnet'; + +stageGroupDashboards.dashboard('source_code') +.addPanel( + grafana.text.new( + title='Group information', + mode='markdown', + content=||| + Useful link for the Source Code Management group dashboard: + - [Issue list](https://gitlab.com/groups/gitlab-org/-/issues?scope=all&utf8=%E2%9C%93&state=opened&label_name%5B%5D=repository) + - [Epic list](https://gitlab.com/groups/gitlab-org/-/epics?label_name[]=repository) + |||, + ), + gridPos={ x: 0, y: 0, w: 24, h: 4 } +) +.addPanel( + basic.timeseries( + title='Total Request Rate', + yAxisLabel='Requests per Second', + decimals=2, + query=||| + sum ( + rate(gitlab_transaction_duration_seconds_count{ + env='$environment', + environment='$environment', + feature_category=~'source_code_management', + }[$__interval]) + ) + ||| + ), + gridPos={ x: 0, y: 0, w: 24, h: 7 } +) +.stageGroupDashboardTrailer() +``` + +![Stage Group Dashboard Customization](img/stage_group_dashboards_time_customization.png) + +For deeper customization and more complicated metrics, visit the [Grafonnet lib](https://github.com/grafana/grafonnet-lib) project and the [GitLab Prometheus Metrics](../administration/monitoring/prometheus/gitlab_metrics.md#gitlab-prometheus-metrics) documentation. diff --git a/doc/development/telemetry/event_dictionary.md b/doc/development/telemetry/event_dictionary.md index bc230a46441..b3b3b0b4fdd 100644 --- a/doc/development/telemetry/event_dictionary.md +++ b/doc/development/telemetry/event_dictionary.md @@ -1,8 +1,8 @@ --- -redirect_to: '../product_analytics/event_dictionary.md' +redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/' --- -This document was moved to [another location](../product_analytics/event_dictionary.md). +This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/). <!-- This redirect file can be deleted after February 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/telemetry/index.md b/doc/development/telemetry/index.md index 24e83ffc524..b3b3b0b4fdd 100644 --- a/doc/development/telemetry/index.md +++ b/doc/development/telemetry/index.md @@ -1,8 +1,8 @@ --- -redirect_to: '../product_analytics/index.md' +redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/' --- -This document was moved to [another location](../product_analytics/index.md). +This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/). <!-- This redirect file can be deleted after February 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/telemetry/snowplow.md b/doc/development/telemetry/snowplow.md index 7cd385be681..bb056ffddfe 100644 --- a/doc/development/telemetry/snowplow.md +++ b/doc/development/telemetry/snowplow.md @@ -1,8 +1,8 @@ --- -redirect_to: '../product_analytics/snowplow.md' +redirect_to: '../snowplow.md' --- -This document was moved to [another location](../product_analytics/snowplow.md). +This document was moved to [another location](../snowplow.md). <!-- This redirect file can be deleted after February 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/telemetry/usage_ping.md b/doc/development/telemetry/usage_ping.md index c890353fe3b..5fbdb508bb1 100644 --- a/doc/development/telemetry/usage_ping.md +++ b/doc/development/telemetry/usage_ping.md @@ -1,8 +1,8 @@ --- -redirect_to: '../product_analytics/usage_ping.md' +redirect_to: '../usage_ping.md' --- -This document was moved to [another location](../product_analytics/usage_ping.md). +This document was moved to [another location](../usage_ping.md). <!-- This redirect file can be deleted after February 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md index d1b7883451f..ac5f1a47f9b 100644 --- a/doc/development/testing_guide/best_practices.md +++ b/doc/development/testing_guide/best_practices.md @@ -842,6 +842,41 @@ Example: expect(response).to have_gitlab_http_status(:ok) ``` +#### `match_schema` and `match_response_schema` + +The `match_schema` matcher allows validating that the subject matches a +[JSON schema](https://json-schema.org/). The item inside `expect` can be +a JSON string or a JSON-compatible data structure. + +`match_response_schema` is a convenience matcher for using with a +response object. from a [request +spec](testing_levels.md#integration-tests). + +Examples: + +```ruby +# Matches against spec/fixtures/api/schemas/prometheus/additional_metrics_query_result.json +expect(data).to match_schema('prometheus/additional_metrics_query_result') + +# Matches against ee/spec/fixtures/api/schemas/board.json +expect(data).to match_schema('board', dir: 'ee') + +# Matches against a schema made up of Ruby data structures +expect(data).to match_schema(Atlassian::Schemata.build_info) +``` + +#### `be_valid_json` + +`be_valid_json` allows validating that a string parses as JSON and gives +a non-empty result. To combine it with the schema matching above, use +`and`: + +```ruby +expect(json_string).to be_valid_json + +expect(json_string).to be_valid_json.and match_schema(schema) +``` + ### Testing query performance Testing query performance allows us to: diff --git a/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md b/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md index 8a49c333f9f..cd429a74a2a 100644 --- a/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md +++ b/doc/development/testing_guide/end_to_end/running_tests_that_require_special_setup.md @@ -403,3 +403,85 @@ Geo requires an EE license. To visit the Geo sites in your browser, you need a r - You can find the full image address from a pipeline by [following these instructions](https://about.gitlab.com/handbook/engineering/quality/guidelines/tips-and-tricks/#running-gitlab-qa-pipeline-against-a-specific-gitlab-release). You might be prompted to set the `GITLAB_QA_ACCESS_TOKEN` variable if you specify the full image address. - You can increase the wait time for replication by setting `GEO_MAX_FILE_REPLICATION_TIME` and `GEO_MAX_DB_REPLICATION_TIME`. The default is 120 seconds. - To save time during tests, create a Personal Access Token with API access on the Geo primary node, and pass that value in as `GITLAB_QA_ACCESS_TOKEN` and `GITLAB_QA_ADMIN_ACCESS_TOKEN`. + +## LDAP Tests + +Tests that are tagged with `:ldap_tls` and `:ldap_no_tls` meta are orchestrated tests where the sign-in happens via LDAP. + +These tests spin up a Docker container [(osixia/openldap)](https://hub.docker.com/r/osixia/openldap) running an instance of [OpenLDAP](https://www.openldap.org/). +The container uses fixtures [checked into the GitLab-QA repo](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/fixtures/ldap) to create +base data such as users and groups including the admin group. The password for [all users](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/9ffb9ad3be847a9054967d792d6772a74220fb42/fixtures/ldap/2_add_users.ldif) including [the `tanuki` user](https://gitlab.com/gitlab-org/gitlab-qa/-/blob/9ffb9ad3be847a9054967d792d6772a74220fb42/fixtures/ldap/tanuki.ldif) is `password`. + +A GitLab instance is also created in a Docker container based on our [General LDAP setup](../../../administration/auth/ldap/index.md#general-ldap-setup) documentation. + +Tests that are tagged `:ldap_tls` enable TLS on GitLab using the certificate [checked into the GitLab-QA repo](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/tls_certificates/gitlab). + +The certificate was generated with openssl using this command: + +```shell +openssl req -x509 -newkey rsa:4096 -keyout gitlab.test.key -out gitlab.test.crt -days 3650 -nodes -subj "/C=US/ST=CA/L=San Francisco/O=GitLab/OU=Org/CN=gitlab.test" +``` + +The OpenLDAP container also uses its [auto-generated TLS certificates](https://github.com/osixia/docker-openldap#use-auto-generated-certificate). + +### Running LDAP tests with TLS enabled + +To run the LDAP tests on your local with TLS enabled, follow these steps: + +1. Include the following entry in your `/etc/hosts` file: + + `127.0.0.1 gitlab.test` + + You can then run tests against GitLab in a Docker container on `https://gitlab.test`. Please note that the TLS certificate [checked into the GitLab-QA repo](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/tls_certificates/gitlab) is configured for this domain. +1. Run the OpenLDAP container with TLS enabled. Change the path to [`gitlab-qa/fixtures/ldap`](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/fixtures/ldap) directory to your local checkout path: + + ```shell + docker network create test && docker run --name ldap-server --net test --hostname ldap-server.test --volume /path/to/gitlab-qa/fixtures/ldap:/container/service/slapd/assets/config/bootstrap/ldif/custom:Z --env LDAP_TLS_CRT_FILENAME="ldap-server.test.crt" --env LDAP_TLS_KEY_FILENAME="ldap-server.test.key" --env LDAP_TLS_ENFORCE="true" --env LDAP_TLS_VERIFY_CLIENT="never" osixia/openldap:latest --copy-service + ``` + +1. Run the GitLab container with TLS enabled. Change the path to [`gitlab-qa/tls_certificates/gitlab`](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/tls_certificates/gitlab) directory to your local checkout path: + + ```shell + sudo docker run \ + --hostname gitlab.test \ + --net test \ + --publish 443:443 --publish 80:80 --publish 22:22 \ + --name gitlab \ + --volume /path/to/gitlab-qa/tls_certificates/gitlab:/etc/gitlab/ssl \ + --env GITLAB_OMNIBUS_CONFIG="gitlab_rails['ldap_enabled'] = true; gitlab_rails['ldap_servers'] = {\"main\"=>{\"label\"=>\"LDAP\", \"host\"=>\"ldap-server.test\", \"port\"=>636, \"uid\"=>\"uid\", \"bind_dn\"=>\"cn=admin,dc=example,dc=org\", \"password\"=>\"admin\", \"encryption\"=>\"simple_tls\", \"verify_certificates\"=>false, \"base\"=>\"dc=example,dc=org\", \"user_filter\"=>\"\", \"group_base\"=>\"ou=Global Groups,dc=example,dc=org\", \"admin_group\"=>\"AdminGroup\", \"external_groups\"=>\"\", \"sync_ssh_keys\"=>false}}; letsencrypt['enable'] = false; external_url 'https://gitlab.test'; gitlab_rails['ldap_sync_worker_cron'] = '* * * * *'; gitlab_rails['ldap_group_sync_worker_cron'] = '* * * * *'; " \ + gitlab/gitlab-ee:latest + ``` + +1. Run an LDAP test from [`gitlab/qa`](https://gitlab.com/gitlab-org/gitlab/-/tree/d5447ebb5f99d4c72780681ddf4dc25b0738acba/qa) directory: + + ```shell + GITLAB_LDAP_USERNAME="tanuki" GITLAB_LDAP_PASSWORD="password" QA_DEBUG=true CHROME_HEADLESS=false bin/qa Test::Instance::All https://gitlab.test qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb + ``` + +### Running LDAP tests with TLS disabled + +To run the LDAP tests on your local with TLS disabled, follow these steps: + +1. Run OpenLDAP container with TLS disabled. Change the path to [`gitlab-qa/fixtures/ldap`](https://gitlab.com/gitlab-org/gitlab-qa/-/tree/9ffb9ad3be847a9054967d792d6772a74220fb42/fixtures/ldap) directory to your local checkout path: + + ```shell + docker network create test && docker run --net test --publish 389:389 --publish 636:636 --name ldap-server --hostname ldap-server.test --volume /path/to/gitlab-qa/fixtures/ldap:/container/service/slapd/assets/config/bootstrap/ldif/custom:Z --env LDAP_TLS="false" osixia/openldap:latest --copy-service + ``` + +1. Run the GitLab container: + + ```shell + sudo docker run \ + --hostname localhost \ + --net test \ + --publish 443:443 --publish 80:80 --publish 22:22 \ + --name gitlab \ + --env GITLAB_OMNIBUS_CONFIG="gitlab_rails['ldap_enabled'] = true; gitlab_rails['ldap_servers'] = {\"main\"=>{\"label\"=>\"LDAP\", \"host\"=>\"ldap-server.test\", \"port\"=>389, \"uid\"=>\"uid\", \"bind_dn\"=>\"cn=admin,dc=example,dc=org\", \"password\"=>\"admin\", \"encryption\"=>\"plain\", \"verify_certificates\"=>false, \"base\"=>\"dc=example,dc=org\", \"user_filter\"=>\"\", \"group_base\"=>\"ou=Global Groups,dc=example,dc=org\", \"admin_group\"=>\"AdminGroup\", \"external_groups\"=>\"\", \"sync_ssh_keys\"=>false}}; gitlab_rails['ldap_sync_worker_cron'] = '* * * * *'; gitlab_rails['ldap_group_sync_worker_cron'] = '* * * * *'; " \ + gitlab/gitlab-ee:latest + ``` + +1. Run an LDAP test from [`gitlab/qa`](https://gitlab.com/gitlab-org/gitlab/-/tree/d5447ebb5f99d4c72780681ddf4dc25b0738acba/qa) directory: + + ```shell + GITLAB_LDAP_USERNAME="tanuki" GITLAB_LDAP_PASSWORD="password" QA_DEBUG=true CHROME_HEADLESS=false bin/qa Test::Instance::All http://localhost qa/specs/features/browser_ui/1_manage/login/log_into_gitlab_via_ldap_spec.rb + ``` diff --git a/doc/development/testing_guide/frontend_testing.md b/doc/development/testing_guide/frontend_testing.md index d83d58d14dd..94bc80abcdb 100644 --- a/doc/development/testing_guide/frontend_testing.md +++ b/doc/development/testing_guide/frontend_testing.md @@ -89,7 +89,7 @@ If your test exceeds that time, it fails. If you cannot improve the performance of the tests, you can increase the timeout for a specific test using -[`setTestTimeout`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/helpers/timeout.js). +[`setTestTimeout`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/__helpers__/timeout.js). ```javascript import { setTestTimeout } from 'helpers/timeout'; @@ -834,12 +834,50 @@ The `response` variable gets automatically set if the test is marked as `type: : When creating a new fixture, it often makes sense to take a look at the corresponding tests for the endpoint in `(ee/)spec/controllers/` or `(ee/)spec/requests/`. +##### GraphQL query fixtures + +You can create a fixture that represents the result of a GraphQL query using the `get_graphql_query_as_string` +helper method. For example: + +```ruby +# spec/frontend/fixtures/releases.rb + +describe GraphQL::Query, type: :request do + include GraphqlHelpers + + all_releases_query_path = 'releases/queries/all_releases.query.graphql' + fragment_paths = ['releases/queries/release.fragment.graphql'] + + before(:all) do + clean_frontend_fixtures('graphql/releases/') + end + + it "graphql/#{all_releases_query_path}.json" do + query = get_graphql_query_as_string(all_releases_query_path, fragment_paths) + + post_graphql(query, current_user: admin, variables: { fullPath: project.full_path }) + + expect_graphql_errors_to_be_empty + end +end +``` + +This will create a new fixture located at +`tmp/tests/frontend/fixtures-ee/graphql/releases/queries/all_releases.query.graphql.json`. + +Note that you will need to provide the paths to all fragments used by the query. +`get_graphql_query_as_string` reads all of the provided file paths and returns +the result as a single, concatenated string. + +You can import the JSON fixture in a Jest test using the `getJSONFixture` method +[as described below](#use-fixtures). + ### Use fixtures Jest and Karma test suites import fixtures in different ways: - The Karma test suite are served by [jasmine-jquery](https://github.com/velesin/jasmine-jquery). -- Jest use `spec/frontend/helpers/fixtures.js`. +- Jest use `spec/frontend/__helpers__/fixtures.js`. The following are examples of tests that work for both Karma and Jest: @@ -1024,6 +1062,9 @@ See also [Notes on testing Vue components](../fe_guide/vue.md#testing-vue-compon ## Test helpers +Test helpers can be found in [`spec/frontend/__helpers__`](https://gitlab.com/gitlab-org/gitlab/blob/master/spec/frontend/__helpers__). +If you introduce new helpers, please place them in that directory. + ### Vuex Helper: `testAction` We have a helper available to make testing actions easier, as per [official documentation](https://vuex.vuejs.org/guide/testing.html): @@ -1065,7 +1106,7 @@ By doing so, the `wrapper` provides you with the ability to perform a `findByTes which is a shortcut to the more verbose `wrapper.find('[data-testid="my-test-id"]');` ```javascript -import { extendedWrapper } from 'jest/helpers/vue_test_utils_helper'; +import { extendedWrapper } from 'helpers/vue_test_utils_helper'; describe('FooComponent', () => { const wrapper = extendedWrapper(shallowMount({ diff --git a/doc/development/testing_guide/testing_levels.md b/doc/development/testing_guide/testing_levels.md index 14d4ee82f75..abacb9a0c87 100644 --- a/doc/development/testing_guide/testing_levels.md +++ b/doc/development/testing_guide/testing_levels.md @@ -230,7 +230,7 @@ They're useful to test permissions, redirections, what view is rendered etc. | Code path | Tests path | Testing engine | Notes | | --------- | ---------- | -------------- | ----- | -| `app/controllers/` | `spec/controllers/` | RSpec | For N+1 tests, use [request specs](../query_recorder.md#use-request-specs-instead-of-controller-specs) | +| `app/controllers/` | `spec/requests/`, `spec/controllers` | RSpec | Request specs are preferred over legacy controller specs. | | `app/mailers/` | `spec/mailers/` | RSpec | | | `lib/api/` | `spec/requests/api/` | RSpec | | | `app/assets/javascripts/` | `spec/javascripts/`, `spec/frontend/` | Karma & Jest | [More details below](#frontend-integration-tests) | @@ -310,6 +310,8 @@ graph RL ### About controller tests +GitLab is [transitioning from controller specs to request specs](https://gitlab.com/groups/gitlab-org/-/epics/5076). + In an ideal world, controllers should be thin. However, when this is not the case, it's acceptable to write a system or feature test without JavaScript instead of a controller test. Testing a fat controller usually involves a lot of stubbing, such as: @@ -318,7 +320,7 @@ of a controller test. Testing a fat controller usually involves a lot of stubbin controller.instance_variable_set(:@user, user) ``` -and use methods which are deprecated in Rails 5 ([#23768](https://gitlab.com/gitlab-org/gitlab/-/issues/16260)). +and use methods [deprecated in Rails 5](https://gitlab.com/gitlab-org/gitlab/-/issues/16260). ### About Karma diff --git a/doc/development/usage_ping.md b/doc/development/usage_ping.md new file mode 100644 index 00000000000..10c3de2f0a1 --- /dev/null +++ b/doc/development/usage_ping.md @@ -0,0 +1,1151 @@ +--- +stage: Growth +group: Product Intelligence +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Usage Ping Guide + +> - Introduced in GitLab Enterprise Edition 8.10. +> - More statistics were added in GitLab Enterprise Edition 8.12. +> - Moved to GitLab Core in 9.1. +> - More statistics were added in GitLab Ultimate 11.2. + +This guide describes Usage Ping's purpose and how it's implemented. + +For more information about Product Intelligence, see: + +- [Product Intelligence Guide](https://about.gitlab.com/handbook/product/product-intelligence-guide/) +- [Snowplow Guide](snowplow.md) + +More useful links: + +- [Product Intelligence Direction](https://about.gitlab.com/direction/product-intelligence/) +- [Data Analysis Process](https://about.gitlab.com/handbook/business-ops/data-team/#data-analysis-process/) +- [Data for Product Managers](https://about.gitlab.com/handbook/business-ops/data-team/programs/data-for-product-managers/) +- [Data Infrastructure](https://about.gitlab.com/handbook/business-ops/data-team/platform/infrastructure/) + +## What is Usage Ping? + +- GitLab sends a weekly payload containing usage data to GitLab Inc. Usage Ping provides high-level data to help our product, support, and sales teams. It does not send any project names, usernames, or any other specific data. The information from the usage ping is not anonymous, it is linked to the hostname of the instance. Sending usage ping is optional, and any instance can disable analytics. +- The usage data is primarily composed of row counts for different tables in the instance’s database. By comparing these counts month over month (or week over week), we can get a rough sense for how an instance is using the different features within the product. In addition to counts, other facts + that help us classify and understand GitLab installations are collected. +- Usage ping is important to GitLab as we use it to calculate our Stage Monthly Active Users (SMAU) which helps us measure the success of our stages and features. +- While usage ping is enabled, GitLab gathers data from the other instances and can show usage statistics of your instance to your users. + +### Why should we enable Usage Ping? + +- The main purpose of Usage Ping is to build a better GitLab. Data about how GitLab is used is collected to better understand feature/stage adoption and usage, which helps us understand how GitLab is adding value and helps our team better understand the reasons why people use GitLab and with this knowledge we're able to make better product decisions. +- As a benefit of having the usage ping active, GitLab lets you analyze the users’ activities over time of your GitLab installation. +- As a benefit of having the usage ping active, GitLab provides you with The DevOps Report,which gives you an overview of your entire instance’s adoption of Concurrent DevOps from planning to monitoring. +- You get better, more proactive support. (assuming that our TAMs and support organization used the data to deliver more value) +- You get insight and advice into how to get the most value out of your investment in GitLab. Wouldn't you want to know that a number of features or values are not being adopted in your organization? +- You get a report that illustrates how you compare against other similar organizations (anonymized), with specific advice and recommendations on how to improve your DevOps processes. +- Usage Ping is enabled by default. To disable it, see [Disable Usage Ping](#disable-usage-ping). + +### Limitations + +- Usage Ping does not track frontend events things like page views, link clicks, or user sessions, and only focuses on aggregated backend events. +- Because of these limitations we recommend instrumenting your products with Snowplow for more detailed analytics on GitLab.com and use Usage Ping to track aggregated backend events on self-managed. + +## Usage Ping payload + +You can view the exact JSON payload sent to GitLab Inc. in the administration panel. To view the payload: + +1. Navigate to **Admin Area > Settings > Metrics and profiling**. +1. Expand the **Usage statistics** section. +1. Click the **Preview payload** button. + +For an example payload, see [Example Usage Ping payload](#example-usage-ping-payload). + +## Disable Usage Ping + +To disable Usage Ping in the GitLab UI, go to the **Settings** page of your administration panel and uncheck the **Usage Ping** checkbox. + +To disable Usage Ping and prevent it from being configured in the future through the administration panel, Omnibus installs can set the following in [`gitlab.rb`](https://docs.gitlab.com/omnibus/settings/configuration.html#configuration-options): + +```ruby +gitlab_rails['usage_ping_enabled'] = false +``` + +Source installations can set the following in `gitlab.yml`: + +```yaml +production: &base + # ... + gitlab: + # ... + usage_ping_enabled: false +``` + +## Usage Ping request flow + +The following example shows a basic request/response flow between a GitLab instance, the Versions Application, the License Application, Salesforce, the GitLab S3 Bucket, the GitLab Snowflake Data Warehouse, and Sisense: + +```mermaid +sequenceDiagram + participant GitLab Instance + participant Versions Application + participant Licenses Application + participant Salesforce + participant S3 Bucket + participant Snowflake DW + participant Sisense Dashboards + GitLab Instance->>Versions Application: Send Usage Ping + loop Process usage data + Versions Application->>Versions Application: Parse usage data + Versions Application->>Versions Application: Write to database + Versions Application->>Versions Application: Update license ping time + end + loop Process data for Salesforce + Versions Application-xLicenses Application: Request Zuora subscription id + Licenses Application-xVersions Application: Zuora subscription id + Versions Application-xSalesforce: Request Zuora account id by Zuora subscription id + Salesforce-xVersions Application: Zuora account id + Versions Application-xSalesforce: Usage data for the Zuora account + end + Versions Application->>S3 Bucket: Export Versions database + S3 Bucket->>Snowflake DW: Import data + Snowflake DW->>Snowflake DW: Transform data using dbt + Snowflake DW->>Sisense Dashboards: Data available for querying + Versions Application->>GitLab Instance: DevOps Report (Conversational Development Index) +``` + +## How Usage Ping works + +1. The Usage Ping [cron job](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/workers/gitlab_usage_ping_worker.rb#L30) is set in Sidekiq to run weekly. +1. When the cron job runs, it calls [`Gitlab::UsageData.to_json`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L22). +1. `Gitlab::UsageData.to_json` [cascades down](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L22) to ~400+ other counter method calls. +1. The response of all methods calls are [merged together](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data.rb#L14) into a single JSON payload in `Gitlab::UsageData.to_json`. +1. The JSON payload is then [posted to the Versions application]( https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/submit_usage_ping_service.rb#L20) + If a firewall exception is needed, the required URL depends on several things. If + the hostname is `version.gitlab.com`, the protocol is `TCP`, and the port number is `443`, + the required URL is <https://version.gitlab.com/>. + +## Implementing Usage Ping + +Usage Ping consists of two kinds of data, counters and observations. Counters track how often a certain event +happened over time, such as how many CI pipelines have run. They are monotonic and always trend up. +Observations are facts collected from one or more GitLab instances and can carry arbitrary data. There are no +general guidelines around how to collect those, due to the individual nature of that data. + +There are several types of counters which are all found in `usage_data.rb`: + +- **Ordinary Batch Counters:** Simple count of a given ActiveRecord_Relation +- **Distinct Batch Counters:** Distinct count of a given ActiveRecord_Relation in a given column +- **Sum Batch Counters:** Sum the values of a given ActiveRecord_Relation in a given column +- **Alternative Counters:** Used for settings and configurations +- **Redis Counters:** Used for in-memory counts. + +NOTE: +Only use the provided counter methods. Each counter method contains a built in fail safe to isolate each counter to avoid breaking the entire Usage Ping. + +### Why batch counting + +For large tables, PostgreSQL can take a long time to count rows due to MVCC [(Multi-version Concurrency Control)](https://en.wikipedia.org/wiki/Multiversion_concurrency_control). Batch counting is a counting method where a single large query is broken into multiple smaller queries. For example, instead of a single query querying 1,000,000 records, with batch counting, you can execute 100 queries of 10,000 records each. Batch counting is useful for avoiding database timeouts as each batch query is significantly shorter than one single long running query. + +For GitLab.com, there are extremely large tables with 15 second query timeouts, so we use batch counting to avoid encountering timeouts. Here are the sizes of some GitLab.com tables: + +| Table | Row counts in millions | +|------------------------------|------------------------| +| `merge_request_diff_commits` | 2280 | +| `ci_build_trace_sections` | 1764 | +| `merge_request_diff_files` | 1082 | +| `events` | 514 | + +We have several batch counting methods available: + +- `Ordinary Batch Counters` +- `Distinct Batch Counters` +- `Sum Batch Counters` +- `Estimated Batch Counters` + +Batch counting requires indexes on columns to calculate max, min, and range queries. In some cases, +you may need to add a specialized index on the columns involved in a counter. + +### Ordinary Batch Counters + +Handles `ActiveRecord::StatementInvalid` error + +Simple count of a given ActiveRecord_Relation, does a non-distinct batch count, smartly reduces batch_size and handles errors. + +Method: `count(relation, column = nil, batch: true, start: nil, finish: nil)` + +Arguments: + +- `relation` the ActiveRecord_Relation to perform the count +- `column` the column to perform the count on, by default is the primary key +- `batch`: default `true` in order to use batch counting +- `start`: custom start of the batch counting in order to avoid complex min calculations +- `end`: custom end of the batch counting in order to avoid complex min calculations + +Examples: + +```ruby +count(User.active) +count(::Clusters::Cluster.aws_installed.enabled, :cluster_id) +count(::Clusters::Cluster.aws_installed.enabled, :cluster_id, start: ::Clusters::Cluster.minimum(:id), finish: ::Clusters::Cluster.maximum(:id)) +``` + +### Distinct Batch Counters + +Handles `ActiveRecord::StatementInvalid` error + +Distinct count of a given ActiveRecord_Relation on given column, a distinct batch count, smartly reduces batch_size and handles errors. + +Method: `distinct_count(relation, column = nil, batch: true, batch_size: nil, start: nil, finish: nil)` + +Arguments: + +- `relation` the ActiveRecord_Relation to perform the count +- `column` the column to perform the distinct count, by default is the primary key +- `batch`: default `true` in order to use batch counting +- `batch_size`: if none set it uses default value 10000 from `Gitlab::Database::BatchCounter` +- `start`: custom start of the batch counting in order to avoid complex min calculations +- `end`: custom end of the batch counting in order to avoid complex min calculations + +WARNING: +Counting over non-unique columns can lead to performance issues. Take a look at the [iterating tables in batches](iterating_tables_in_batches.md) guide for more details. + +Examples: + +```ruby +distinct_count(::Project, :creator_id) +distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id)) +distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id') +``` + +### Sum Batch Counters + +Handles `ActiveRecord::StatementInvalid` error + +Sum the values of a given ActiveRecord_Relation on given column and handles errors. + +Method: `sum(relation, column, batch_size: nil, start: nil, finish: nil)` + +Arguments: + +- `relation` the ActiveRecord_Relation to perform the operation +- `column` the column to sum on +- `batch_size`: if none set it uses default value 1000 from `Gitlab::Database::BatchCounter` +- `start`: custom start of the batch counting in order to avoid complex min calculations +- `end`: custom end of the batch counting in order to avoid complex min calculations + +Examples: + +```ruby +sum(JiraImportState.finished, :imported_issues_count) +``` + +### Grouping & Batch Operations + +The `count`, `distinct_count`, and `sum` batch counters can accept an `ActiveRecord::Relation` +object, which groups by a specified column. With a grouped relation, the methods do batch counting, +handle errors, and returns a hash table of key-value pairs. + +Examples: + +```ruby +count(Namespace.group(:type)) +# returns => {nil=>179, "Group"=>54} + +distinct_count(Project.group(:visibility_level), :creator_id) +# returns => {0=>1, 10=>1, 20=>11} + +sum(Issue.group(:state_id), :weight)) +# returns => {1=>3542, 2=>6820} +``` + +### Estimated Batch Counters + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48233) in GitLab 13.7. + +Estimated batch counter functionality handles `ActiveRecord::StatementInvalid` errors +when used through the provided `estimate_batch_distinct_count` method. +Errors return a value of `-1`. + +WARNING: +This functionality estimates a distinct count of a specific ActiveRecord_Relation in a given column, +which uses the [HyperLogLog](http://algo.inria.fr/flajolet/Publications/FlFuGaMe07.pdf) algorithm. +As the HyperLogLog algorithm is probabilistic, the **results always include error**. +The highest encountered error rate is 4.9%. + +When correctly used, the `estimate_batch_distinct_count` method enables efficient counting over +columns that contain non-unique values, which can not be assured by other counters. + +Method: [`estimate_batch_distinct_count(relation, column = nil, batch_size: nil, start: nil, finish: nil)`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/utils/usage_data.rb#L63) + +The method includes the following arguments: + +- `relation`: The ActiveRecord_Relation to perform the count. +- `column`: The column to perform the distinct count. The default is the primary key. +- `batch_size`: The default is 10,000, from `Gitlab::Database::PostgresHll::BatchDistinctCounter::DEFAULT_BATCH_SIZE`. +- `start`: The custom start of the batch count, to avoid complex minimum calculations. +- `finish`: The custom end of the batch count in order to avoid complex maximum calculations. + +The method includes the following prerequisites: + +1. The supplied `relation` must include the primary key defined as the numeric column. + For example: `id bigint NOT NULL`. +1. The `estimate_batch_distinct_count` can handle a joined relation. To use its ability to + count non-unique columns, the joined relation **must NOT** have a one-to-many relationship, + such as `has_many :boards`. +1. Both `start` and `finish` arguments should always represent primary key relationship values, + even if the estimated count refers to another column, for example: + + ```ruby + estimate_batch_distinct_count(::Note, :author_id, start: ::Note.minimum(:id), finish: ::Note.maximum(:id)) + ``` + +Examples: + +1. Simple execution of estimated batch counter, with only relation provided, + returned value represents estimated number of unique values in `id` column + (which is the primary key) of `Project` relation: + + ```ruby + estimate_batch_distinct_count(::Project) + ``` + +1. Execution of estimated batch counter, where provided relation has applied + additional filter (`.where(time_period)`), number of unique values estimated + in custom column (`:author_id`), and parameters: `start` and `finish` together + apply boundaries that defines range of provided relation to analyze: + + ```ruby + estimate_batch_distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::Note.minimum(:id), finish: ::Note.maximum(:id)) + ``` + +1. Execution of estimated batch counter with joined relation (`joins(:cluster)`), + for a custom column (`'clusters.user_id'`): + + ```ruby + estimate_batch_distinct_count(::Clusters::Applications::CertManager.where(time_period).available.joins(:cluster), 'clusters.user_id') + ``` + +When instrumenting metric with usage of estimated batch counter please add +`_estimated` suffix to its name, for example: + +```ruby + "counts": { + "ci_builds_estimated": estimate_batch_distinct_count(Ci::Build), + ... +``` + +### Redis Counters + +Handles `::Redis::CommandError` and `Gitlab::UsageDataCounters::BaseCounter::UnknownEvent` +returns -1 when a block is sent or hash with all values -1 when a `counter(Gitlab::UsageDataCounters)` is sent +different behavior due to 2 different implementations of Redis counter + +Method: `redis_usage_data(counter, &block)` + +Arguments: + +- `counter`: a counter from `Gitlab::UsageDataCounters`, that has `fallback_totals` method implemented +- or a `block`: which is evaluated + +#### Ordinary Redis Counters + +Examples of implementation: + +- Using Redis methods [`INCR`](https://redis.io/commands/incr), [`GET`](https://redis.io/commands/get), and [`Gitlab::UsageDataCounters::WikiPageCounter`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/wiki_page_counter.rb) +- Using Redis methods [`HINCRBY`](https://redis.io/commands/hincrby), [`HGETALL`](https://redis.io/commands/hgetall), and [`Gitlab::UsageCounters::PodLogs`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_counters/pod_logs.rb) + +##### UsageData API Tracking + +<!-- There's nearly identical content in `##### Adding new events`. If you fix errors here, you may need to fix the same errors in the other location. --> + +1. Track event using `UsageData` API + + Increment event count using ordinary Redis counter, for given event name. + + Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default. + + API requests are protected by checking for a valid CSRF token. + + In order to be able to increment the values the related feature `usage_data_<event_name>` should be enabled. + + ```plaintext + POST /usage_data/increment_counter + ``` + + | Attribute | Type | Required | Description | + | :-------- | :--- | :------- | :---------- | + | `event` | string | yes | The event name it should be tracked | + + Response + + - `200` if event was tracked + - `400 Bad request` if event parameter is missing + - `401 Unauthorized` if user is not authenticated + - `403 Forbidden` for invalid CSRF token provided + +1. Track events using JavaScript/Vue API helper which calls the API above + + Note that `usage_data_api` and `usage_data_#{event_name}` should be enabled in order to be able to track events + + ```javascript + import api from '~/api'; + + api.trackRedisCounterEvent('my_already_defined_event_name'), + ``` + +#### Redis HLL Counters + +WARNING: +HyperLogLog (HLL) is a probabilistic algorithm and its **results always includes some small error**. According to [Redis documentation](https://redis.io/commands/pfcount), data from +used HLL implementation is "approximated with a standard error of 0.81%". + +With `Gitlab::UsageDataCounters::HLLRedisCounter` we have available data structures used to count unique values. + +Implemented using Redis methods [PFADD](https://redis.io/commands/pfadd) and [PFCOUNT](https://redis.io/commands/pfcount). + +##### Adding new events + +1. Define events in [`known_events`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/). + + Example event: + + ```yaml + - name: i_compliance_credential_inventory + category: compliance + redis_slot: compliance + expiry: 42 # 6 weeks + aggregation: weekly + ``` + + Keys: + + - `name`: unique event name. + + Name format `<prefix>_<redis_slot>_name`. + + Use one of the following prefixes for the event's name: + + - `g_` for group, as an event which is tracked for group. + - `p_` for project, as an event which is tracked for project. + - `i_` for instance, as an event which is tracked for instance. + - `a_` for events encompassing all `g_`, `p_`, `i_`. + - `o_` for other. + + Consider including in the event's name the Redis slot in order to be able to count totals for a specific category. + + Example names: `i_compliance_credential_inventory`, `g_analytics_contribution`. + + - `category`: event category. Used for getting total counts for events in a category, for easier + access to a group of events. + - `redis_slot`: optional Redis slot; default value: event name. Used if needed to calculate totals + for a group of metrics. Ensure keys are in the same slot. For example: + `i_compliance_credential_inventory` with `redis_slot: 'compliance'` builds Redis key + `i_{compliance}_credential_inventory-2020-34`. If `redis_slot` is not defined the Redis key will + be `{i_compliance_credential_inventory}-2020-34`. + - `expiry`: expiry time in days. Default: 29 days for daily aggregation and 6 weeks for weekly + aggregation. + - `aggregation`: may be set to a `:daily` or `:weekly` key. Defines how counting data is stored in Redis. + Aggregation on a `daily` basis does not pull more fine grained data. + - `feature_flag`: optional. For details, see our [GitLab internal Feature flags](feature_flags/) documentation. + +1. Track event in controller using `RedisTracking` module with `track_redis_hll_event(*controller_actions, name:, feature:, feature_default_enabled: false)`. + + Arguments: + + - `controller_actions`: controller actions we want to track. + - `name`: event name. + - `feature`: feature name, all metrics we track should be under feature flag. + - `feature_default_enabled`: feature flag is disabled by default, set to `true` for it to be enabled by default. + + Example usage: + + ```ruby + # controller + class ProjectsController < Projects::ApplicationController + include RedisTracking + + skip_before_action :authenticate_user!, only: :show + track_redis_hll_event :index, :show, name: 'g_compliance_example_feature_visitors', feature: :compliance_example_feature, feature_default_enabled: true + + def index + render html: 'index' + end + + def new + render html: 'new' + end + + def show + render html: 'show' + end + end + ``` + +1. Track event in API using `increment_unique_values(event_name, values)` helper method. + + In order to be able to track the event, Usage Ping must be enabled and the event feature `usage_data_<event_name>` must be enabled. + + Arguments: + + - `event_name`: event name. + - `values`: values counted, one value or array of values. + + Example usage: + + ```ruby + get ':id/registry/repositories' do + repositories = ContainerRepositoriesFinder.new( + user: current_user, subject: user_group + ).execute + + increment_unique_values('i_list_repositories', current_user.id) + + present paginate(repositories), with: Entities::ContainerRegistry::Repository, tags: params[:tags], tags_count: params[:tags_count] + end + ``` + +1. Track event using `track_usage_event(event_name, values) in services and GraphQL + + Increment unique values count using Redis HLL, for given event name. + + Example: + + [Track usage event for incident created in service](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/services/issues/update_service.rb) + + [Track usage event for incident created in GraphQL](https://gitlab.com/gitlab-org/gitlab/-/blob/master/app/graphql/mutations/alert_management/update_alert_status.rb) + + ```ruby + track_usage_event(:incident_management_incident_created, current_user.id) + ``` + +<!-- There's nearly identical content in `##### UsageData API Tracking`. If you find / fix errors here, you may need to fix errors in that section too. --> + +1. Track event using `UsageData` API + + Increment unique users count using Redis HLL, for given event name. + + Tracking events using the `UsageData` API requires the `usage_data_api` feature flag to be enabled, which is enabled by default. + + API requests are protected by checking for a valid CSRF token. + + In order to increment the values, the related feature `usage_data_<event_name>` should be + set to `default_enabled: true`. For more information, see + [Feature flags in development of GitLab](feature_flags/index.md). + + ```plaintext + POST /usage_data/increment_unique_users + ``` + + | Attribute | Type | Required | Description | + | :-------- | :--- | :------- | :---------- | + | `event` | string | yes | The event name it should be tracked | + + Response + + Return 200 if tracking failed for any reason. + + - `200` if event was tracked or any errors + - `400 Bad request` if event parameter is missing + - `401 Unauthorized` if user is not authenticated + - `403 Forbidden` for invalid CSRF token provided + +1. Track events using JavaScript/Vue API helper which calls the API above + + Example usage for an existing event already defined in [known events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/): + + Usage Data API is behind `usage_data_api` feature flag which, as of GitLab 13.7, is + now set to `default_enabled: true`. + + Each event tracked using Usage Data API is behind a feature flag `usage_data_#{event_name}` which should be `default_enabled: true` + + ```javascript + import api from '~/api'; + + api.trackRedisHllUserEvent('my_already_defined_event_name'), + ``` + +1. Track event using base module `Gitlab::UsageDataCounters::HLLRedisCounter.track_event(event_name, values:)`. + + Arguments: + + - `event_name`: event name. + - `values`: One value or array of values we count. For example: user_id, visitor_id, user_ids. + +1. Track event on context level using base module `Gitlab::UsageDataCounters::HLLRedisCounter.track_event_in_context(event_name, values:, context:)`. + + Arguments: + + - `event_name`: event name. + - `values`: values we count. For example: user_id, visitor_id. + - `context`: context value. Allowed values are `default`, `free`, `bronze`, `silver`, `gold`, `starter`, `premium`, `ultimate` + +1. Get event data using `Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names:, start_date:, end_date:, context: '')`. + + Arguments: + + - `event_names`: the list of event names. + - `start_date`: start date of the period for which we want to get event data. + - `end_date`: end date of the period for which we want to get event data. + - `context`: context of the event. Allowed values are `default`, `free`, `bronze`, `silver`, `gold`, `starter`, `premium`, `ultimate`. + +1. Testing tracking and getting unique events + +Trigger events in rails console by using `track_event` method + + ```ruby + Gitlab::UsageDataCounters::HLLRedisCounter.track_event('g_compliance_audit_events', values: 1) + Gitlab::UsageDataCounters::HLLRedisCounter.track_event('g_compliance_audit_events', values: [2, 3]) + ``` + +Next, get the unique events for the current week. + + ```ruby + # Get unique events for metric for current_week + Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'g_compliance_audit_events', + start_date: Date.current.beginning_of_week, end_date: Date.current.end_of_week) + ``` + +##### Recommendations + +We have the following recommendations for [Adding new events](#adding-new-events): + +- Event aggregation: weekly. +- Key expiry time: + - Daily: 29 days. + - Weekly: 42 days. +- When adding new metrics, use a [feature flag](../operations/feature_flags.md) to control the impact. +- For feature flags triggered by another service, set `default_enabled: false`, + - Events can be triggered using the `UsageData` API, which helps when there are > 10 events per change + +##### Enable/Disable Redis HLL tracking + +Events are tracked behind [feature flags](feature_flags/index.md) due to concerns for Redis performance and scalability. + +For a full list of events and corresponding feature flags see, [known_events](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/) files. + +To enable or disable tracking for specific event within <https://gitlab.com> or <https://about.staging.gitlab.com>, run commands such as the following to +[enable or disable the corresponding feature](feature_flags/index.md). + +```shell +/chatops run feature set <feature_name> true +/chatops run feature set <feature_name> false +``` + +##### Known events are added automatically in usage data payload + +All events added in [`known_events/common.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml) are automatically added to usage data generation under the `redis_hll_counters` key. This column is stored in [version-app as a JSON](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L209). +For each event we add metrics for the weekly and monthly time frames, and totals for each where applicable: + +- `#{event_name}_weekly`: Data for 7 days for daily [aggregation](#adding-new-events) events and data for the last complete week for weekly [aggregation](#adding-new-events) events. +- `#{event_name}_monthly`: Data for 28 days for daily [aggregation](#adding-new-events) events and data for the last 4 complete weeks for weekly [aggregation](#adding-new-events) events. + +Redis HLL implementation calculates automatic total metrics, if there are more than one metric for the same category, aggregation and Redis slot. + +- `#{category}_total_unique_counts_weekly`: Total unique counts for events in the same category for the last 7 days or the last complete week, if events are in the same Redis slot and we have more than one metric. +- `#{category}_total_unique_counts_monthly`: Total unique counts for events in same category for the last 28 days or the last 4 complete weeks, if events are in the same Redis slot and we have more than one metric. + +Example of `redis_hll_counters` data: + +```ruby +{:redis_hll_counters=> + {"compliance"=> + {"g_compliance_dashboard_weekly"=>0, + "g_compliance_dashboard_monthly"=>0, + "g_compliance_audit_events_weekly"=>0, + "g_compliance_audit_events_monthly"=>0, + "compliance_total_unique_counts_weekly"=>0, + "compliance_total_unique_counts_monthly"=>0}, + "analytics"=> + {"g_analytics_contribution_weekly"=>0, + "g_analytics_contribution_monthly"=>0, + "g_analytics_insights_weekly"=>0, + "g_analytics_insights_monthly"=>0, + "analytics_total_unique_counts_weekly"=>0, + "analytics_total_unique_counts_monthly"=>0}, + "ide_edit"=> + {"g_edit_by_web_ide_weekly"=>0, + "g_edit_by_web_ide_monthly"=>0, + "g_edit_by_sfe_weekly"=>0, + "g_edit_by_sfe_monthly"=>0, + "ide_edit_total_unique_counts_weekly"=>0, + "ide_edit_total_unique_counts_monthly"=>0}, + "search"=> + {"i_search_total_weekly"=>0, "i_search_total_monthly"=>0, "i_search_advanced_weekly"=>0, "i_search_advanced_monthly"=>0, "i_search_paid_weekly"=>0, "i_search_paid_monthly"=>0, "search_total_unique_counts_weekly"=>0, "search_total_unique_counts_monthly"=>0}, + "source_code"=>{"wiki_action_weekly"=>0, "wiki_action_monthly"=>0} + } +``` + +Example usage: + +```ruby +# Redis Counters +redis_usage_data(Gitlab::UsageDataCounters::WikiPageCounter) +redis_usage_data { ::Gitlab::UsageCounters::PodLogs.usage_totals[:total] } + +# Define events in common.yml https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/known_events/common.yml + +# Tracking events +Gitlab::UsageDataCounters::HLLRedisCounter.track_event('expand_vulnerabilities', values: visitor_id) + +# Get unique events for metric +redis_usage_data { Gitlab::UsageDataCounters::HLLRedisCounter.unique_events(event_names: 'expand_vulnerabilities', start_date: 28.days.ago, end_date: Date.current) } +``` + +### Alternative Counters + +Handles `StandardError` and fallbacks into -1 this way not all measures fail if we encounter one exception. +Mainly used for settings and configurations. + +Method: `alt_usage_data(value = nil, fallback: -1, &block)` + +Arguments: + +- `value`: a simple static value in which case the value is simply returned. +- or a `block`: which is evaluated +- `fallback: -1`: the common value used for any metrics that are failing. + +Example of usage: + +```ruby +alt_usage_data { Gitlab::VERSION } +alt_usage_data { Gitlab::CurrentSettings.uuid } +alt_usage_data(999) +``` + +### Prometheus Queries + +In those cases where operational metrics should be part of Usage Ping, a database or Redis query is unlikely +to provide useful data. Instead, Prometheus might be more appropriate, since most GitLab architectural +components publish metrics to it that can be queried back, aggregated, and included as usage data. + +NOTE: +Prometheus as a data source for Usage Ping is currently only available for single-node Omnibus installations +that are running the [bundled Prometheus](../administration/monitoring/prometheus/index.md) instance. + +To query Prometheus for metrics, a helper method is available to `yield` a fully configured +`PrometheusClient`, given it is available as per the note above: + +```ruby +with_prometheus_client do |client| + response = client.query('<your query>') + ... +end +``` + +Please refer to [the `PrometheusClient` definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/prometheus_client.rb) +for how to use its API to query for data. + +## Developing and testing Usage Ping + +### 1. Naming and placing the metrics + +Add the metric in one of the top level keys + +- `license`: for license related metrics. +- `settings`: for settings related metrics. +- `counts_weekly`: for counters that have data for the most recent 7 days. +- `counts_monthly`: for counters that have data for the most recent 28 days. +- `counts`: for counters that have data for all time. + +### 2. Use your Rails console to manually test counters + +```ruby +# count +Gitlab::UsageData.count(User.active) +Gitlab::UsageData.count(::Clusters::Cluster.aws_installed.enabled, :cluster_id) + +# count distinct +Gitlab::UsageData.distinct_count(::Project, :creator_id) +Gitlab::UsageData.distinct_count(::Note.with_suggestions.where(time_period), :author_id, start: ::User.minimum(:id), finish: ::User.maximum(:id)) +``` + +### 3. Generate the SQL query + +Your Rails console returns the generated SQL queries. + +Example: + +```ruby +pry(main)> Gitlab::UsageData.count(User.active) + (2.6ms) SELECT "features"."key" FROM "features" + (15.3ms) SELECT MIN("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) + (2.4ms) SELECT MAX("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) + (1.9ms) SELECT COUNT("users"."id") FROM "users" WHERE ("users"."state" IN ('active')) AND ("users"."user_type" IS NULL OR "users"."user_type" IN (6, 4)) AND "users"."id" BETWEEN 1 AND 100000 +``` + +### 4. Optimize queries with #database-lab + +Paste the SQL query into `#database-lab` to see how the query performs at scale. + +- `#database-lab` is a Slack channel which uses a production-sized environment to test your queries. +- GitLab.com’s production database has a 15 second timeout. +- Any single query must stay below [1 second execution time](query_performance.md#timing-guidelines-for-queries) with cold caches. +- Add a specialized index on columns involved to reduce the execution time. + +In order to have an understanding of the query's execution we add in the MR description the following information: + +- For counters that have a `time_period` test we add information for both cases: + - `time_period = {}` for all time periods + - `time_period = { created_at: 28.days.ago..Time.current }` for last 28 days period +- Execution plan and query time before and after optimization +- Query generated for the index and time +- Migration output for up and down execution + +We also use `#database-lab` and [explain.depesz.com](https://explain.depesz.com/). For more details, see the [database review guide](database_review.md#preparation-when-adding-or-modifying-queries). + +#### Optimization recommendations and examples + +- Use specialized indexes [example 1](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26871), [example 2](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26445). +- Use defined `start` and `finish`, and simple queries, because these values can be memoized and reused, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37155). +- Avoid joins and write the queries as simply as possible, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36316). +- Set a custom `batch_size` for `distinct_count`, [example](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/38000). + +### 5. Add the metric definition + +When adding, changing, or updating metrics, please update the [Event Dictionary's **Usage Ping** table](https://about.gitlab.com/handbook/product/product-intelligence-guide/#event-dictionary). + +### 6. Add new metric to Versions Application + +Check if new metrics need to be added to the Versions Application. See `usage_data` [schema](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/db/schema.rb#L147) and usage data [parameters accepted](https://gitlab.com/gitlab-services/version-gitlab-com/-/blob/master/app/services/usage_ping.rb). Any metrics added under the `counts` key are saved in the `stats` column. + +### 7. Add the feature label + +Add the `feature` label to the Merge Request for new Usage Ping metrics. These are user-facing changes and are part of expanding the Usage Ping feature. + +### 8. Add a changelog file + +Ensure you comply with the [Changelog entries guide](changelog.md). + +### 9. Ask for a Product Intelligence Review + +On GitLab.com, we have DangerBot setup to monitor Product Intelligence related files and DangerBot recommends a Product Intelligence review. Mention `@gitlab-org/growth/product_intelligence/engineers` in your MR for a review. + +### 10. Verify your metric + +On GitLab.com, the Product Intelligence team regularly monitors Usage Ping. They may alert you that your metrics need further optimization to run quicker and with greater success. You may also use the [Usage Ping QA dashboard](https://app.periscopedata.com/app/gitlab/632033/Usage-Ping-QA) to check how well your metric performs. The dashboard allows filtering by GitLab version, by "Self-managed" & "SaaS" and shows you how many failures have occurred for each metric. Whenever you notice a high failure rate, you may re-optimize your metric. + +### Optional: Test Prometheus based Usage Ping + +If the data submitted includes metrics [queried from Prometheus](#prometheus-queries) that you would like to inspect and verify, +then you need to ensure that a Prometheus server is running locally, and that furthermore the respective GitLab components +are exporting metrics to it. If you do not need to test data coming from Prometheus, no further action +is necessary, since Usage Ping should degrade gracefully in the absence of a running Prometheus server. + +There are currently three kinds of components that may export data to Prometheus, and which are included in Usage Ping: + +- [`node_exporter`](https://github.com/prometheus/node_exporter) - Exports node metrics from the host machine +- [`gitlab-exporter`](https://gitlab.com/gitlab-org/gitlab-exporter) - Exports process metrics from various GitLab components +- various GitLab services such as Sidekiq and the Rails server that export their own metrics + +#### Test with an Omnibus container + +This is the recommended approach to test Prometheus based Usage Ping. + +The easiest way to verify your changes is to build a new Omnibus image from your code branch via CI, then download the image +and run a local container instance: + +1. From your merge request, click on the `qa` stage, then trigger the `package-and-qa` job. This job triggers an Omnibus +build in a [downstream pipeline of the `omnibus-gitlab-mirror` project](https://gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/-/pipelines). +1. In the downstream pipeline, wait for the `gitlab-docker` job to finish. +1. Open the job logs and locate the full container name including the version. It takes the following form: `registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>`. +1. On your local machine, make sure you are logged in to the GitLab Docker registry. You can find the instructions for this in +[Authenticate to the GitLab Container Registry](../user/packages/container_registry/index.md#authenticate-with-the-container-registry). +1. Once logged in, download the new image via `docker pull registry.gitlab.com/gitlab-org/build/omnibus-gitlab-mirror/gitlab-ee:<VERSION>` +1. For more information about working with and running Omnibus GitLab containers in Docker, please refer to [GitLab Docker images](https://docs.gitlab.com/omnibus/docker/README.html) in the Omnibus documentation. + +#### Test with GitLab development toolkits + +This is the less recommended approach, since it comes with a number of difficulties when emulating a real GitLab deployment. + +The [GDK](https://gitlab.com/gitlab-org/gitlab-development-kit) is not currently set up to run a Prometheus server or `node_exporter` alongside other GitLab components. If you would +like to do so, [Monitoring the GDK with Prometheus](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/master/doc/howto/prometheus/index.md#monitoring-the-gdk-with-prometheus) is a good start. + +The [GCK](https://gitlab.com/gitlab-org/gitlab-compose-kit) has limited support for testing Prometheus based Usage Ping. +By default, it already comes with a fully configured Prometheus service that is set up to scrape a number of components, +but with the following limitations: + +- It does not currently run a `gitlab-exporter` instance, so several `process_*` metrics from services such as Gitaly may be missing. +- While it runs a `node_exporter`, `docker-compose` services emulate hosts, meaning that it would normally report itself to not be associated +with any of the other services that are running. That is not how node metrics are reported in a production setup, where `node_exporter` +always runs as a process alongside other GitLab components on any given node. From Usage Ping's perspective none of the node data would therefore +appear to be associated to any of the services running, since they all appear to be running on different hosts. To alleviate this problem, the `node_exporter` in GCK was arbitrarily "assigned" to the `web` service, meaning only for this service `node_*` metrics appears in Usage Ping. + +## Aggregated metrics + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45979) in GitLab 13.6. + +WARNING: +This feature is intended solely for internal GitLab use. + +In order to add data for aggregated metrics into Usage Ping payload you should add corresponding definition in [`aggregated_metrics`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/usage_data_counters/aggregated_metrics/). Each aggregate definition includes following parts: + +- name: unique name under which aggregate metric is added to Usage Ping payload +- operator: operator that defines how aggregated metric data is counted. Available operators are: + - `OR`: removes duplicates and counts all entries that triggered any of listed events + - `AND`: removes duplicates and counts all elements that were observed triggering all of following events +- events: list of events names (from [`known_events/`](#known-events-are-added-automatically-in-usage-data-payload)) to aggregate into metric. All events in this list must have the same `redis_slot` and `aggregation` attributes. +- feature_flag: name of [development feature flag](feature_flags/development.md#development-type) that is checked before +metrics aggregation is performed. Corresponding feature flag should have `default_enabled` attribute set to `false`. +`feature_flag` attribute is **OPTIONAL** and can be omitted, when `feature_flag` is missing no feature flag is checked. + +Example aggregated metric entries: + +```yaml +- name: product_analytics_test_metrics_union + operator: OR + events: ['i_search_total', 'i_search_advanced', 'i_search_paid'] +- name: product_analytics_test_metrics_intersection_with_feautre_flag + operator: AND + events: ['i_search_total', 'i_search_advanced', 'i_search_paid'] + feature_flag: example_aggregated_metric +``` + +Aggregated metrics are added under `aggregated_metrics` key in both `counts_weekly` and `counts_monthly` top level keys in Usage Ping payload. + +```ruby +{ + :counts_monthly => { + :deployments => 1003, + :successful_deployments => 78, + :failed_deployments => 275, + :packages => 155, + :personal_snippets => 2106, + :project_snippets => 407, + :promoted_issues => 719, + :aggregated_metrics => { + :product_analytics_test_metrics_union => 7, + :product_analytics_test_metrics_intersection_with_feautre_flag => 2 + }, + :snippets => 2513 + } +} +``` + +## Example Usage Ping payload + +The following is example content of the Usage Ping payload. + +```json +{ + "uuid": "0000000-0000-0000-0000-000000000000", + "hostname": "example.com", + "version": "12.10.0-pre", + "installation_type": "omnibus-gitlab", + "active_user_count": 999, + "recorded_at": "2020-04-17T07:43:54.162+00:00", + "edition": "EEU", + "license_md5": "00000000000000000000000000000000", + "license_id": null, + "historical_max_users": 999, + "licensee": { + "Name": "ABC, Inc.", + "Email": "email@example.com", + "Company": "ABC, Inc." + }, + "license_user_count": 999, + "license_starts_at": "2020-01-01", + "license_expires_at": "2021-01-01", + "license_plan": "ultimate", + "license_add_ons": { + }, + "license_trial": false, + "counts": { + "assignee_lists": 999, + "boards": 999, + "ci_builds": 999, + ... + }, + "container_registry_enabled": true, + "dependency_proxy_enabled": false, + "gitlab_shared_runners_enabled": true, + "gravatar_enabled": true, + "influxdb_metrics_enabled": true, + "ldap_enabled": false, + "mattermost_enabled": false, + "omniauth_enabled": true, + "prometheus_enabled": false, + "prometheus_metrics_enabled": false, + "reply_by_email_enabled": "incoming+%{key}@incoming.gitlab.com", + "signup_enabled": true, + "web_ide_clientside_preview_enabled": true, + "ingress_modsecurity_enabled": true, + "projects_with_expiration_policy_disabled": 999, + "projects_with_expiration_policy_enabled": 999, + ... + "elasticsearch_enabled": true, + "license_trial_ends_on": null, + "geo_enabled": false, + "git": { + "version": { + "major": 2, + "minor": 26, + "patch": 1 + } + }, + "gitaly": { + "version": "12.10.0-rc1-93-g40980d40", + "servers": 56, + "clusters": 14, + "filesystems": [ + "EXT_2_3_4" + ] + }, + "gitlab_pages": { + "enabled": true, + "version": "1.17.0" + }, + "container_registry_server": { + "vendor": "gitlab", + "version": "2.9.1-gitlab" + }, + "database": { + "adapter": "postgresql", + "version": "9.6.15", + "pg_system_id": 6842684531675334351 + }, + "analytics_unique_visits": { + "g_analytics_contribution": 999, + ... + }, + "usage_activity_by_stage": { + "configure": { + "project_clusters_enabled": 999, + ... + }, + "create": { + "merge_requests": 999, + ... + }, + "manage": { + "events": 999, + ... + }, + "monitor": { + "clusters": 999, + ... + }, + "package": { + "projects_with_packages": 999 + }, + "plan": { + "issues": 999, + ... + }, + "release": { + "deployments": 999, + ... + }, + "secure": { + "user_container_scanning_jobs": 999, + ... + }, + "verify": { + "ci_builds": 999, + ... + } + }, + "usage_activity_by_stage_monthly": { + "configure": { + "project_clusters_enabled": 999, + ... + }, + "create": { + "merge_requests": 999, + ... + }, + "manage": { + "events": 999, + ... + }, + "monitor": { + "clusters": 999, + ... + }, + "package": { + "projects_with_packages": 999 + }, + "plan": { + "issues": 999, + ... + }, + "release": { + "deployments": 999, + ... + }, + "secure": { + "user_container_scanning_jobs": 999, + ... + }, + "verify": { + "ci_builds": 999, + ... + } + }, + "topology": { + "duration_s": 0.013836685999194742, + "application_requests_per_hour": 4224, + "query_apdex_weekly_average": 0.996, + "failures": [], + "nodes": [ + { + "node_memory_total_bytes": 33269903360, + "node_memory_utilization": 0.35, + "node_cpus": 16, + "node_cpu_utilization": 0.2, + "node_uname_info": { + "machine": "x86_64", + "sysname": "Linux", + "release": "4.19.76-linuxkit" + }, + "node_services": [ + { + "name": "web", + "process_count": 16, + "process_memory_pss": 233349888, + "process_memory_rss": 788220927, + "process_memory_uss": 195295487, + "server": "puma" + }, + { + "name": "sidekiq", + "process_count": 1, + "process_memory_pss": 734080000, + "process_memory_rss": 750051328, + "process_memory_uss": 731533312 + }, + ... + ], + ... + }, + ... + ] + } +} +``` + +## Notable changes + +In GitLab 13.5, `pg_system_id` was added to send the [PostgreSQL system identifier](https://www.2ndquadrant.com/en/blog/support-for-postgresqls-system-identifier-in-barman/). + +## Exporting Usage Ping SQL queries and definitions + +Two Rake tasks exist to export Usage Ping definitions. + +- The Rake tasks export the raw SQL queries for `count`, `distinct_count`, `sum`. +- The Rake tasks export the Redis counter class or the line of the Redis block for `redis_usage_data`. +- The Rake tasks calculate the `alt_usage_data` metrics. + +In the home directory of your local GitLab installation run the following Rake tasks for the YAML and JSON versions respectively: + +```shell +# for YAML export +bin/rake gitlab:usage_data:dump_sql_in_yaml + +# for JSON export +bin/rake gitlab:usage_data:dump_sql_in_json + +# You may pipe the output into a file +bin/rake gitlab:usage_data:dump_sql_in_yaml > ~/Desktop/usage-metrics-2020-09-02.yaml +``` + +## Generating and troubleshooting usage ping + +To get a usage ping, or to troubleshoot caching issues on your GitLab instance, please follow [instructions to generate usage ping](../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping). diff --git a/doc/development/usage_ping/metrics_dictionary.md b/doc/development/usage_ping/metrics_dictionary.md new file mode 100644 index 00000000000..bae79689f3b --- /dev/null +++ b/doc/development/usage_ping/metrics_dictionary.md @@ -0,0 +1,73 @@ +--- +stage: Growth +group: Product Intelligence +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Metrics Dictionary Guide + +This guide describes Metrics Dictionary and how it's implemented + +## Metrics Definition and validation + +We are using [JSON Schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/schema.json) to validate the metrics definition. + +This process is meant to ensure consistent and valid metrics defined for Usage Ping. All metrics *must*: + +- Comply with the definied [JSON schema](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/schema.json). +- Have a unique `full_path` . +- Have an owner. + +All metrics are stored in YAML files: + +- [`config/metrics`](https://gitlab.com/gitlab-org/gitlab/-/tree/master/config/metrics) + +Each metric is definied in a separate YAML file consisting of a number of fields: + +| Field | Required | Additional information | +|---------------------|----------|----------------------------------------------------------------| +| `name` | yes | | +| `description` | yes | | +| `value_type` | yes | | +| `status` | yes | | +| `default_generation`| yes | Default generation path of the metric. One full_path value. (1) | +| `full_path` | yes | Full path of the metric for one or multiple generations. Path of the metric in Usage Ping payload. (1) | +| `group` | yes | The [group](https://about.gitlab.com/handbook/product/categories/#devops-stages) that owns the metric. | +| `time_frame` | yes | `string`; may be set to a value like "7d" | +| `data_source` | yes | `string`: may be set to a value like `database` or `redis_hll`. | +| `distribution` | yes | The [distribution](https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/#definitions) where the metric applies. | +| `tier` | yes | The [tier]( https://about.gitlab.com/handbook/marketing/strategic-marketing/tiers/) where the metric applies. | +| `product_category` | no | The [product category](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/categories.yml) for the metric. | +| `stage` | no | The [stage](https://gitlab.com/gitlab-com/www-gitlab-com/blob/master/data/stages.yml) for the metric. | +| `milestone` | no | The milestone when the metric is introduced. | +| `milestone_removed` | no | The milestone when the metric is removed. | +| `introduced_by_url` | no | The URL to the Merge Request that introduced the metric. | + +1. The default generation path is the location of the metric in the Usage Ping payload. + The `full_path` is the list locations for multiple Usage Ping generaations. + +### Example metric definition + +The linked [`uuid`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/config/metrics/license/uuid.yml) +YAML file includes an example metric definition, where the `uuid` metric is the GitLab +instance unique identifier. + +```yaml +name: uuid +description: GitLab instance unique identifier +value_type: string +product_category: collection +stage: growth +status: data_available +default_generation: generation_1 +full_path: + generation_1: uuid + generation_2: license.uuid +milestone: 9.1 +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1521 +group: group::product intelligence +time_frame: none +data_source: database +distribution: [ee, ce] +tier: ['free', 'starter', 'premium', 'ultimate', 'bronze', 'silver', 'gold'] +``` diff --git a/doc/gitlab-basics/create-branch.md b/doc/gitlab-basics/create-branch.md index c971ff7cb52..3697ae34bf9 100644 --- a/doc/gitlab-basics/create-branch.md +++ b/doc/gitlab-basics/create-branch.md @@ -9,7 +9,7 @@ type: howto A branch is an independent line of development in a [project](../user/project/index.md). -When you create a new branch (in your [terminal](start-using-git.md) or with +When you create a new branch (in your [terminal](start-using-git.md#create-a-branch) or with [the web interface](../user/project/repository/web_editor.md#create-a-new-branch)), you are creating a snapshot of a certain branch, usually the main `master` branch, at its current state. From there, you can start to make your own changes without diff --git a/doc/gitlab-basics/create-project.md b/doc/gitlab-basics/create-project.md index 30f467c2b12..c4fe522e6a2 100644 --- a/doc/gitlab-basics/create-project.md +++ b/doc/gitlab-basics/create-project.md @@ -145,6 +145,8 @@ git push --set-upstream git@gitlab.example.com:namespace/nonexistent-project.git git push --set-upstream https://gitlab.example.com/namespace/nonexistent-project.git master ``` +You can pass the flag `--tags` to the `git push` command to export existing repository tags. + Once the push finishes successfully, a remote message indicates the command to set the remote and the URL to the new project: diff --git a/doc/gitlab-basics/start-using-git.md b/doc/gitlab-basics/start-using-git.md index 22b10c32434..7f3e90dc6bd 100644 --- a/doc/gitlab-basics/start-using-git.md +++ b/doc/gitlab-basics/start-using-git.md @@ -167,14 +167,13 @@ original repository if you'd like. ### Download vs clone -To create a copy of a remote repository files on your computer, you can either -**download** or **clone** it. If you download it, you cannot sync it with the +To create a copy of a remote repository's files on your computer, you can either +**download** or **clone**. If you download, you cannot sync it with the remote repository on GitLab. -On the other hand, by cloning a repository, you'll download a copy of its -files to your local computer, but preserve the Git connection with the remote -repository, so that you can work on the its files on your computer and then -upload the changes to GitLab. +Cloning a repository is the same as downloading, except it preserves the Git connection +with the remote repository. This allows you to modify the files locally and +upload the changes to the remote repository on GitLab. ### Pull and push diff --git a/doc/install/README.md b/doc/install/README.md index f0aee9b6927..7ed478439e0 100644 --- a/doc/install/README.md +++ b/doc/install/README.md @@ -17,7 +17,7 @@ troubleshooting), and the cost of hosting. Depending on your platform, select from the following available methods to install GitLab: -- [_Omnibus GitLab_](#installing-gitlab-using-the-omnibus-gitlab-package-recommended): +- [_Omnibus GitLab_](#installing-gitlab-on-linux-using-the-omnibus-gitlab-package-recommended): The official deb/rpm packages that contain a bundle of GitLab and the components it depends on, including PostgreSQL, Redis, and Sidekiq. - [_GitLab Helm chart_](#installing-gitlab-on-kubernetes-via-the-gitlab-helm-charts): @@ -42,16 +42,24 @@ Before you install GitLab, be sure to review the [system requirements](requireme The system requirements include details about the minimum hardware, software, database, and additional requirements to support GitLab. -## Installing GitLab using the Omnibus GitLab package (recommended) +## Installing GitLab on Linux using the Omnibus GitLab package (recommended) The Omnibus GitLab package uses our official deb/rpm repositories, and is recommended for most users. -If you need additional flexibility and resilience, we recommend deploying +If you need additional scale or resilience, we recommend deploying GitLab as described in our [reference architecture documentation](../administration/reference_architectures/index.md). [**> Install GitLab using the Omnibus GitLab package.**](https://about.gitlab.com/install/) +### GitLab Environment Toolkit (alpha) + +The [GitLab Environment Toolkit](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit) provides a set of automation tools to easily deploy a [reference architecture](../administration/reference_architectures/index.md) on most major cloud providers. + +It is currently in alpha, and is not recommended for production use. + +[**> Install a GitLab reference architecture using the GitLab Environment Toolkit.**](https://gitlab.com/gitlab-org/quality/gitlab-environment-toolkit#documentation) + ## Installing GitLab on Kubernetes via the GitLab Helm charts When installing GitLab on Kubernetes, there are some trade-offs that you @@ -79,9 +87,10 @@ package. ## Installing GitLab from source -If the Omnibus GitLab package is not available in your distribution, you can -install GitLab from source: Useful for unsupported systems like \*BSD. For an -overview of the directory structure, read the [structure documentation](installation.md#gitlab-directory-structure). +If the Omnibus GitLab package isn't available for your distribution, you can +install GitLab from source. This can be useful with unsupported systems, like +\*BSD. For an overview of the directory structure, see the +[structure documentation](installation.md#gitlab-directory-structure). [**> Install GitLab from source.**](installation.md) @@ -94,8 +103,7 @@ the above methods, provided the cloud provider supports it. - [Install GitLab on Google Cloud Platform](google_cloud_platform/index.md): Install Omnibus GitLab on a VM in GCP. - [Install GitLab on Azure](azure/index.md): Install Omnibus GitLab from Azure Marketplace. - [Install GitLab on OpenShift](https://docs.gitlab.com/charts/installation/cloud/openshift.html): Install GitLab on OpenShift by using the GitLab Helm charts. -- [Install GitLab on DC/OS](https://d2iq.com/blog/gitlab-dcos): Install GitLab on Mesosphere DC/OS via the [GitLab-Mesosphere integration](https://about.gitlab.com/blog/2016/09/16/announcing-gitlab-and-mesosphere/). -- [Install GitLab on DigitalOcean](https://about.gitlab.com/blog/2016/04/27/getting-started-with-gitlab-and-digitalocean/): Install Omnibus GitLab on DigitalOcean. +- [Install GitLab on DigitalOcean](https://www.digitalocean.com/community/tutorials/how-to-install-and-configure-gitlab-on-ubuntu-18-04): Install Omnibus GitLab on DigitalOcean. - _Testing only!_ [DigitalOcean and Docker Machine](digitaloceandocker.md): Quickly test any version of GitLab on DigitalOcean using Docker Machine. diff --git a/doc/install/aws/index.md b/doc/install/aws/index.md index 28f04c1a7a7..8a8e3a053b6 100644 --- a/doc/install/aws/index.md +++ b/doc/install/aws/index.md @@ -8,7 +8,7 @@ type: howto # Installing GitLab on Amazon Web Services (AWS) This page offers a walkthrough of a common configuration -for GitLab on AWS. You should customize it to accommodate your needs. +for GitLab on AWS using the official GitLab Linux package. You should customize it to accommodate your needs. NOTE: For organizations with 1,000 users or less, the recommended AWS installation method is to launch an EC2 single box [Omnibus Installation](https://about.gitlab.com/install/) and implement a snapshot strategy for backing up the data. See the [1,000 user reference architecture](../../administration/reference_architectures/1k_users.md) for more. @@ -44,22 +44,21 @@ Below is a diagram of the recommended architecture. ## AWS costs -Here's a list of the AWS services we will use, with links to pricing information: - -- **EC2**: GitLab will deployed on shared hardware which means - [on-demand pricing](https://aws.amazon.com/ec2/pricing/on-demand/) - will apply. If you want to run it on a dedicated or reserved instance, - consult the [EC2 pricing page](https://aws.amazon.com/ec2/pricing/) for more - information on the cost. -- **S3**: We will use S3 to store backups, artifacts, LFS objects, etc. See the - [Amazon S3 pricing](https://aws.amazon.com/s3/pricing/). -- **ELB**: A Classic Load Balancer will be used to route requests to the - GitLab instances. See the [Amazon ELB pricing](https://aws.amazon.com/elasticloadbalancing/pricing/). -- **RDS**: An Amazon Relational Database Service using PostgreSQL will be used. See the - [Amazon RDS pricing](https://aws.amazon.com/rds/postgresql/pricing/). -- **ElastiCache**: An in-memory cache environment will be used to provide a - Redis configuration. See the - [Amazon ElastiCache pricing](https://aws.amazon.com/elasticache/pricing/). +GitLab uses the following AWS services, with links to pricing information: + +- **EC2**: GitLab is deployed on shared hardware, for which + [on-demand pricing](https://aws.amazon.com/ec2/pricing/on-demand/) applies. + If you want to run GitLab on a dedicated or reserved instance, see the + [EC2 pricing page](https://aws.amazon.com/ec2/pricing/) for information about + its cost. +- **S3**: GitLab uses S3 ([pricing page](https://aws.amazon.com/s3/pricing/)) to + store backups, artifacts, and LFS objects. +- **ELB**: A Classic Load Balancer ([pricing page](https://aws.amazon.com/elasticloadbalancing/pricing/)), + used to route requests to the GitLab instances. +- **RDS**: An Amazon Relational Database Service using PostgreSQL + ([pricing page](https://aws.amazon.com/rds/postgresql/pricing/)). +- **ElastiCache**: An in-memory cache environment ([pricing page](https://aws.amazon.com/elasticache/pricing/)), + used to provide a Redis configuration. ## Create an IAM EC2 instance role and profile diff --git a/doc/install/google_cloud_platform/index.md b/doc/install/google_cloud_platform/index.md index 22f32d69c02..d579e214efc 100644 --- a/doc/install/google_cloud_platform/index.md +++ b/doc/install/google_cloud_platform/index.md @@ -8,7 +8,7 @@ type: howto # Installing GitLab on Google Cloud Platform -This guide will help you install GitLab on a [Google Cloud Platform (GCP)](https://cloud.google.com/) instance. +This guide will help you install GitLab on a [Google Cloud Platform (GCP)](https://cloud.google.com/) using the official GitLab Linux package. You should customize it to accommodate your needs. NOTE: Google provides a whitepaper for [deploying production-ready GitLab on diff --git a/doc/install/installation.md b/doc/install/installation.md index 983c7ed577f..80f3f6ab092 100644 --- a/doc/install/installation.md +++ b/doc/install/installation.md @@ -271,10 +271,22 @@ sudo adduser --disabled-login --gecos 'GitLab' git NOTE: In GitLab 12.1 and later, only PostgreSQL is supported. In GitLab 13.0 and later, we [require PostgreSQL 11+](requirements.md#postgresql-requirements). -1. Install the database packages: +1. Install the database packages. + + For Ubuntu 20.04 and later: + + ```shell + sudo apt install -y postgresql postgresql-client libpq-dev postgresql-contrib + ``` + + For Ubuntu 18.04 and earlier, the available PostgreSQL doesn't meet the minimum + version requirement. You need to add PostgreSQL's repository: ```shell - sudo apt-get install -y postgresql postgresql-client libpq-dev postgresql-contrib + wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - + RELEASE=$(lsb_release -cs) echo "deb http://apt.postgresql.org/pub/repos/apt/ ${RELEASE}"-pgdg main | sudo tee /etc/apt/sources.list.d/pgdg.list + sudo apt update + sudo apt -y install postgresql-11 postgresql-client-11 libpq-dev ``` 1. Verify the PostgreSQL version you have is supported by the version of GitLab you're @@ -426,7 +438,7 @@ Clone Enterprise Edition: ```shell # Clone GitLab repository -sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab.git -b <X-Y-stable> gitlab +sudo -u git -H git clone https://gitlab.com/gitlab-org/gitlab.git -b <X-Y-stable-ee> gitlab ``` Make sure to replace `<X-Y-stable>` with the stable branch that matches the @@ -1041,3 +1053,34 @@ On RedHat/CentOS: ```shell sudo yum groupinstall 'Development Tools' ``` + +### Error compiling GitLab assets + +While compiling assets, you may receive the following error message: + +```plaintext +Killed +error Command failed with exit code 137. +``` + +This can occur when Yarn kills a container that runs out of memory. To fix this: + +1. Increase your system's memory to at least 8 GB. + +1. Run this command to clean the assets: + + ```shell + sudo -u git -H bundle exec rake gitlab:assets:clean RAILS_ENV=production NODE_ENV=production + ``` + +1. Run the `yarn` command again to resolve any conflicts: + + ```shell + sudo -u git -H yarn install --production --pure-lockfile + ``` + +1. Recompile the assets: + + ```shell + sudo -u git -H bundle exec rake gitlab:assets:compile RAILS_ENV=production NODE_ENV=production + ``` diff --git a/doc/install/requirements.md b/doc/install/requirements.md index cced6d0a3f6..69983edc383 100644 --- a/doc/install/requirements.md +++ b/doc/install/requirements.md @@ -16,7 +16,7 @@ as the hardware requirements that are needed to install and use GitLab. - Ubuntu (16.04/18.04/20.04) - Debian (9/10) -- CentOS (6/7/8) +- CentOS (7/8) - openSUSE (Leap 15.1/Enterprise Server 12.2) - Red Hat Enterprise Linux (please use the CentOS packages and instructions) - Scientific Linux (please use the CentOS packages and instructions) @@ -35,6 +35,9 @@ For the installation options, see [the main installation page](README.md). Installation of GitLab on these operating systems is possible, but not supported. Please see the [installation from source guide](installation.md) and the [installation guides](https://about.gitlab.com/install/) for more information. +Please see [OS versions that are no longer supported](https://docs.gitlab.com/omnibus/package-information/deprecated_os.html) for Omnibus installs page +for a list of supported and unsupported OS versions as well as the last support GitLab version for that OS. + ### Microsoft Windows GitLab is developed for Linux-based operating systems. @@ -163,11 +166,11 @@ Support for [PostgreSQL 9.6 and 10 has been removed in GitLab 13.0](https://abou #### Additional requirements for GitLab Geo -If you're using [GitLab Geo](../administration/geo/index.md): - -- We strongly recommend running Omnibus-managed instances as they are actively - developed and tested. We aim to be compatible with most external (not managed - by Omnibus) databases (for example, [AWS Relational Database Service (RDS)](https://aws.amazon.com/rds/)) but we don't guarantee compatibility. +If you're using [GitLab Geo](../administration/geo/index.md), we strongly +recommend running Omnibus GitLab-managed instances, as we actively develop and +test based on those. We try to be compatible with most external (not managed by +Omnibus GitLab) databases (for example, [AWS Relational Database Service (RDS)](https://aws.amazon.com/rds/)), +but we can't guarantee compatibility. ## Puma settings diff --git a/doc/integration/bitbucket.md b/doc/integration/bitbucket.md index 81cbc42cf45..4bc9d39ae3f 100644 --- a/doc/integration/bitbucket.md +++ b/doc/integration/bitbucket.md @@ -104,14 +104,13 @@ you to use. url: 'https://bitbucket.org/' } ``` - --- - Where `BITBUCKET_APP_KEY` is the Key and `BITBUCKET_APP_SECRET` the Secret from the Bitbucket application page. 1. Save the configuration file. -1. For the changes to take effect, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) if you installed via - Omnibus GitLab, or [restart](../administration/restart_gitlab.md#installations-from-source) if installed from source. +1. For the changes to take effect, [reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) + if you installed using Omnibus GitLab, or [restart](../administration/restart_gitlab.md#installations-from-source) + if you installed from source. On the sign-in page there should now be a Bitbucket icon below the regular sign-in form. Click the icon to begin the authentication process. Bitbucket asks diff --git a/doc/integration/elasticsearch.md b/doc/integration/elasticsearch.md index 52275649a67..b1fc2573bb0 100644 --- a/doc/integration/elasticsearch.md +++ b/doc/integration/elasticsearch.md @@ -175,7 +175,7 @@ instances](#indexing-large-instances) below. To enable Advanced Search, you need to have admin access to GitLab: -1. Navigate to **Admin Area** (wrench icon), then **Settings > General** +1. Navigate to **Admin Area**, then **Settings > General** and expand the **Advanced Search** section. NOTE: @@ -205,6 +205,12 @@ To enable Advanced Search, you need to have admin access to GitLab: **Admin Area > Settings > General > Advanced Search** and click **Save changes**. +NOTE: +When your Elasticsearch cluster is down while Elasticsearch is enabled, +you might have problems updating documents such as issues because your +instance queues a job to index the change, but cannot find a valid +Elasticsearch cluster. + ### Advanced Search configuration The following Elasticsearch settings are available: @@ -259,7 +265,7 @@ You can improve the language support for Chinese and Japanese languages by utili To enable language(s) support: 1. Install the desired plugin(s), please refer to [Elasticsearch documentation](https://www.elastic.co/guide/en/elasticsearch/plugins/7.9/installation.html) for plugins installation instructions. The plugin(s) must be installed on every node in the cluster, and each node must be restarted after installation. For a list of plugins, see the table later in this section. -1. Navigate to the **Admin Area** (wrench icon), then **Settings > General**.. +1. Navigate to the **Admin Area**, then **Settings > General**.. 1. Expand the **Advanced Search** section and locate **Custom analyzers: language support**. 1. Enable plugin(s) support for **Indexing**. 1. Click **Save changes** for the changes to take effect. @@ -279,11 +285,11 @@ For guidance on what to install, see the following Elasticsearch language plugin To disable the Elasticsearch integration: -1. Navigate to the **Admin Area** (wrench icon), then **Settings > General**. +1. Navigate to the **Admin Area**, then **Settings > General**. 1. Expand the **Advanced Search** section and uncheck **Elasticsearch indexing** and **Search with Elasticsearch enabled**. 1. Click **Save changes** for the changes to take effect. -1. (Optional) Delete the existing index: +1. (Optional) Delete the existing indexes: ```shell # Omnibus installations @@ -311,10 +317,11 @@ used by the GitLab Advanced Search integration. In the **Admin Area > Settings > General > Advanced Search** section, select the **Pause Elasticsearch Indexing** setting, and then save your change. - With this, all updates that should happen on your Elasticsearch index will be buffered and caught up once unpaused. +The indexing will also be automatically paused when the [**Trigger cluster reindexing**](#trigger-the-reindex-via-the-advanced-search-administration) button is used, and unpaused when the reindexing completes or aborts. + ### Setup NOTE: @@ -346,7 +353,8 @@ To reclaim the `gitlab-production` index name, you need to first create a `secon To create a secondary index, run the following Rake task. The `SKIP_ALIAS` environment variable will disable the automatic creation of the Elasticsearch -alias, which would conflict with the existing index under `$PRIMARY_INDEX`: +alias, which would conflict with the existing index under `$PRIMARY_INDEX`, and will +not create a separate Issue index: ```shell # Omnibus installation @@ -506,6 +514,15 @@ This should return something similar to: In order to debug issues with the migrations you can check the [`elasticsearch.log` file](../administration/logs.md#elasticsearchlog). +### Retry a halted migration + +Some migrations are built with a retry limit. If the migration cannot finish within the retry limit, +it will be halted and a notification will be displayed in the Advanced Search integration settings. +It is recommended to check the [`elasticsearch.log` file](../administration/logs.md#elasticsearchlog) to +debug why the migration was halted and make any changes before retrying the migration. Once you believe you've +fixed the cause of the failure, click "Retry migration", and the migration will be scheduled to be retried +in the background. + ## GitLab Advanced Search Rake tasks Rake tasks are available to: @@ -522,8 +539,8 @@ The following are some available Rake tasks: | [`sudo gitlab-rake gitlab:elastic:index_projects`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Iterates over all projects and queues Sidekiq jobs to index them in the background. | | [`sudo gitlab-rake gitlab:elastic:index_projects_status`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Determines the overall status of the indexing. It is done by counting the total number of indexed projects, dividing by a count of the total number of projects, then multiplying by 100. | | [`sudo gitlab-rake gitlab:elastic:clear_index_status`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Deletes all instances of IndexStatus for all projects. Note that this command will result in a complete wipe of the index, and it should be used with caution. | -| [`sudo gitlab-rake gitlab:elastic:create_empty_index[<TARGET_NAME>]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Generates an empty index and assigns an alias for it on the Elasticsearch side only if it doesn't already exist. | -| [`sudo gitlab-rake gitlab:elastic:delete_index[<TARGET_NAME>]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Removes the GitLab index and alias (if exists) on the Elasticsearch instance. | +| [`sudo gitlab-rake gitlab:elastic:create_empty_index[<TARGET_NAME>]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Generates empty indexes (the default index and a separate issues index) and assigns an alias for each on the Elasticsearch side only if it doesn't already exist. | +| [`sudo gitlab-rake gitlab:elastic:delete_index[<TARGET_NAME>]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Removes the GitLab indexes and aliases (if they exist) on the Elasticsearch instance. | | [`sudo gitlab-rake gitlab:elastic:recreate_index[<TARGET_NAME>]`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Wrapper task for `gitlab:elastic:delete_index[<TARGET_NAME>]` and `gitlab:elastic:create_empty_index[<TARGET_NAME>]`. | | [`sudo gitlab-rake gitlab:elastic:index_snippets`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Performs an Elasticsearch import that indexes the snippets data. | | [`sudo gitlab-rake gitlab:elastic:projects_not_indexed`](https://gitlab.com/gitlab-org/gitlab/blob/master/ee/lib/tasks/gitlab/elastic.rake) | Displays which projects are not indexed. | @@ -979,3 +996,11 @@ results and assuming that basic search is supported in that scope. This "basic search" will behave as though you don't have Advanced Search enabled at all for your instance and search using other data sources (ie. PostgreSQL data and Git data). + +### Data recovery: Elasticsearch is a secondary data store only + +The use of Elasticsearch in GitLab is only ever as a secondary data store. +This means that all of the data stored in Elasticsearch can always be derived +again from other data sources, specifically PostgreSQL and Gitaly. Therefore, if +the Elasticsearch data store is ever corrupted for whatever reason, you can +simply reindex everything from scratch. diff --git a/doc/integration/github.md b/doc/integration/github.md index c65027e3585..858614a0571 100644 --- a/doc/integration/github.md +++ b/doc/integration/github.md @@ -12,7 +12,7 @@ with your GitHub account. ## Enabling GitHub OAuth -To enable the GitHub OmniAuth provider, you need an OAuth 2 Client ID and Client Secret from GitHub. To get these credentials, sign into GitHub and follow their procedure for [Creating an OAuth App](https://developer.github.com/apps/building-oauth-apps/creating-an-oauth-app/). +To enable the GitHub OmniAuth provider, you need an OAuth 2 Client ID and Client Secret from GitHub. To get these credentials, sign into GitHub and follow their procedure for [Creating an OAuth App](https://docs.github.com/apps/building-oauth-apps/creating-an-oauth-app/). When you create an OAuth 2 app in GitHub, you need the following information: diff --git a/doc/integration/gitlab.md b/doc/integration/gitlab.md index 37c91aedb15..3bd3099e390 100644 --- a/doc/integration/gitlab.md +++ b/doc/integration/gitlab.md @@ -75,15 +75,20 @@ GitLab.com generates an application ID and secret key for you to use. args: { scope: 'api' } } ``` -1. Change 'YOUR_APP_ID' to the Application ID from the GitLab.com application page. +1. Change `'YOUR_APP_ID'` to the Application ID from the GitLab.com application page. -1. Change 'YOUR_APP_SECRET' to the secret from the GitLab.com application page. +1. Change `'YOUR_APP_SECRET'` to the secret from the GitLab.com application page. 1. Save the configuration file. -1. [Reconfigure](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure) or [restart GitLab](../administration/restart_gitlab.md#installations-from-source) for the changes to take effect if you - installed GitLab via Omnibus or from source respectively. +1. Based on how GitLab was installed, implement these changes by using + the appropriate method: -On the sign in page there should now be a GitLab.com icon below the regular sign in form. -Click the icon to begin the authentication process. GitLab.com asks the user to sign in and authorize the GitLab application. -If everything goes well the user is returned to your GitLab instance and is signed in. + - Omnibus GitLab: [Reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure). + - Source: [Restart GitLab](../administration/restart_gitlab.md#installations-from-source). + +On the sign-in page, there should now be a GitLab.com icon following the +regular sign-in form. Select the icon to begin the authentication process. +GitLab.com asks the user to sign in and authorize the GitLab application. If +everything goes well, the user is returned to your GitLab instance and is +signed in. diff --git a/doc/integration/gitpod.md b/doc/integration/gitpod.md index 04274c1c015..05f129e6049 100644 --- a/doc/integration/gitpod.md +++ b/doc/integration/gitpod.md @@ -8,14 +8,7 @@ info: "To determine the technical writer assigned to the Stage/Group associated # Gitpod Integration > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/228893) in GitLab 13.4. -> - It was [deployed behind a feature flag](#enable-or-disable-the-gitpod-integration), disabled by default. -> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/258206) in GitLab 13.5. -> - It's enabled on GitLab.com. -> - It's recommended for production use. -> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#configure-your-gitlab-instance-with-gitpod). **(CORE ONLY)** - -WARNING: -This feature might not be available to you. Check the **version history** note above for details. +> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/258206) in GitLab 13.8 With [Gitpod](https://gitpod.io/) you can describe your dev environment as code to get fully set up, compiled, and tested dev environments for any GitLab project. The dev environments are not only @@ -48,28 +41,14 @@ can follow the same steps once the integration has been enabled and configured b ## Configure your GitLab instance with Gitpod **(CORE ONLY)** -If you are new to Gitpod, head over to the [Gitpod documentation](https://www.gitpod.io/docs/self-hosted/latest/self-hosted/) -and get your instance up and running. +The integration of Gitpod with GitLab is enabled on GitLab.com and available to all users. +For GitLab self-managed instances, a GitLab administrator needs to enable it through the admin settings. + +First, you (GitLab admin) need to set up a Gitpod instance to integrate with GitLab. +Head over to the [Gitpod documentation](https://www.gitpod.io/docs/self-hosted/latest/self-hosted/) to +get your instance up and running. Once done: 1. In GitLab, go to **Admin Area > Settings > General**. 1. Expand the **Gitpod** configuration section. 1. Check **Enable Gitpod**. 1. Add your Gitpod instance URL (for example, `https://gitpod.example.com`). - -## Enable or disable the Gitpod integration **(CORE ONLY)** - -The Gitpod integration is deployed behind a feature flag that is **enabled by default**. -[GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md) -can enable or disable it. - -To disable it: - -```ruby -Feature.disable(:gitpod) -``` - -To enable it: - -```ruby -Feature.enable(:gitpod) -``` diff --git a/doc/integration/jira_development_panel.md b/doc/integration/jira_development_panel.md index 7488df3580e..1c0b2bdc85e 100644 --- a/doc/integration/jira_development_panel.md +++ b/doc/integration/jira_development_panel.md @@ -211,7 +211,8 @@ The requested scope is invalid, unknown, or malformed. Potential resolutions: -- Verify the URL includes `scope=api` on the end of the URL. +- Verify the URL shown in the browser after being redirected from Jira in step 5 of [Jira DVCS Connector Setp](#jira-dvcs-connector-setup) includes `scope=api` within the query string. +- If `scope=api` is missing from the URL, return to [GitLab account configuration](#gitlab-account-configuration-for-dvcs) and ensure the application you created in step 1 has the `api` box checked under scopes. ##### Jira error adding account and no repositories listed @@ -272,7 +273,13 @@ The GitLab user only needs access when adding a new namespace. For syncing with ![Configure namespace on GitLab Jira App](img/jira_dev_panel_setup_com_3.png) -After a namespace is added, all future commits, branches, and merge requests of all projects under that namespace are synced to Jira. Past data cannot be synced at the moment. +After a namespace is added: + +- All future commits, branches, and merge requests of all projects under that namespace + are synced to Jira. +- From GitLab 13.8, past merge request data is synced to Jira. + +Support for syncing past branch and commit data [is planned](https://gitlab.com/gitlab-org/gitlab/-/issues/263240). For more information, see [Usage](#usage). diff --git a/doc/integration/vault.md b/doc/integration/vault.md index 7f81fd3a7da..3c49cd47509 100644 --- a/doc/integration/vault.md +++ b/doc/integration/vault.md @@ -13,12 +13,12 @@ type: reference, howto It allows you to store and manage sensitive information such as secret environment variables, encryption keys, and authentication tokens. Vault offers Identity-based Access, which means Vault users can authenticate through several of their preferred cloud providers. -In this document, we'll explain how Vault users can authenticate themselves through GitLab by utilizing our OpenID authentication feature. +This document explains how Vault users can authenticate themselves through GitLab by utilizing our OpenID authentication feature. The following assumes you already have Vault installed and running. 1. **Get the OpenID Connect client ID and secret from GitLab:** - First you'll need to create a GitLab application to obtain an application ID and secret for authenticating into Vault. To do this, sign in to GitLab and follow these steps: + First you must create a GitLab application to obtain an application ID and secret for authenticating into Vault. To do this, sign in to GitLab and follow these steps: 1. On GitLab, click your avatar on the top-right corner, and select your user **Settings > Applications**. 1. Fill out the application **Name** and [**Redirect URI**](https://www.vaultproject.io/docs/auth/jwt#redirect-uris), @@ -71,7 +71,7 @@ The following assumes you already have Vault installed and running. Now that Vault has a GitLab application ID and secret, it needs to know the [**Redirect URIs**](https://www.vaultproject.io/docs/auth/jwt#redirect-uris) and scopes given to GitLab during the application creation process. The redirect URIs need to match where your Vault instance is running. The `oidc_scopes` field needs to include the `openid`. Similarly to the previous step, replace `your_application_id` with the generated application ID from GitLab: - This configuration is saved under the name of the role you are creating. In this case, we are creating a `demo` role. Later, we'll show how you can access this role through the Vault CLI. + This configuration is saved under the name of the role you are creating. In this case, we are creating a `demo` role. Later, we show how you can access this role through the Vault CLI. ```shell vault write auth/oidc/role/demo \ @@ -88,11 +88,11 @@ The following assumes you already have Vault installed and running. 1. Go to your Vault UI (example: [http://127.0.0.1:8200/ui/vault/auth?with=oidc](http://127.0.0.1:8200/ui/vault/auth?with=oidc)). 1. If the `OIDC` method is not currently selected, open the dropdown and select it. - 1. Click the **Sign in With GitLab** button, which will open a modal window: + 1. Click the **Sign in With GitLab** button, which opens a modal window: ![Sign into Vault with GitLab](img/sign_into_vault_with_gitlab_v12_6.png) - 1. Click **Authorize** on the modal to allow Vault to sign in through GitLab. This will redirect you back to your Vault UI as a signed-in user. + 1. Click **Authorize** on the modal to allow Vault to sign in through GitLab. This redirects you back to your Vault UI as a signed-in user. ![Authorize Vault to connect with GitLab](img/authorize_vault_with_gitlab_v12_6.png) @@ -116,12 +116,12 @@ The following assumes you already have Vault installed and running. another port number that matches the port given to GitLab when listing [Redirect URIs](https://www.vaultproject.io/docs/auth/jwt#redirect-uris). - After running the command, it will present a link in the terminal. - Click the link in the terminal and a tab will open in the browser confirming you're signed into Vault via OIDC: + After running the command, it presents a link in the terminal. + Click the link in the terminal and a browser tab opens that confirms you're signed into Vault via OIDC: ![Signed into Vault via OIDC](img/signed_into_vault_via_oidc_v12_6.png) - The terminal will output: + The terminal outputs: ```plaintext Success! You are now authenticated. The token information displayed below diff --git a/doc/operations/feature_flags.md b/doc/operations/feature_flags.md index e22a45fc18c..9ce7eb0ede2 100644 --- a/doc/operations/feature_flags.md +++ b/doc/operations/feature_flags.md @@ -226,9 +226,9 @@ To remove users from a user list: > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/8240) in GitLab 12.2. > - [Made read-only](https://gitlab.com/gitlab-org/gitlab/-/issues/220228) in GitLab 13.4. -In GitLab 13.0 and earlier, the **Rollout strategy** setting affects which users will experience -the feature as enabled. Choose the percentage of users that the feature will be enabled -for. The rollout strategy will have no effect if the environment spec is disabled. +In GitLab 13.0 and earlier, the **Rollout strategy** setting affects which users experience +the feature as enabled. Choose the percentage of users that the feature is enabled +for. The rollout strategy has no effect if the environment spec is disabled. It can be set to: @@ -282,7 +282,7 @@ To get the access credentials that your application needs to communicate with Gi could be `production` or similar. This value is used for the environment spec evaluation. Note that the meaning of these fields might change over time. For example, we're not sure if -**Instance ID** will be single token or multiple tokens, assigned to the **Environment**. Also, +**Instance ID** is a single token or multiple tokens, assigned to the **Environment**. Also, **Application name** could describe the application version instead of the running environment. ### Choose a client library diff --git a/doc/operations/incident_management/alert_integrations.md b/doc/operations/incident_management/alert_integrations.md index 70c4e7f2f29..0f695e7a6c9 100644 --- a/doc/operations/incident_management/alert_integrations.md +++ b/doc/operations/incident_management/alert_integrations.md @@ -79,11 +79,11 @@ to configure alerts for this integration. ## Customize the alert payload outside of GitLab For all integration types, you can customize the payload by sending the following -parameters. All fields other than `title` are optional: +parameters. All fields are optional. If the incoming alert does not contain a value for the `Title` field, a default value of `New: Incident` will be applied. | Property | Type | Description | | ------------------------- | --------------- | ----------- | -| `title` | String | The title of the incident. Required. | +| `title` | String | The title of the incident. | | `description` | String | A high-level summary of the problem. | | `start_time` | DateTime | The time of the incident. If none is provided, a timestamp of the issue is used. | | `end_time` | DateTime | For existing alerts only. When provided, the alert is resolved and the associated incident is closed. | @@ -170,13 +170,14 @@ If the existing alert is already `resolved`, GitLab creates a new alert instead. ## Link to your Opsgenie Alerts +> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. + WARNING: We are building deeper integration with Opsgenie and other alerting tools through -[HTTP endpoint integrations](#single-http-endpoint) so you can see alerts within +[HTTP endpoint integrations](#single-http-endpoint) so you can see alerts in the GitLab interface. As a result, the previous direct link to Opsgenie Alerts from -the GitLab alerts list is scheduled for deprecation following the 13.7 release on December 22, 2020. - -> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3066) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.2. +the GitLab alerts list is deprecated in +GitLab versions [13.8 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/273657). You can monitor alerts using a GitLab integration with [Opsgenie](https://www.atlassian.com/software/opsgenie). diff --git a/doc/operations/incident_management/img/incident_metrics_tab_v13_8.png b/doc/operations/incident_management/img/incident_metrics_tab_v13_8.png Binary files differnew file mode 100644 index 00000000000..27345b09419 --- /dev/null +++ b/doc/operations/incident_management/img/incident_metrics_tab_v13_8.png diff --git a/doc/operations/incident_management/img/metric_image_url_dialog_v13_8.png b/doc/operations/incident_management/img/metric_image_url_dialog_v13_8.png Binary files differnew file mode 100644 index 00000000000..732921bbb9f --- /dev/null +++ b/doc/operations/incident_management/img/metric_image_url_dialog_v13_8.png diff --git a/doc/operations/incident_management/incidents.md b/doc/operations/incident_management/incidents.md index 074cacd2e30..3f6522b3f90 100644 --- a/doc/operations/incident_management/incidents.md +++ b/doc/operations/incident_management/incidents.md @@ -10,6 +10,9 @@ Incidents are critical entities in incident management workflows. They represent a service disruption or outage that needs to be restored urgently. GitLab provides tools for the triage, response, and remediation of incidents. +Users with at least Guest [permissions](../../user/permissions.md) can access +incidents [on public projects](../../user/permissions.md#project-members-permissions). + ## Incident Creation You can create an incident manually or automatically. @@ -126,7 +129,7 @@ For a live example of the incident list in action, visit this > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/230847) in GitLab 13.4. -Users with at least Reporter [permissions](../../user/permissions.md) can view +Users with at least Guest [permissions](../../user/permissions.md) can view the Incident Details page. Navigate to **Operations > Incidents** in your project's sidebar, and select an incident from the list. @@ -160,6 +163,19 @@ Beneath the highlight bar, GitLab displays a summary that includes the following Comments are displayed in threads, but can be displayed chronologically [in a timeline view](#timeline-view). +### Metrics + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/235994) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.8. + +In many cases, incidents are associated to metrics. You can upload screenshots of metric +charts in the **Metrics** tab: + +![Incident Metrics tab](img/incident_metrics_tab_v13_8.png) + +When you upload an image, you can associate it with a URL to the original graph. Users can access the original graph by clicking the image: + +![Metric image URL dialog](img/metric_image_url_dialog_v13_8.png) + ### Alert details Incidents show the details of linked alerts in a separate tab. To populate this diff --git a/doc/public_access/img/project_visibility_confirmation_v12_6.png b/doc/public_access/img/project_visibility_confirmation_v12_6.png Binary files differdeleted file mode 100644 index 8fba57f353b..00000000000 --- a/doc/public_access/img/project_visibility_confirmation_v12_6.png +++ /dev/null diff --git a/doc/public_access/public_access.md b/doc/public_access/public_access.md index 8d751d10aa5..5d07095ac3e 100644 --- a/doc/public_access/public_access.md +++ b/doc/public_access/public_access.md @@ -92,16 +92,6 @@ by accident. The restricted visibility settings do not apply to admin users. For details, see [Restricted visibility levels](../user/admin_area/settings/visibility_and_access_controls.md#restricted-visibility-levels). -## Reducing visibility - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/33358) in GitLab 12.6. - -Reducing a project's visibility level removes the fork relationship between the project and -any forked project. This is a potentially destructive action which requires confirmation before -this can be saved. - -![Project visibility change confirmation](img/project_visibility_confirmation_v12_6.png) - <!-- ## Troubleshooting Include any troubleshooting steps that you can foresee. If you know beforehand what issues diff --git a/doc/push_rules/push_rules.md b/doc/push_rules/push_rules.md index 99a5ac8ed3b..4f902382fd5 100644 --- a/doc/push_rules/push_rules.md +++ b/doc/push_rules/push_rules.md @@ -84,21 +84,21 @@ override them in a project's settings. They can be also set on a [group level](. 1. Set the rule you want 1. Click **Save Push Rules** for the changes to take effect -The following options are available. - -| Push rule | GitLab version | Description | -| --------- | :------------: | ----------- | -| Removal of tags with `git push` | **Starter** 7.10 | Forbid users to remove Git tags with `git push`. Tags will still be able to be deleted through the web UI. | -| Check whether author is a GitLab user | **Starter** 7.10 | Restrict commits by author (email) to existing GitLab users. | -| Committer restriction | **Premium** 10.2 | GitLab will reject any commit that was not committed by the current authenticated user | -| Check whether commit is signed through GPG | **Premium** 10.1 | Reject commit when it is not signed through GPG. Read [signing commits with GPG](../user/project/repository/gpg_signed_commits/index.md). | -| Prevent committing secrets to Git | **Starter** 8.12 | GitLab will reject any files that are likely to contain secrets. Read [what files are forbidden](#prevent-pushing-secrets-to-the-repository). | -| Restrict by commit message | **Starter** 7.10 | Only commit messages that match this regular expression are allowed to be pushed. Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. | -| Restrict by commit message (negative match)| **Starter** 11.1 | Only commit messages that do not match this regular expression are allowed to be pushed. Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. | -| Restrict by branch name | **Starter** 9.3 | Only branch names that match this regular expression are allowed to be pushed. Leave empty to allow any branch name. | -| Restrict by commit author's email | **Starter** 7.10 | Only commit author's email that match this regular expression are allowed to be pushed. Leave empty to allow any email. | -| Prohibited file names | **Starter** 7.10 | Any committed filenames that match this regular expression and do not already exist in the repository are not allowed to be pushed. Leave empty to allow any filenames. See [common examples](#prohibited-file-names). | -| Maximum file size | **Starter** 7.12 | Pushes that contain added or updated files that exceed this file size (in MB) are rejected. Set to 0 to allow files of any size. Files tracked by Git LFS are exempted. | +The following options are available: + +| Push rule | Description | +|---------------------------------|-------------| +| Removal of tags with `git push` | Forbid users to remove Git tags with `git push`. Tags will still be able to be deleted through the web UI. | +| Check whether author is a GitLab user | Restrict commits by author (email) to existing GitLab users. | +| Committer restriction **(PREMIUM)** | GitLab will reject any commit that was not committed by the current authenticated user. | +| Check whether commit is signed through GPG **(PREMIUM)** | Reject commit when it is not signed through GPG. Read [signing commits with GPG](../user/project/repository/gpg_signed_commits/index.md). | +| Prevent committing secrets to Git | GitLab will reject any files that are likely to contain secrets. Read [what files are forbidden](#prevent-pushing-secrets-to-the-repository). | +| Restrict by commit message | Only commit messages that match this regular expression are allowed to be pushed. Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. | +| Restrict by commit message (negative match) | Only commit messages that do not match this regular expression are allowed to be pushed. Leave empty to allow any commit message. Uses multiline mode, which can be disabled using `(?-m)`. | +| Restrict by branch name | Only branch names that match this regular expression are allowed to be pushed. Leave empty to allow any branch name. | +| Restrict by commit author's email | Only commit author's email that match this regular expression are allowed to be pushed. Leave empty to allow any email. | +| Prohibited file names | Any committed filenames that match this regular expression and do not already exist in the repository are not allowed to be pushed. Leave empty to allow any filenames. See [common examples](#prohibited-file-names). | +| Maximum file size | Pushes that contain added or updated files that exceed this file size (in MB) are rejected. Set to 0 to allow files of any size. Files tracked by Git LFS are exempted. | NOTE: GitLab uses [RE2 syntax](https://github.com/google/re2/wiki/Syntax) for regular expressions in push rules, and you can test them at the [regex101 regex tester](https://regex101.com/). @@ -174,15 +174,15 @@ id_ecdsa ##################### # Any file ending with _history or .history extension ##################### -pry.history -bash_history +*.history +*_history ``` ## Prohibited file names > Introduced in [GitLab Starter](https://about.gitlab.com/pricing/) 7.10. -Each file name contained in a Git push is compared to the regular expression in this field. Filenames in Git consist of both the file's name and any directory that may precede it. A singular regular expression can contain multiple independent matches used as exclusions. File names can be broadly matched to any location in the repository, or restricted to specific locations. Filenames can also be partial matches used to exclude file types by extension. +Each filename contained in a Git push is compared to the regular expression in this field. Filenames in Git consist of both the file's name and any directory that may precede it. A singular regular expression can contain multiple independent matches used as exclusions. File names can be broadly matched to any location in the repository, or restricted to specific locations. Filenames can also be partial matches used to exclude file types by extension. The following examples make use of regex string boundary characters which match the beginning of a string (`^`), and the end (`$`). They also include instances where either the directory path or the filename can include `.` or `/`. Both of these special regex characters have to be escaped with a backslash `\\` to be used as normal characters in a match condition. diff --git a/doc/raketasks/README.md b/doc/raketasks/README.md index a42bf2a5d91..e119563fd25 100644 --- a/doc/raketasks/README.md +++ b/doc/raketasks/README.md @@ -42,7 +42,7 @@ The following are available Rake tasks: | [Repository storage](../administration/raketasks/storage.md) | List and migrate existing projects and attachments from legacy storage to hashed storage. | | [Uploads migrate](../administration/raketasks/uploads/migrate.md) | Migrate uploads between storage local and object storage. | | [Uploads sanitize](../administration/raketasks/uploads/sanitize.md) | Remove EXIF data from images uploaded to earlier versions of GitLab. | -| [Usage data](../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping) | Generate and troubleshoot [Usage Ping](../development/product_analytics/usage_ping.md).| +| [Usage data](../administration/troubleshooting/gitlab_rails_cheat_sheet.md#generate-usage-ping) | Generate and troubleshoot [Usage Ping](../development/usage_ping.md).| | [User management](user_management.md) | Perform user management tasks. | | [Webhooks administration](web_hooks.md) | Maintain project Webhooks. | | [X.509 signatures](x509_signatures.md) | Update X.509 commit signatures, useful if certificate store has changed. | diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 03ffd6bd6ad..8a01975f771 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -61,6 +61,7 @@ including: - Container Registry images - GitLab Pages content - Snippets +- Group wikis **(PREMIUM)** WARNING: GitLab does not back up any configuration files, SSL certificates, or system @@ -890,7 +891,7 @@ Restoring repositories: Deleting tmp directories...[DONE] ``` -Next, restore `/home/git/gitlab/.secret` if necessary, as previously mentioned. +Next, restore `/home/git/gitlab/.secret` if necessary, [as previously mentioned](#restore-prerequisites). Restart GitLab: @@ -943,8 +944,16 @@ permissions on your Registry directory. This is a [known issue](https://gitlab.c On GitLab 12.2 or later, you can use `gitlab-backup restore` to avoid this issue. -Next, restore `/etc/gitlab/gitlab-secrets.json` if necessary, as previously -mentioned. +If there's a GitLab version mismatch between your backup tar file and the +installed version of GitLab, the restore command aborts with an error +message. Install the [correct GitLab version](https://packages.gitlab.com/gitlab/), +and then try again. + +NOTE: +There is a known issue with restore not working with `pgbouncer`. [Read more about backup and restore with `pgbouncer`](#backup-and-restore-for-installations-using-pgbouncer). + +Next, restore `/etc/gitlab/gitlab-secrets.json` if necessary, +[as previously mentioned](#restore-prerequisites). Reconfigure, restart and check GitLab: @@ -954,13 +963,13 @@ sudo gitlab-ctl restart sudo gitlab-rake gitlab:check SANITIZE=true ``` -If there's a GitLab version mismatch between your backup tar file and the -installed version of GitLab, the restore command aborts with an error -message. Install the [correct GitLab version](https://packages.gitlab.com/gitlab/), -and then try again. +On GitLab 13.1 and later, check [database values can be decrypted](../administration/raketasks/doctor.md) +especially if `/etc/gitlab/gitlab-secrets.json` was restored, or if a different server is +the target for the restore. -NOTE: -There is a known issue with restore not working with `pgbouncer`. [Read more about backup and restore with `pgbouncer`](#backup-and-restore-for-installations-using-pgbouncer). +```shell +sudo gitlab-rake gitlab:doctor:secrets +``` ### Restore for Docker image and GitLab Helm chart installations @@ -1068,6 +1077,13 @@ following error message is shown: ActiveRecord::StatementInvalid: PG::UndefinedTable ``` +Each time the GitLab backup runs, GitLab will start generating 500 errors and errors about missing +tables will [be logged by PostgreSQL](../administration/logs.md#postgresql-logs): + +```plaintext +ERROR: relation "tablename" does not exist at character 123 +``` + This happens because the task uses `pg_dump`, which [sets a null search path and explicitly includes the schema in every SQL query](https://gitlab.com/gitlab-org/gitlab/-/issues/23211) to address [CVE-2018-1058](https://www.postgresql.org/about/news/postgresql-103-968-9512-9417-and-9322-released-1834/). diff --git a/doc/raketasks/migrate_snippets.md b/doc/raketasks/migrate_snippets.md index 8050a8a38e5..244ff4f2b56 100644 --- a/doc/raketasks/migrate_snippets.md +++ b/doc/raketasks/migrate_snippets.md @@ -14,7 +14,7 @@ and users can update it directly through Git. Nevertheless, existing GitLab Snippets have to be migrated to this new functionality. For each snippet, a new repository is created and the snippet content is committed -to the repository inside a file whose name is the file name used in the snippet +to the repository inside a file whose name is the filename used in the snippet as well. GitLab performs this migration through a [Background Migration](../development/background_migrations.md) diff --git a/doc/security/rack_attack.md b/doc/security/rack_attack.md index f159b4f8e21..d80de92501e 100644 --- a/doc/security/rack_attack.md +++ b/doc/security/rack_attack.md @@ -54,11 +54,7 @@ By default, protected paths are: - `/import/github/personal_access_token` - `/admin/session` -This header is included in responses to blocked requests: - -```plaintext -Retry-After: 60 -``` +See [User and IP rate limits](../user/admin_area/settings/user_and_ip_rate_limits.md#response-headers) for the headers responded to blocked requests. For example, the following are limited to a maximum 10 requests per minute: diff --git a/doc/security/webhooks.md b/doc/security/webhooks.md index 0bb8e90d38f..bed998a5c84 100644 --- a/doc/security/webhooks.md +++ b/doc/security/webhooks.md @@ -26,7 +26,7 @@ sent. Webhook requests are made by the GitLab server itself and use a single (optional) secret token per hook for authorization (instead of a user or -repo-specific token). As a result, these may have broader access than +repository-specific token). As a result, these may have broader access than intended to everything running on the server hosting the webhook (which may include the GitLab server or API itself, e.g., `http://localhost:123`). Depending on the called webhook, this may also result in network access diff --git a/doc/subscriptions/gitlab_com/index.md b/doc/subscriptions/gitlab_com/index.md index 7dd08da74f9..aef1c1127c5 100644 --- a/doc/subscriptions/gitlab_com/index.md +++ b/doc/subscriptions/gitlab_com/index.md @@ -1,6 +1,6 @@ --- -stage: fulfillment -group: fulfillment +stage: Fulfillment +group: Purchase info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments type: index, reference --- @@ -106,15 +106,46 @@ to the **Billing** section of the relevant namespace: The following table describes details of your subscription for groups: - | Field | Description | - |-------------------------|-----------------------------------------------------------------------------------------------------------------------------------------| - | **Seats in subscription** | If this is a paid plan, represents the number of seats you've paid to support in your group. | - | **Seats currently in use** | Number of seats in use. | - | **Max seats used** | Highest number of seats you've used. If this exceeds the seats in subscription, you may owe an additional fee for the additional users. | - | **Seats owed** | If your maximum seats used exceeds the seats in your subscription, you owe an additional fee for the users you've added. | - | **Subscription start date** | Date your subscription started. If this is for a Free plan, is the date you transitioned off your group's paid plan. | - | **Subscription end date** | Date your current subscription ends. Does not apply to Free plans. | - | **Billable users list** | List of users that belong to your group subscription. Does not apply to Free plans. | + | Field | Description | + |-----------------------------|-------------| + | **Seats in subscription** | If this is a paid plan, represents the number of seats you've bought for this group. | + | **Seats currently in use** | Number of seats in use. Select **See usage** to see a list of the users using these seats. For more details, see [Seat usage](#seat-usage). | + | **Max seats used** | Highest number of seats you've used. | + | **Seats owed** | _Seats owed_ = _Max seats used_ - _Seats in subscription_. | + | **Subscription start date** | Date your subscription started. If this is for a Free plan, it's the date you transitioned off your group's paid plan. | + | **Subscription end date** | Date your current subscription ends. Does not apply to Free plans. | + +## Seat usage + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216899) in GitLab 13.5. +> - [Updated](https://gitlab.com/gitlab-org/gitlab/-/issues/292086) in GitLab 13.8 to include public + email address. + +The **Seat usage** page lists all users occupying seats. Details for each user include: + +- Full name +- Username +- Public email address (if they have provided one in their [profile settings](../../user/profile/index.md#profile-settings)) + +The Seat usage listing is updated live, but the usage statistics on the billing page are updated +only once per day. For this reason there can be a minor difference between the seat usage listing +and the billing page. + +### Search seat usage + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/262875) in GitLab 13.8. + +To search users in the **Seat usage** page, enter a string in the search field. A minimum of 3 +characters are required. + +The search returns those users whose first name, last name, or username contain the search string. + +For example: + +| First name | Search string | Match ? | +|:-----------|:--------------|:--------| +| Amir | `ami` | Yes | +| Amir | `amr` | No | ## Renew your GitLab.com subscription diff --git a/doc/subscriptions/index.md b/doc/subscriptions/index.md index d80a2ebe179..383ba471df4 100644 --- a/doc/subscriptions/index.md +++ b/doc/subscriptions/index.md @@ -1,6 +1,6 @@ --- -stage: none -group: unassigned +stage: Fulfillment +group: Purchase info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments type: index, reference --- diff --git a/doc/subscriptions/self_managed/index.md b/doc/subscriptions/self_managed/index.md index 301d78b708a..a9c0337509a 100644 --- a/doc/subscriptions/self_managed/index.md +++ b/doc/subscriptions/self_managed/index.md @@ -1,6 +1,6 @@ --- -stage: none -group: unassigned +stage: Fulfillment +group: Purchase info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments type: index, reference --- @@ -11,6 +11,16 @@ You can install, administer, and maintain your own GitLab instance. This page covers the details of your GitLab self-managed subscription. +GitLab subscription management requires access to the Customers Portal. + +## Customers Portal + +GitLab provides the [Customers Portal](../index.md#customers-portal) where you can +manage your subscriptions and your account details. + +Customers of resellers do not have access to this portal and should contact their reseller for any +changes to their subscription. + ## Subscription The cost of a GitLab self-managed subscription is determined by the following: @@ -43,7 +53,7 @@ billable user, with the following exceptions: count toward overages in the subscribed seat count. - Users who are [pending approval](../../user/admin_area/approving_users.md). - Members with Guest permissions on an Ultimate subscription. -- GitLab-created service accounts: `Ghost User` and bots (`Support Bot`, [`Project bot users`](../../user/project/settings/project_access_tokens.md#project-bot-users), and so on). +- GitLab-created service accounts: `Ghost User` and bots [(`Support Bot`](../../user/project/service_desk.md#support-bot-user), [`Project bot users`](../../user/project/settings/project_access_tokens.md#project-bot-users), and so on). ### Tips for managing users and subscription seats @@ -95,10 +105,10 @@ It also displays the following important statistics: | Field | Description | |:-------------------|:------------| -| Users in License | The number of users you've paid for in the current license loaded on the system. This does not include the amount you've paid for `Users over license` during renewal. | -| Billable users | The daily count of billable users on your system. | -| Maximum users | The highest number of billable users on your system during the term of the loaded license. If this number exceeds your users in license count at any point, you incur users over license. | -| Users over license | The number of users that exceed the `Users in License` for the current license term. Charges for this number of users are incurred at the next renewal. | +| Users in License | The number of users you've paid for in the current license loaded on the system. The number does not change unless you [add seats](#add-seats-to-a-subscription) during your current subscription period. | +| Billable users | The daily count of billable users on your system. The count may change as you block or add users to your instance. | +| Maximum users | The highest number of billable users on your system during the term of the loaded license. | +| Users over license | Calculated as `Maximum users` - `Users in License` for the current license term. This number incurs a retroactive charge that needs to be paid for at renewal. | ## Renew your subscription @@ -122,28 +132,38 @@ the contact person who manages your subscription. It's important to regularly review your user accounts, because: -- A GitLab subscription is based on the number of users. You pay more than you should if you renew - for too many users, while the renewal fails if you attempt to renew a subscription for too few - users. +- Stale user accounts that are not blocked count as billable users. You may pay more than you should + if you renew for too many users. - Stale user accounts can be a security risk. A regular review helps reduce this risk. #### Users over License -A GitLab subscription is valid for a specific number of users. For details, see -[Billable users](#billable-users). If the billable user -count exceeds the number included in the subscription, known as the number of -_users over license_, you must pay for the excess number of users either before -renewal, or at the time of renewal. This is also known as the _true up_ process. +A GitLab subscription is valid for a specific number of seats. The number of users over license +is the number of _Maximum users_ that exceed the _Users in License_ for the current license term. +You must pay for this number of users either before renewal, or at the time of renewal. This is +known as the _true up_ process. + +To view the number of _users over license_ go to the **Admin Area**. -To view the number of _Users over License_ go to the **Admin Area**. +##### Users over license example -### Add users to a subscription +You purchase a license for 10 users. -Self-managed instances can add users to a subscription any time during the -subscription period. The cost of additional users added during the subscription +| Event | Billable members | Maximum users | +|:---------------------------------------------------|:-----------------|:--------------| +| Ten people (users) occupy all 10 seats. | 10 | 10 | +| Two new people join. | 12 | 12 | +| Three people leave and their accounts are removed. | 9 | 12 | + +Users over license = 12 - 10 (Maximum users - users in license) + +### Add seats to a subscription + +The users in license count can be increased by adding seats to a subscription any time during the +subscription period. The cost of seats added during the subscription period is prorated from the date of purchase through the end of the subscription period. -To add users to a subscription: +To add seats to a subscription: 1. Log in to the [Customers Portal](https://customers.gitlab.com/). 1. Navigate to the **Manage Purchases** page. @@ -185,7 +205,7 @@ An invoice is generated for the renewal and available for viewing or download on Seat Link allows GitLab Inc. to provide our self-managed customers with prorated charges for user growth throughout the year using a quarterly reconciliation process. -Seat Link daily sends a count of all users in connected self-managed instances to GitLab. That information is used to automate prorated reconciliations. The data is sent securely through an encrypted HTTPS connection. +Seat Link daily sends a count of all users in connected self-managed instances to GitLab. That information is used to automate prorated reconciliations. The data is sent securely through an encrypted HTTPS connection to `customers.gitlab.com` on port `443`. Seat Link provides **only** the following information to GitLab: @@ -312,11 +332,6 @@ only. However, if you remove the license, you immediately revert to Core features, and the instance become read / write again. -## Customers Portal - -GitLab provides the [Customers Portal](../index.md#customers-portal) where you can -manage your subscriptions and your account details. - ## Contact Support Learn more about: diff --git a/doc/system_hooks/system_hooks.md b/doc/system_hooks/system_hooks.md index b3a74e62ba8..7e4d274f21b 100644 --- a/doc/system_hooks/system_hooks.md +++ b/doc/system_hooks/system_hooks.md @@ -535,9 +535,11 @@ X-Gitlab-Event: System Hook { "object_kind": "merge_request", "user": { + "id": 1, "name": "Administrator", "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", + "email": "admin@example.com" }, "project": { "name": "Example", diff --git a/doc/telemetry/index.md b/doc/telemetry/index.md index 57740672fb4..b3b3b0b4fdd 100644 --- a/doc/telemetry/index.md +++ b/doc/telemetry/index.md @@ -1,8 +1,8 @@ --- -redirect_to: '../development/product_analytics/index.md' +redirect_to: 'https://about.gitlab.com/handbook/product/product-intelligence-guide/' --- -This document was moved to [another location](../development/product_analytics/index.md). +This document was moved to [another location](https://about.gitlab.com/handbook/product/product-intelligence-guide/). <!-- This redirect file can be deleted after February 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/telemetry/snowplow.md b/doc/telemetry/snowplow.md index ac157a8e639..709c61b9e64 100644 --- a/doc/telemetry/snowplow.md +++ b/doc/telemetry/snowplow.md @@ -1,8 +1,8 @@ --- -redirect_to: '../development/product_analytics/snowplow.md' +redirect_to: '../development/snowplow.md' --- -This document was moved to [another location](../development/product_analytics/snowplow.md). +This document was moved to [another location](../development/snowplow.md). <!-- This redirect file can be deleted after February 1, 2021. --> <!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/topics/autodevops/index.md b/doc/topics/autodevops/index.md index 7234bca8e12..78be67a5196 100644 --- a/doc/topics/autodevops/index.md +++ b/doc/topics/autodevops/index.md @@ -30,9 +30,12 @@ configuration. Automation enables consistency across your projects, seamless management of processes, and faster creation of new projects: push your code, and GitLab does the rest, improving your productivity and efficiency. +<i class="fa fa-youtube-play youtube" aria-hidden="true"></i> For an introduction to Auto DevOps, watch [AutoDevOps in GitLab 11.0](https://youtu.be/0Tc0YYBxqi4). -For requirements, see [Requirements for Auto DevOps](requirements.md) for more information. +For requirements, read [Requirements for Auto DevOps](requirements.md) for more information. + +For a developer's guide, read [Auto DevOps development guide](../../development/auto_devops.md). ## Enabled by default @@ -307,6 +310,11 @@ and verifying your application is deployed as a Review App in the Kubernetes cluster with the `review/*` environment scope. Similarly, you can check the other environments. +[Cluster environment scope isn't respected](https://gitlab.com/gitlab-org/gitlab/-/issues/20351) +when checking for active Kubernetes clusters. For multi-cluster setup to work with Auto DevOps, +create a fallback cluster with **Cluster environment scope** set to `*`. A new cluster isn't +required. You can use any of the clusters already added. + ## Limitations The following restrictions apply. @@ -481,7 +489,7 @@ that works for this problem. Follow these steps to use the tool in Auto DevOps: ### Error: error initializing: Looks like "https://kubernetes-charts.storage.googleapis.com" is not a valid chart repository or cannot be reached -As [announced in the official CNCF blogpost](https://www.cncf.io/blog/2020/10/07/important-reminder-for-all-helm-users-stable-incubator-repos-are-deprecated-and-all-images-are-changing-location/), +As [announced in the official CNCF blog post](https://www.cncf.io/blog/2020/10/07/important-reminder-for-all-helm-users-stable-incubator-repos-are-deprecated-and-all-images-are-changing-location/), the stable Helm chart repository was deprecated and removed on November 13th, 2020. You may encounter this error after that date. @@ -526,7 +534,7 @@ To fix your custom chart: it's used to verify the integrity of the downloaded dependencies. You can find more information in -[issue #263778, "Migrate PostgreSQL from stable Helm repo"](https://gitlab.com/gitlab-org/gitlab/-/issues/263778). +[issue #263778, "Migrate PostgreSQL from stable Helm repository"](https://gitlab.com/gitlab-org/gitlab/-/issues/263778). ### Error: release .... failed: timed out waiting for the condition @@ -545,7 +553,7 @@ page of the deployed application on port 5000. If your application isn't configu to serve anything at the root page, or is configured to run on a specific port *other* than 5000, this check fails. -If it fails, you should see these failures within the events for the relevant +If it fails, you should see these failures in the events for the relevant Kubernetes namespace. These events look like the following example: ```plaintext diff --git a/doc/topics/autodevops/quick_start_guide.md b/doc/topics/autodevops/quick_start_guide.md index 5c3b296fdea..effdb4d7b75 100644 --- a/doc/topics/autodevops/quick_start_guide.md +++ b/doc/topics/autodevops/quick_start_guide.md @@ -25,7 +25,7 @@ Sign in with an existing Google account, such as the one you use to access Gmail or Google Drive, or create a new one. 1. Follow the steps described in the ["Before you begin" section](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin) - of the Kubernetes Engine docs to enable the required APIs and related services. + of the Kubernetes Engine documentation to enable the required APIs and related services. 1. Ensure you've created a [billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account) with Google Cloud Platform. @@ -101,30 +101,41 @@ to deploy this project to. After a couple of minutes, the cluster is created. You can also see its status on your [GCP dashboard](https://console.cloud.google.com/kubernetes). -Next, install some applications on your cluster that are needed -to take full advantage of Auto DevOps. +## Install Ingress -## Install Ingress and Prometheus +After your cluster is running, you must install NGINX Ingress Controller as a +load balancer, to route traffic from the internet to your application. Because +you've created a Google GKE cluster in this guide, you can install NGINX Ingress Controller +with Google Cloud Shell: -After your cluster is running, you can install your first applications, -Ingress and Prometheus: +1. Go to your cluster's details page, and click the **Advanced Settings** tab. +1. Click the link to Google Kubernetes Engine to visit the cluster on Google Cloud Console. +1. On the GKE cluster page, select **Connect**, then click **Run in Cloud Shell**. +1. After the Cloud Shell starts, run these commands to install NGINX Ingress Controller: -- Ingress - Provides load balancing, SSL termination, and name-based virtual hosting, - using NGINX behind the scenes. -- Prometheus - An open-source monitoring and alerting system used to supervise the - deployed application. + ```shell + helm repo add nginx-stable https://helm.nginx.com/stable + helm repo update + helm install nginx-ingress nginx-stable/nginx-ingress -We aren't installing GitLab Runner in this quick start guide, as this guide uses the -shared runners provided by GitLab.com. + # Check that the ingress controller is installed successfully + kubectl get service nginx-ingress-nginx-ingress + ``` + +1. A few minutes after you install NGINX, the load balancer obtains an IP address, and you can + get the external IP address with this command: + + ```shell + kubectl get service nginx-ingress-nginx-ingress -ojson | jq -r '.status.loadBalancer.ingress[].ip' + ``` -To install the applications: + Copy this IP address, as you need it in the next step. -- Click the **Install** button for **Ingress**. -- When the **Ingress Endpoint** is displayed, copy the IP address. -- Add your **Base domain**. For this guide, use the domain suggested by GitLab. -- Click **Save changes**. +1. Go back to the cluster page on GitLab, and go to the **Details** tab. + - Add your **Base domain**. For this guide, use the domain `<IP address>.nip.io`. + - Click **Save changes**. -![Cluster Base Domain](img/guide_base_domain_v12_3.png) + ![Cluster Base Domain](img/guide_base_domain_v12_3.png) ## Enable Auto DevOps (optional) @@ -290,7 +301,7 @@ and then deploys the application to production. After implementing this project, you should have a solid understanding of the basics of Auto DevOps. You started from building and testing, to deploying and monitoring an application -all within GitLab. Despite its automatic nature, Auto DevOps can also be configured +all in GitLab. Despite its automatic nature, Auto DevOps can also be configured and customized to fit your workflow. Here are some helpful resources for further reading: 1. [Auto DevOps](index.md) diff --git a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md index c45390e935d..663060bf59d 100644 --- a/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md +++ b/doc/topics/autodevops/upgrading_auto_deploy_dependencies.md @@ -161,7 +161,7 @@ For example, if the template is bundled in GitLab v13.3, change your `.gitlab-ci ```yaml include: - template: Auto-DevOps.gitlab-ci.yml - - remote: https://gitlab.com/gitlab-org/gitlab/-/blob/v13.3.0-ee/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml + - remote: https://gitlab.com/gitlab-org/gitlab/-/raw/v13.3.0-ee/lib/gitlab/ci/templates/Jobs/Deploy.gitlab-ci.yml ``` ### Ignore warnings and continue deploying @@ -181,7 +181,7 @@ the latest Auto Deploy template into your `.gitlab-ci.yml`: ```yaml include: - template: Auto-DevOps.gitlab-ci.yml - - remote: https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml + - remote: https://gitlab.com/gitlab-org/gitlab/-/raw/master/lib/gitlab/ci/templates/Jobs/Deploy.latest.gitlab-ci.yml ``` WARNING: diff --git a/doc/topics/git/lfs/index.md b/doc/topics/git/lfs/index.md index f6e0cdee2cf..6179175b4cd 100644 --- a/doc/topics/git/lfs/index.md +++ b/doc/topics/git/lfs/index.md @@ -96,7 +96,7 @@ git lfs fetch origin master Make sure your files aren't listed in `.gitignore`, otherwise, they will be ignored by Git thus will not be pushed to the remote repository. -### Migrate an existing repo to Git LFS +### Migrate an existing repository to Git LFS Read the documentation on how to [migrate an existing Git repository with Git LFS](migrate_to_git_lfs.md). diff --git a/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md b/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md index 30be9c42f01..3bd754aabfb 100644 --- a/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md +++ b/doc/topics/git/lfs/migrate_from_git_annex_to_git_lfs.md @@ -71,7 +71,7 @@ Fire up a terminal, navigate to your Git repository and: git push ``` -### Disabling Git Annex in your repo +### Disabling Git Annex in your repository Before changing anything, make sure you have a backup of your repository first. There are a couple of ways to do that, but you can simply clone it to another @@ -164,7 +164,7 @@ At this point, you have two options. Either add, commit and push the files directly back to GitLab or switch to Git LFS. We will tackle the LFS switch in the next section. -### Enabling Git LFS in your repo +### Enabling Git LFS in your repository Git LFS is enabled by default on all GitLab products (GitLab CE, GitLab EE, GitLab.com), therefore, you don't need to do anything server-side. diff --git a/doc/topics/git/lfs/migrate_to_git_lfs.md b/doc/topics/git/lfs/migrate_to_git_lfs.md index 941fc281e4c..ef2675db6d4 100644 --- a/doc/topics/git/lfs/migrate_to_git_lfs.md +++ b/doc/topics/git/lfs/migrate_to_git_lfs.md @@ -5,7 +5,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w description: "How to migrate an existing Git repository to Git LFS with BFG." --- -# Migrate a Git repo into Git LFS with BFG +# Migrate a Git repository into Git LFS with BFG Using Git LFS can help you to reduce the size of your Git repository and improve its performance. @@ -38,7 +38,6 @@ Before beginning, make sure: Storage is required for the entire history of all files. - All the team members you share the repository with have pushed all changes. Branches based on the repository before applying this method cannot be merged. - Branches based on the repo before applying this method cannot be merged. To follow this tutorial, you need: @@ -74,7 +73,7 @@ Consider an example upstream project, `git@gitlab.com:gitlab-tests/test-git-lfs- 1. Clone `--mirror` the repository: Cloning with the mirror flag creates a bare repository. - This ensures you get all the branches within the repo. + This ensures you get all the branches within the repository. It creates a directory called `<repo-name>.git` (in our example, `test-git-lfs-repo-migration.git`), diff --git a/doc/topics/git/numerous_undo_possibilities_in_git/index.md b/doc/topics/git/numerous_undo_possibilities_in_git/index.md index 8fc2259c83e..f6571c7b277 100644 --- a/doc/topics/git/numerous_undo_possibilities_in_git/index.md +++ b/doc/topics/git/numerous_undo_possibilities_in_git/index.md @@ -493,6 +493,8 @@ An alternative is the open source community-maintained tool [BFG](https://rtyley Keep in mind that these tools are faster because they do not provide the same feature set as `git filter-branch` does, but focus on specific use cases. +Refer [Reduce repository size](../../../user/project/repository/reducing_the_repo_size_using_git.md) page to know more about purging files from repository history & GitLab storage. + ## Conclusion There are various options of undoing your work with any version control system, but diff --git a/doc/topics/git/partial_clone.md b/doc/topics/git/partial_clone.md index 590a37d0128..fa42cfd6e5b 100644 --- a/doc/topics/git/partial_clone.md +++ b/doc/topics/git/partial_clone.md @@ -229,7 +229,7 @@ remove filtering: `pack-<SHA1>.promisor` file, which should be empty and should be deleted. 1. Remove partial clone configuration. The partial clone-related configuration - variables should be removed from Git config files. Usually only the following + variables should be removed from Git configuration files. Usually only the following configuration must be removed: - `remote.origin.promisor`. - `remote.origin.partialclonefilter`. diff --git a/doc/topics/gitlab_flow.md b/doc/topics/gitlab_flow.md index 292e35922d6..87d8129dc7f 100644 --- a/doc/topics/gitlab_flow.md +++ b/doc/topics/gitlab_flow.md @@ -22,7 +22,7 @@ It offers a simple, transparent, and effective way to work with Git. When converting to Git, you have to get used to the fact that it takes three steps to share a commit with colleagues. Most version control systems have only one step: committing from the working copy to a shared server. -In Git, you add files from the working copy to the staging area. After that, you commit them to your local repo. +In Git, you add files from the working copy to the staging area. After that, you commit them to your local repository. The third step is pushing to a shared remote repository. After getting used to these three steps, the next challenge is the branching model. diff --git a/doc/topics/web_application_firewall/index.md b/doc/topics/web_application_firewall/index.md index 1c1728d9277..297b2f7eaaa 100644 --- a/doc/topics/web_application_firewall/index.md +++ b/doc/topics/web_application_firewall/index.md @@ -1,97 +1,8 @@ --- -stage: Protect -group: Container Security -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +redirect_to: '../../user/project/clusters/protect/web_application_firewall/index.md' --- +This document was moved to [another location](../../user/project/clusters/protect/web_application_firewall/index.md). -# Web Application Firewall - ModSecurity - -A web application firewall (or WAF) filters, monitors, and blocks HTTP traffic to -and from a web application. By inspecting HTTP traffic, it can prevent attacks -stemming from web application security flaws. It can be used to detect SQL injection, -Cross-Site Scripting (XSS), Remote File Inclusion, Security Misconfigurations, and -much more. - -## Overview - -GitLab provides a WAF out of the box after Ingress is deployed. All you need to do is deploy your -application along with a service and Ingress resource. In the GitLab [Ingress](../../user/clusters/applications.md#ingress) -deployment, the [ModSecurity](https://modsecurity.org/) -module is loaded into Ingress-NGINX by default and monitors the traffic to the applications -which have an Ingress. The ModSecurity module runs with the [OWASP Core Rule Set (CRS)](https://coreruleset.org/) -by default. The OWASP CRS detects and logs a wide range of common attacks. - -By default, the WAF is deployed in Detection-only mode and only logs attack attempts. - -## Requirements - -The Web Application Firewall requires: - -- **Kubernetes** - - To enable the WAF, you need: - - - Kubernetes 1.12+. - - A load balancer. You can use NGINX-Ingress by deploying it to your - Kubernetes cluster by either: - - Using the [`nginx-ingress` Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress). - - Installing the [Ingress GitLab Managed App](../../user/clusters/applications.md#ingress) with WAF enabled. - -- **Configured Kubernetes objects** - - To use the WAF on an application, you need to deploy the following Kubernetes resources: - - - [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) - - [Service](https://kubernetes.io/docs/concepts/services-networking/service/) - - [Ingress Resource](https://kubernetes.io/docs/concepts/services-networking/ingress/) - -## Quick start - -If you are using GitLab.com, see the [quick start guide](quick_start_guide.md) for -how to use the WAF with GitLab.com and a Kubernetes cluster on Google Kubernetes Engine (GKE). - -If you are using a self-managed instance of GitLab, you need to configure the -[Google OAuth2 OmniAuth Provider](../../integration/google.md) before -you can configure a cluster on GKE. Once this is set up, you can follow the steps on the [quick start guide](quick_start_guide.md) to get started. - -NOTE: -This guide shows how the WAF can be deployed using Auto DevOps. The WAF -is available by default to all applications no matter how they are deployed, -as long as they are using Ingress. - -## Network firewall vs. Web Application Firewall - -A network firewall or packet filter looks at traffic at the Network (L3) and Transport (L4) layers -of the [OSI Model](https://en.wikipedia.org/wiki/OSI_model), and denies packets from entry based on -a set of rules regarding the network in general. - -A Web Application Firewall operates at the Application (L7) layer of the OSI Model and can -examine all the packets traveling to and from a specific application. A WAF can set -more advanced rules around threat detection. - -## Features - -ModSecurity is enabled with the [OWASP Core Rule Set (CRS)](https://github.com/coreruleset/coreruleset/) by -default. The OWASP CRS logs attempts to the following attacks: - -- [SQL Injection](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_SQL_Injection) -- [Cross-Site Scripting](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_Cross-Site_Scripting_(XSS)) -- [Local File Inclusion](https://wiki.owasp.org/index.php/Testing_for_Local_File_Inclusion) -- [Remote File Inclusion](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_Remote_File_Inclusion) -- [Code Injection](https://wiki.owasp.org/index.php/Code_Injection) -- [Session Fixation](https://wiki.owasp.org/index.php/Session_fixation) -- [Scanner Detection](https://wiki.owasp.org/index.php/Category:Vulnerability_Scanning_Tools) -- [Metadata/Error Leakages](https://wiki.owasp.org/index.php/Improper_Error_Handling) - -It is good to have a basic knowledge of the following: - -- [Kubernetes](https://kubernetes.io/docs/home/) -- [Ingress](https://kubernetes.github.io/ingress-nginx/) -- [ModSecurity](https://www.modsecurity.org/) -- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/) - -## Roadmap - -You can find more information on the product direction of the WAF in -[Category Direction - Web Application Firewall](https://about.gitlab.com/direction/protect/web_application_firewall/). +<!-- This redirect file can be deleted after <2021-04-01>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/topics/web_application_firewall/quick_start_guide.md b/doc/topics/web_application_firewall/quick_start_guide.md index df355ff2413..4d7244f88fa 100644 --- a/doc/topics/web_application_firewall/quick_start_guide.md +++ b/doc/topics/web_application_firewall/quick_start_guide.md @@ -1,258 +1,8 @@ --- -stage: Protect -group: Container Security -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +redirect_to: '../../user/project/clusters/protect/web_application_firewall/quick_start_guide.md' --- -# Getting started with the Web Application Firewall +This document was moved to [another location](../../user/project/clusters/protect/web_application_firewall/quick_start_guide.md). -This is a step-by-step guide to help you use the GitLab [Web Application Firewall](index.md) after -deploying a project hosted on GitLab.com to Google Kubernetes Engine using [Auto DevOps](../autodevops/index.md). - -The GitLab native Kubernetes integration is used, so you do not need -to create a Kubernetes cluster manually using the Google Cloud Platform console. -A simple application is created and deployed based on a GitLab template. - -These instructions also work for a self-managed GitLab instance. However, you -need to ensure your own [runners are configured](../../ci/runners/README.md) and -[Google OAuth is enabled](../../integration/google.md). - -The GitLab Web Application Firewall is deployed with [Ingress](../../user/clusters/applications.md#ingress), -so it is available to your applications no matter how you deploy them to Kubernetes. - -## Configuring your Google account - -Before creating and connecting your Kubernetes cluster to your GitLab project, -you need a Google Cloud Platform account. If you do not already have one, -sign up at <https://console.cloud.google.com>. You need to either sign in with an existing -Google account (for example, one that you use to access Gmail, Drive, etc.) or create a new one. - -1. To enable the required APIs and related services, follow the steps in the ["Before you begin" section of the Kubernetes Engine docs](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin). -1. Make sure you have created a [billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account). - -NOTE: -Every new Google Cloud Platform (GCP) account receives [$300 in credit](https://console.cloud.google.com/freetrial), -and in partnership with Google, GitLab is able to offer an additional $200 for new GCP accounts to get started with the GitLab -Google Kubernetes Engine integration. All you have to do is [follow this link](https://cloud.google.com/partners/partnercredit/?PCN=a0n60000006Vpz4AAC) and apply for credit. - -## Creating a new project from a template - -We use a GitLab project templates to get started. As the name suggests, -those projects provide a barebones application built on some well-known frameworks. - -1. In GitLab, click the plus icon (**+**) at the top of the navigation bar and select - **New project**. -1. Go to the **Create from template** tab where you can choose for example a Ruby on - Rails, Spring, or NodeJS Express project. - Use the Ruby on Rails template. - - ![Select project template](../autodevops/img/guide_project_template_v12_3.png) - -1. Give your project a name, optionally a description, and make it public so that - you can take advantage of the features available in the - [GitLab Gold plan](https://about.gitlab.com/pricing/#gitlab-com). - - ![Create project](../autodevops/img/guide_create_project_v12_3.png) - -1. Click **Create project**. - -Now that the project is created, the next step is to create the Kubernetes cluster -to deploy this application under. - -## Creating a Kubernetes cluster from within GitLab - -1. On the project's landing page, click **Add Kubernetes cluster** - (note that this option is also available when you navigate to **Operations > Kubernetes**). - - ![Project landing page](../autodevops/img/guide_project_landing_page_v12_10.png) - -1. On the **Create new cluster on GKE** tab, click **Sign in with Google**. - - ![Google sign in](../autodevops/img/guide_google_signin_v12_3.png) - -1. Connect with your Google account and click **Allow** when asked (this - appears only the first time you connect GitLab with your Google account). - - ![Google auth](../autodevops/img/guide_google_auth_v12_3.png) - -1. The last step is to provide the cluster details. - 1. Give it a name, leave the environment scope as is, and choose the GCP project under which to create the cluster. - (Per the instructions to [configure your Google account](#configuring-your-google-account), a project should have already been created for you.) - 1. Choose the [region/zone](https://cloud.google.com/compute/docs/regions-zones/) to create the cluster in. - 1. Enter the number of nodes you want it to have. - 1. Choose the [machine type](https://cloud.google.com/compute/docs/machine-types). - - ![GitLab GKE cluster details](../autodevops/img/guide_gitlab_gke_details_v12_3.png) - -1. Click **Create Kubernetes cluster**. - -After a couple of minutes, the cluster is created. You can also see its -status on your [GCP dashboard](https://console.cloud.google.com/kubernetes). - -The next step is to install some applications on your cluster that are needed -to take full advantage of Auto DevOps. - -## Install Ingress - -The GitLab Kubernetes integration comes with some -[pre-defined applications](../../user/project/clusters/index.md#installing-applications) -for you to install. - -![Cluster applications](../autodevops/img/guide_cluster_apps_v12_3.png) - -For this guide, we need to install Ingress. Ingress provides load balancing, -SSL termination, and name-based virtual hosting, using NGINX behind -the scenes. Make sure to switch the toggle to the enabled position before installing. - -Both logging and blocking modes are available for WAF. While logging mode is useful for -auditing anomalous traffic, blocking mode ensures the traffic doesn't reach past Ingress. - -![Cluster applications](img/guide_waf_ingress_installation_v12_10.png) - -After Ingress is installed, wait a few seconds and copy the IP address that -is displayed in order to add in your base **Domain** at the top of the page. For -the purpose of this guide, we use the one suggested by GitLab. Once you have -filled in the domain, click **Save changes**. - -![Cluster Base Domain](../autodevops/img/guide_base_domain_v12_3.png) - -Prometheus should also be installed. It is an open-source monitoring and -alerting system that is used to supervise the deployed application. -Installing GitLab Runner is not required as we use the shared runners that -GitLab.com provides. - -## Enabling Auto DevOps (optional) - -Starting with GitLab 11.3, Auto DevOps is enabled by default. However, it is possible to disable -Auto DevOps at both the instance-level (for self-managed instances) and the group-level. -Follow these steps if Auto DevOps has been manually disabled: - -1. Navigate to **Settings > CI/CD > Auto DevOps**. -1. Select **Default to Auto DevOps pipeline**. -1. Select the [continuous deployment strategy](../autodevops/index.md#deployment-strategy) - which automatically deploys the application to production once the pipeline - successfully runs on the `master` branch. -1. Click **Save changes**. - - ![Auto DevOps settings](../autodevops/img/guide_enable_autodevops_v12_3.png) - -Once you complete all the above and save your changes, a new pipeline is -automatically created. To view the pipeline, go to **CI/CD > Pipelines**. - -![First pipeline](../autodevops/img/guide_first_pipeline_v12_3.png) - -The next section explains what each pipeline job does. - -## Deploying the application - -By now you should see the pipeline running, but what is it running exactly? - -To navigate inside the pipeline, click its status badge (its status should be "Running"). -The pipeline is split into a few stages, each running a couple of jobs. - -![Pipeline stages](../autodevops/img/guide_pipeline_stages_v13_0.png) - -In the **build** stage, the application is built into a Docker image and then -uploaded to your project's [Container Registry](../../user/packages/container_registry/index.md) ([Auto Build](../autodevops/stages.md#auto-build)). - -In the **test** stage, GitLab runs various checks on the application. - -The **production** stage is run after the tests and checks finish, and it automatically -deploys the application in Kubernetes ([Auto Deploy](../autodevops/stages.md#auto-deploy)). - -The **production** stage creates Kubernetes objects -like a Deployment, Service, and Ingress resource. The -application is monitored by the WAF automatically. - -## Validating Ingress is running ModSecurity - -Now we can make sure that Ingress is running properly with ModSecurity and send -a request to ensure our application is responding correctly. You must connect to -your cluster either using [Cloud Shell](https://cloud.google.com/shell/) or the [Google Cloud SDK](https://cloud.google.com/sdk/docs/install). - -1. After connecting to your cluster, check if the Ingress-NGINX controller is running and ModSecurity is enabled. - - This is done by running the following commands: - - ```shell - $ kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' - ingress-nginx-ingress-controller-55f9cf6584-dxljn 2/2 Running - - $ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- cat /etc/nginx/nginx.conf | grep 'modsecurity on;' - modsecurity on; - ``` - -1. Verify the Rails application has been installed properly. - - ```shell - $ kubectl get ns - auto-devv-2-16730183-production Active - - $ kubectl get pods -n auto-devv-2-16730183-production - NAME READY STATUS RESTARTS - production-5778cfcfcd-nqjcm 1/1 Running 0 - production-postgres-6449f8cc98-r7xgg 1/1 Running 0 - ``` - -1. To make sure the Rails application is responding, send a request to it by running: - - ```shell - $ kubectl get ing -n auto-devv-2-16730183-production - NAME HOSTS PORTS - production-auto-deploy fjdiaz-auto-devv-2.34.68.60.207.nip.io,le-16730183.34.68.60.207.nip.io 80, 443 - - $ curl --location --insecure "fjdiaz-auto-devv-2.34.68.60.207.nip.io" | grep 'Rails!' --after 2 --before 2 - <body> - <p>You're on Rails!</p> - </body> - ``` - -Now that we have confirmed our system is properly setup, we can go ahead and test -the WAF with OWASP CRS! - -## Testing out the OWASP Core Rule Set - -Now let's send a potentially malicious request, as if we were a scanner, -checking for vulnerabilities within our application and examine the ModSecurity logs: - -```shell -$ curl --location --insecure "fjdiaz-auto-devv-2.34.68.60.207.nip.io" --header "User-Agent: absinthe" | grep 'Rails!' --after 2 --before 2 -<body> - <p>You're on Rails!</p> -</body> - -$ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- cat /var/log/modsec/audit.log | grep 'absinthe' -{ - "message": "Found User-Agent associated with security scanner", - "details": { - "match": "Matched \"Operator `PmFromFile' with parameter `scanners-user-agents.data' against variable `REQUEST_HEADERS:user-agent' (Value: `absinthe' )", - "reference": "o0,8v84,8t:lowercase", - "ruleId": "913100", - "file": "/etc/nginx/owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf", - "lineNumber": "33", - "data": "Matched Data: absinthe found within REQUEST_HEADERS:user-agent: absinthe", - "severity": "2", - "ver": "OWASP_CRS/3.2.0", - "rev": "", - "tags": ["application-multi", "language-multi", "platform-multi", "attack-reputation-scanner", "OWASP_CRS", "OWASP_CRS/AUTOMATION/SECURITY_SCANNER", "WASCTC/WASC-21", "OWASP_TOP_10/A7", "PCI/6.5.10"], - "maturity": "0", - "accuracy": "0" - } -} -``` - -You can see that ModSecurity logs the suspicious behavior. By sending a request -with the `User Agent: absinthe` header, which [absinthe](https://github.com/cameronhotchkies/Absinthe), a tool for testing for SQL injections uses, we can detect that someone was -searching for vulnerabilities on our system. Detecting scanners is useful, because we -can learn if someone is trying to exploit our system. - -## Conclusion - -You can now see the benefits of a using a Web Application Firewall. -ModSecurity and the OWASP Core Rule Set, offer many more benefits. -You can explore them in more detail: - -- [Category Direction - Web Application Firewall](https://about.gitlab.com/direction/protect/web_application_firewall/) -- [ModSecurity](https://www.modsecurity.org/) -- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/) -- [AutoDevOps](../autodevops/index.md) +<!-- This redirect file can be deleted after <2021-04-01>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/university/training/topics/getting_started.md b/doc/university/training/topics/getting_started.md index f5c91b94813..fd600624a25 100644 --- a/doc/university/training/topics/getting_started.md +++ b/doc/university/training/topics/getting_started.md @@ -25,7 +25,7 @@ comments: false - To instantiate a central repository a `--bare` flag is required. - Bare repositories don't allow file editing or committing changes. -- Create a bare repo with: +- Create a bare repository with: ```shell git init --bare project-name.git diff --git a/doc/university/training/topics/unstage.md b/doc/university/training/topics/unstage.md index 7e7530aba75..30d26854135 100644 --- a/doc/university/training/topics/unstage.md +++ b/doc/university/training/topics/unstage.md @@ -19,7 +19,7 @@ comments: false git checkout -- <file> ``` -- To remove a file from disk and repo use `git rm` and to remove a directory use the `-r` flag: +- To remove a file from disk and repository, use `git rm`. To remove a directory, use the `-r` flag: ```shell git rm '*.txt' diff --git a/doc/update/README.md b/doc/update/README.md index 45cac3ec8ca..958beeeb321 100644 --- a/doc/update/README.md +++ b/doc/update/README.md @@ -195,7 +195,7 @@ However, for this to work there are the following requirements: 9.3. - You have to use [post-deployment migrations](../development/post_deployment_migrations.md) (included in - zero downtime update steps below). + [zero downtime update steps below](#steps)). - You are using PostgreSQL. Starting from GitLab 12.1, MySQL is not supported. - Multi-node GitLab instance. Single-node instances may experience brief interruptions [as services restart (Puma in particular)](https://docs.gitlab.com/omnibus/update/README.html#single-node-deployment). diff --git a/doc/update/mysql_to_postgresql.md b/doc/update/mysql_to_postgresql.md index 613df2c3a84..fb1335acd7d 100644 --- a/doc/update/mysql_to_postgresql.md +++ b/doc/update/mysql_to_postgresql.md @@ -1,6 +1,6 @@ --- -stage: none -group: unassigned +stage: Enablement +group: Database info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/update/patch_versions.md b/doc/update/patch_versions.md index 754265a23cf..71c8c701775 100644 --- a/doc/update/patch_versions.md +++ b/doc/update/patch_versions.md @@ -1,6 +1,6 @@ --- -stage: none -group: unassigned +stage: Enablement +group: Distribution info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments comments: false --- diff --git a/doc/update/restore_after_failure.md b/doc/update/restore_after_failure.md index 0625cc5a68f..64e92c802f2 100644 --- a/doc/update/restore_after_failure.md +++ b/doc/update/restore_after_failure.md @@ -1,6 +1,6 @@ --- -stage: none -group: unassigned +stage: Enablement +group: Distribution info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/update/upgrading_from_ce_to_ee.md b/doc/update/upgrading_from_ce_to_ee.md index 9a75326009c..7f190a310b0 100644 --- a/doc/update/upgrading_from_ce_to_ee.md +++ b/doc/update/upgrading_from_ce_to_ee.md @@ -1,6 +1,6 @@ --- -stage: none -group: unassigned +stage: Enablement +group: Distribution info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments comments: false --- diff --git a/doc/update/upgrading_from_source.md b/doc/update/upgrading_from_source.md index 770eade6542..93aefb60f61 100644 --- a/doc/update/upgrading_from_source.md +++ b/doc/update/upgrading_from_source.md @@ -1,6 +1,6 @@ --- -stage: none -group: unassigned +stage: Enablement +group: Distribution info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments comments: false --- diff --git a/doc/update/upgrading_postgresql_using_slony.md b/doc/update/upgrading_postgresql_using_slony.md index 89df7090977..c5dd6cf16b7 100644 --- a/doc/update/upgrading_postgresql_using_slony.md +++ b/doc/update/upgrading_postgresql_using_slony.md @@ -1,6 +1,6 @@ --- -stage: none -group: unassigned +stage: Enablement +group: Database info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- diff --git a/doc/user/admin_area/analytics/dev_ops_report.md b/doc/user/admin_area/analytics/dev_ops_report.md index 8f629fd4250..80108fba060 100644 --- a/doc/user/admin_area/analytics/dev_ops_report.md +++ b/doc/user/admin_area/analytics/dev_ops_report.md @@ -38,7 +38,7 @@ collected before this feature is available. ## DevOps Adoption **(ULTIMATE)** -[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247112) in GitLab 13.7. +[Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247112) in GitLab 13.7 as a [Beta feature](https://about.gitlab.com/handbook/product/gitlab-the-product/#beta). The DevOps Adoption tab shows you which segments of your organization are using the most essential features of GitLab: @@ -50,7 +50,9 @@ The DevOps Adoption tab shows you which segments of your organization are using - Deploys - Scanning -Segments are arbitrary collections of GitLab groups that you define. You might define a segment to represent a small team, a large department, or a whole organization. You are limited to creating a maximum of 20 segments, and each segment is limited to a maximum of 20 groups. Buttons to manage your segments appear in the DevOps Adoption section of the page. +Segments are arbitrary collections of GitLab groups that you define. You might define a segment to represent a small team, a large department, or a whole organization. +You are limited to creating a maximum of 20 segments, and each segment is limited to a maximum of 20 groups. +Buttons to manage your segments appear in the DevOps Adoption section of the page. DevOps Adoption allows you to: @@ -62,18 +64,18 @@ DevOps Adoption allows you to: ### Disable or enable DevOps Adoption -DevOps Adoption is deployed behind a feature flag that is **enabled by default**. +DevOps Adoption is deployed behind a feature flag that is **disabled by default**. [GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) -can opt to disable it. +can opt to enable it. -To disable it: +To enable it: ```ruby -Feature.disable(:devops_adoption_feature) +Feature.enable(:devops_adoption_feature) ``` -To enable it: +To disable it: ```ruby -Feature.enable(:devops_adoption_feature) +Feature.disable(:devops_adoption_feature) ``` diff --git a/doc/user/admin_area/analytics/user_cohorts.md b/doc/user/admin_area/analytics/user_cohorts.md index 1d2d0029860..7adc9ad59a5 100644 --- a/doc/user/admin_area/analytics/user_cohorts.md +++ b/doc/user/admin_area/analytics/user_cohorts.md @@ -6,32 +6,31 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Cohorts **(CORE)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/23361) in GitLab 9.1. - As a benefit of having the [usage ping active](../settings/usage_statistics.md), -GitLab lets you analyze the users' activities over time of your GitLab installation. +you can analyze your users' GitLab activities over time. -To see User Cohorts, go to **Admin Area > Analytics > Cohorts**. +To see user cohorts, go to **Admin Area > Analytics > Cohorts**. ## Overview -How do we read the user cohorts table? Let's take an example with the following -user cohorts. +How do you interpret the user cohorts table? Let's review an example with the +following user cohorts: ![User cohort example](img/cohorts_v13_4.png) -For the cohort of March 2020, three users have been added on this server and have -been active since this month. One month later, in April 2020, two users are -still active. Five months later (August), we can see that one user from this cohort -is active, or 33% of the original cohort of three that joined in March. +For the cohort of March 2020, three users were added to this server and have +been active since this month. One month later (April 2020), two users are still +active. Five months later (August 2020), one user from this cohort is still +active, or 33% of the original cohort of three that joined in March. -The Inactive users column shows the number of users who have been added during -the month, but who have never actually had any activity in the instance. +The **Inactive users** column shows the number of users who were added during +the month, but who never had any activity in the instance. How do we measure the activity of users? GitLab considers a user active if: - The user signs in. - The user has Git activity (whether push or pull). -- The user visits pages related to Dashboards, Projects, Issues, and Merge Requests ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54947) in GitLab 11.8). -- The user uses the API -- The user uses the GraphQL API +- The user visits pages related to dashboards, projects, issues, or merge + requests ([introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/54947) in GitLab 11.8). +- The user uses the API. +- The user uses the GraphQL API. diff --git a/doc/user/admin_area/img/license_admin_area.png b/doc/user/admin_area/img/license_admin_area.png Binary files differdeleted file mode 100644 index b5662b81c5e..00000000000 --- a/doc/user/admin_area/img/license_admin_area.png +++ /dev/null diff --git a/doc/user/admin_area/img/license_upload.png b/doc/user/admin_area/img/license_upload.png Binary files differdeleted file mode 100644 index 29d55175a2d..00000000000 --- a/doc/user/admin_area/img/license_upload.png +++ /dev/null diff --git a/doc/user/admin_area/img/license_upload_v13_8.png b/doc/user/admin_area/img/license_upload_v13_8.png Binary files differnew file mode 100644 index 00000000000..c15bc2bfa02 --- /dev/null +++ b/doc/user/admin_area/img/license_upload_v13_8.png diff --git a/doc/user/admin_area/license.md b/doc/user/admin_area/license.md index d7710c362e5..d06b0c844ec 100644 --- a/doc/user/admin_area/license.md +++ b/doc/user/admin_area/license.md @@ -32,7 +32,7 @@ is locked. ## Uploading your license -The very first time you visit your GitLab EE installation signed in as an administrator, +The first time you visit your GitLab EE installation signed in as an administrator, you should see a note urging you to upload a license with a link that takes you to **Admin Area > License**. @@ -42,18 +42,21 @@ Otherwise, you can: 1. Navigate to the **License** tab, and click **Upload New License**. - ![License Admin Area](img/license_admin_area.png) + - *If you've received a `.gitlab-license` file:* + 1. Download the license file to your local machine. + 1. Select **Upload `.gitlab-license` file**. + 1. Select **Choose File** and select the license file. + In this example the license file is named `GitLab.gitlab-license`. + 1. Check the **Subscription Agreement** checkbox. + 1. Select **Upload License**. - - *If you've received a `.gitlab-license` file,* you should have already downloaded - it in your local machine. You can then upload it directly by choosing the - license file and clicking the **Upload license** button. In the image below, - the selected license file is named `GitLab.gitlab-license`. + ![Upload license](img/license_upload_v13_8.png) - ![Upload license](img/license_upload.png) - - - *If you've received your license as plain text,* select the - **Enter license key** option, copy the license, paste it into the **License key** - field, and click **Upload license**. + - *If you've received your license as plain text:* + 1. Select **Enter license key**. + 1. Copy the license and paste it into the **License key** field. + 1. Check the **Subscription Agreement** checkbox. + 1. Select **Upload License**. ## Add your license at install time @@ -120,6 +123,11 @@ You can upload and view more than one license, but only the latest license in th range is used as the active license. When you upload a future-dated license, it doesn't take effect until its applicable date. +NOTE: +In GitLab 13.6 and earlier, a notification banner about an expiring license may continue to be displayed even after a new license has been uploaded. +This happens when the newly uploaded license's start date is in the future and the expiring one is still active. +The banner disappears after the new license becomes active. + ## Troubleshooting ### There is no License tab in the Admin Area diff --git a/doc/user/admin_area/settings/account_and_limit_settings.md b/doc/user/admin_area/settings/account_and_limit_settings.md index bc266216714..028858c96f6 100644 --- a/doc/user/admin_area/settings/account_and_limit_settings.md +++ b/doc/user/admin_area/settings/account_and_limit_settings.md @@ -7,10 +7,18 @@ type: reference # Account and limit settings **(CORE ONLY)** +## Default projects limit + +You can change the default maximum number of projects that users can create in their personal namespace. +Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**. +You can increase or decrease that `Default projects limit` value. + +- If you set `Default projects limit` to 0, users are not allowed to create projects in their users personal namespace. However, projects can still be created within a group. + ## Max attachment size You can change the maximum file size for attachments in comments and replies in GitLab. -Navigate to **Admin Area (wrench icon) > Settings > General**, then expand **Account and Limit**. +Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**. From here, you can increase or decrease by changing the value in `Maximum attachment size (MB)`. NOTE: @@ -21,13 +29,13 @@ details. ## Max push size You can change the maximum push size for your repository. -Navigate to **Admin Area (wrench icon) > Settings > General**, then expand **Account and Limit**. +Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**. From here, you can increase or decrease by changing the value in `Maximum push size (MB)`. ## Max import size You can change the maximum file size for imports in GitLab. -Navigate to **Admin Area (wrench icon) > Settings > General**, then expand **Account and Limit**. +Navigate to **Admin Area > Settings > General**, then expand **Account and Limit**. From here, you can increase or decrease by changing the value in `Maximum import size (MB)`. NOTE: diff --git a/doc/user/admin_area/settings/continuous_integration.md b/doc/user/admin_area/settings/continuous_integration.md index ef2eb046c21..6418be13ee9 100644 --- a/doc/user/admin_area/settings/continuous_integration.md +++ b/doc/user/admin_area/settings/continuous_integration.md @@ -174,7 +174,7 @@ but commented out to help encourage others to add to it in the future. --> WARNING: This feature is being re-evaluated in favor of a different -[compliance solution](https://gitlab.com/gitlab-org/gitlab/-/issues/34830). +[compliance solution](https://gitlab.com/groups/gitlab-org/-/epics/3156). We recommend that users who haven't yet implemented this feature wait for the new solution. @@ -187,6 +187,12 @@ sourced from: - The [instance template repository](instance_template_repository.md). - GitLab-supplied configuration. +NOTE: +When you use a configuration defined in an instance template repository, +nested [`include:`](../../../ci/yaml/README.md#include) keywords +(including `include:file`, `include:local`, `include:remote`, and `include:template`) +[do not work](https://gitlab.com/gitlab-org/gitlab/-/issues/35345). + To set required pipeline configuration: 1. Go to **Admin Area > Settings > CI/CD**. diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md index a7641ec22ca..9a661fa9716 100644 --- a/doc/user/admin_area/settings/index.md +++ b/doc/user/admin_area/settings/index.md @@ -38,7 +38,7 @@ Access the default page for admin area settings by navigating to **Admin Area > | [PlantUML](../../../administration/integration/plantuml.md#gitlab) | Allow rendering of PlantUML diagrams in AsciiDoc and Markdown documents. | | [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) **(FREE ONLY)** | Slack integration allows you to interact with GitLab via slash commands in a chat window. This option is only available on GitLab.com, though it may be [available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164). | | [Third party offers](third_party_offers.md) | Control the display of third party offers. | -| [Snowplow](../../../development/product_analytics/snowplow.md) | Configure the Snowplow integration. | +| [Snowplow](../../../development/snowplow.md) | Configure the Snowplow integration. | | [Google GKE](../../project/clusters/add_gke_clusters.md) | Google GKE integration allows you to provision GKE clusters from GitLab. | | [Amazon EKS](../../project/clusters/add_eks_clusters.md) | Amazon EKS integration allows you to provision EKS clusters from GitLab. | diff --git a/doc/user/admin_area/settings/project_integration_management.md b/doc/user/admin_area/settings/project_integration_management.md index fe4e84b98ac..adb192f5b4a 100644 --- a/doc/user/admin_area/settings/project_integration_management.md +++ b/doc/user/admin_area/settings/project_integration_management.md @@ -51,6 +51,14 @@ is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137). This would allo administrators to update settings inherited by groups and projects without enabling the integration on all non-configured groups and projects by default. +### Remove an instance-level default setting + +1. Navigate to **Admin Area > Settings > Integrations**. +1. Select an integration. +1. Click **Reset** and confirm. + +Resetting an instance-level default setting removes the integration from all projects that have the integration set to use default settings. + ## Manage group-level default settings for a project integration > [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6. @@ -86,6 +94,14 @@ is [planned](https://gitlab.com/groups/gitlab-org/-/epics/2137). This would allo administrators to update settings inherited by subgroups and projects without enabling the integration on all non-configured groups and projects by default. +### Remove a group-level default setting + +1. Navigate to the group's **Settings > Integrations**. +1. Select an integration. +1. Click **Reset** and confirm. + +Resetting a group-level default setting removes integrations that use default settings and belong to a project or subgroup of the group. + ## Use instance-level or group-level default settings for a project integration > [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/2543) in GitLab 13.6 for group-level settings. diff --git a/doc/user/admin_area/settings/protected_paths.md b/doc/user/admin_area/settings/protected_paths.md index 870735f5be7..a03156511e2 100644 --- a/doc/user/admin_area/settings/protected_paths.md +++ b/doc/user/admin_area/settings/protected_paths.md @@ -28,11 +28,7 @@ GitLab rate limits the following paths with Rack Attack by default: GitLab responds with HTTP status code `429` to POST requests at protected paths that exceed 10 requests per minute per IP address. -This header is included in responses to blocked requests: - -```plaintext -Retry-After: 60 -``` +See [User and IP rate limits](../../admin_area/settings/user_and_ip_rate_limits.md#response-headers) for the headers responded to blocked requests. For example, the following are limited to a maximum 10 requests per minute: diff --git a/doc/user/admin_area/settings/usage_statistics.md b/doc/user/admin_area/settings/usage_statistics.md index 02b1428177f..06b39d67228 100644 --- a/doc/user/admin_area/settings/usage_statistics.md +++ b/doc/user/admin_area/settings/usage_statistics.md @@ -61,13 +61,12 @@ sequenceDiagram ## Usage Ping **(CORE ONLY)** -See [Usage Ping guide](../../../development/product_analytics/usage_ping.md). +See [Usage Ping guide](../../../development/usage_ping.md). -## Instance-level statistics **(CORE ONLY)** +## Instance-level analytics availability After usage ping is enabled, GitLab gathers data from other instances and -can show [usage statistics](../analytics/index.md) -of your instance to your admins in **Admin Area > Analytics**. +enables certain [instance-level analytics features](../analytics/index.md) that are dependent on usage ping. <!-- ## Troubleshooting diff --git a/doc/user/admin_area/settings/user_and_ip_rate_limits.md b/doc/user/admin_area/settings/user_and_ip_rate_limits.md index 3f0d75dc682..e2040ef19d6 100644 --- a/doc/user/admin_area/settings/user_and_ip_rate_limits.md +++ b/doc/user/admin_area/settings/user_and_ip_rate_limits.md @@ -20,8 +20,42 @@ IP rate limits**: These limits are disabled by default. +NOTE: +By default, all Git operations are first tried unauthenticated. Because of this, HTTP Git operations +may trigger the rate limits configured for unauthenticated requests. + ![user-and-ip-rate-limits](img/user_and_ip_rate_limits.png) +## Response text + +A request that exceeds a rate limit returns a 429 response code and a +plain-text body, which by default is: + +```plaintext +Retry later +``` + +It is possible to customize this response text in the Admin Area. + +## Response headers + +> [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/731) in GitLab 13.8, the `Rate-Limit` headers. `Retry-After` was introduced in an earlier version. + +When a client exceeds the associated rate limit, the following requests are +blocked. The server may respond with rate-limiting information allowing the +requester to retry after a specific period of time. These information are +attached into the response headers. + +| Header | Example | Description | +|:----------------------|:--------------------------------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| `RateLimit-Limit` | `60` | The request quota for the client **each minute**. If the rate limit period set in the admin area is different from 1 minute, the value of this header is adjusted to approximately the nearest 60-minute period. | +| `RateLimit-Name` | `throttle_authenticated_web` | Name of the throttle blocking the requests. | +| `RateLimit-Observed` | `67` | Number of requests associated to the client in the time window. | +| `RateLimit-Remaining` | `0` | Remaining quota in the time window. The result of `RateLimit-Limit` - `RateLimit-Remaining`. | +| `RateLimit-Reset` | `1609844400` | [Unix time](https://en.wikipedia.org/wiki/Unix_time)-formatted time when the request quota is reset. | +| `RateLimit-ResetTime` | `Tue, 05 Jan 2021 11:00:00 GMT` | [RFC2616](https://tools.ietf.org/html/rfc2616#section-3.3.1)-formatted date and time when the request quota is reset. | +| `Retry-After` | `30` | Remaining duration **in seconds** until the quota is reset. This is a [standard HTTP header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After). | + ## Use an HTTP header to bypass rate limiting > [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/622) in GitLab 13.6. @@ -47,7 +81,7 @@ GitLab. For example: in `/etc/default/gitlab`. It is important that your load balancer erases or overwrites the bypass -header on all incoming traffic, because otherwise you must trust your +header on all incoming traffic. Otherwise, you must trust your users to not set that header and bypass the GitLab rate limiter. Note that the bypass only works if the header is set to `1`. @@ -59,7 +93,9 @@ are marked with `"throttle_safelist":"throttle_bypass_header"` in To disable the bypass mechanism, make sure the environment variable `GITLAB_THROTTLE_BYPASS_HEADER` is unset or empty. -## Allowing specific users to bypass authenticated request rate limiting +## Allow specific users to bypass authenticated request rate limiting + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49127) in GitLab 13.7. Similarly to the bypass header described above, it is possible to allow a certain set of users to bypass the rate limiter. This only applies @@ -82,13 +118,12 @@ are marked with `"throttle_safelist":"throttle_user_allowlist"` in At application startup, the allowlist is logged in [`auth.log`](../../../administration/logs.md#authlog). -## Trying out throttling settings before enforcing them +## Try out throttling settings before enforcing them > [Introduced](https://gitlab.com/gitlab-com/gl-infra/scalability/-/issues/629) in GitLab 13.6. -Trying out throttling settings can be done by setting the -`GITLAB_THROTTLE_DRY_RUN` environment variable to a comma-separated -list of throttle names. +You can try out throttling settings by setting the `GITLAB_THROTTLE_DRY_RUN` environment variable to +a comma-separated list of throttle names. The possible names are: @@ -99,21 +134,19 @@ The possible names are: - `throttle_authenticated_protected_paths_api` - `throttle_authenticated_protected_paths_web` -For example: trying out throttles for all authenticated requests to -non-protected paths could be done by setting +For example, to try out throttles for all authenticated requests to +non-protected paths can be done by setting `GITLAB_THROTTLE_DRY_RUN='throttle_authenticated_web,throttle_authenticated_api'`. -To enable the dry-run mode for all throttles, the variable can be set -to `*`. +To enable dry run mode for all throttles, the variable can be set to `*`. -Setting a throttle to dry-run mode will log a message to the -[`auth.log`](../../../administration/logs.md#authlog) when it would -hit the limit, while letting the request continue as normal. The log -message will contain an `env` field set to `track`. The `matched` -field will contain the name of throttle that was hit. +Setting a throttle to dry run mode logs a message to the +[`auth.log`](../../../administration/logs.md#authlog) when it would hit the limit, while letting the +request continue as normal. The log message contains an `env` field set to `track`. The `matched` +field contains the name of throttle that was hit. It is important to set the environment variable **before** enabling -the rate limiting in the settings. The settings in the admin panel +the rate limiting in the settings. The settings in the Admin Area take effect immediately, while setting the environment variable requires a restart of all the Puma processes. diff --git a/doc/user/analytics/ci_cd_analytics.md b/doc/user/analytics/ci_cd_analytics.md new file mode 100644 index 00000000000..beb2cbfdc58 --- /dev/null +++ b/doc/user/analytics/ci_cd_analytics.md @@ -0,0 +1,33 @@ +--- +stage: Release +group: Release +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# CI/CD Analytics + +## Pipeline success and duration charts **(CORE)** + +> - Introduced in GitLab 3.1.1 as Commit Stats, and later renamed to Pipeline Charts. +> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/38318) to CI/CD Analytics in GitLab 12.8. + +GitLab tracks the history of your pipeline successes and failures, as well as how long each pipeline +ran. To view this information, go to **Analytics > CI/CD Analytics**. + +View successful pipelines: + +![Successful pipelines](img/pipelines_success_chart.png) + +View pipeline duration history: + +![Pipeline duration](img/pipelines_duration_chart.png) + +## Deployment frequency charts **(ULTIMATE)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/275991) in GitLab 13.8. + +The **Analytics > CI/CD Analytics** page shows information about the deployment frequency to the +`production` environment. The environment **must** be named `production` for its deployment +information to appear on the graphs. + +![Deployment frequency](img/deployment_frequency_chart_v13_8.png) diff --git a/doc/user/analytics/img/deployment_frequency_chart_v13_8.png b/doc/user/analytics/img/deployment_frequency_chart_v13_8.png Binary files differnew file mode 100644 index 00000000000..40dd2fa0321 --- /dev/null +++ b/doc/user/analytics/img/deployment_frequency_chart_v13_8.png diff --git a/doc/ci/pipelines/img/pipelines_duration_chart.png b/doc/user/analytics/img/pipelines_duration_chart.png Binary files differindex 12ec262dadb..12ec262dadb 100644 --- a/doc/ci/pipelines/img/pipelines_duration_chart.png +++ b/doc/user/analytics/img/pipelines_duration_chart.png diff --git a/doc/ci/pipelines/img/pipelines_success_chart.png b/doc/user/analytics/img/pipelines_success_chart.png Binary files differindex f44dc25ff1c..f44dc25ff1c 100644 --- a/doc/ci/pipelines/img/pipelines_success_chart.png +++ b/doc/user/analytics/img/pipelines_success_chart.png diff --git a/doc/user/analytics/index.md b/doc/user/analytics/index.md index adfd09d8526..caa8972b220 100644 --- a/doc/user/analytics/index.md +++ b/doc/user/analytics/index.md @@ -33,7 +33,7 @@ The following analytics features are available at the group level: The following analytics features are available at the project level: -- [CI/CD](../../ci/pipelines/index.md#pipeline-success-and-duration-charts). **(STARTER)** +- [CI/CD](ci_cd_analytics.md). **(CORE)** - [Code Review](code_review_analytics.md). **(STARTER)** - [Insights](../project/insights/index.md). **(ULTIMATE)** - [Issue](../group/issues_analytics/index.md). **(PREMIUM)** diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md index 09e38d5048f..674afcb29ee 100644 --- a/doc/user/application_security/api_fuzzing/index.md +++ b/doc/user/application_security/api_fuzzing/index.md @@ -157,6 +157,7 @@ You can use various tools to generate HAR files: - [Insomnia Core](https://insomnia.rest/): API client - [Chrome](https://www.google.com/chrome/): Browser - [Firefox](https://www.mozilla.org/en-US/firefox/): Browser +- [GitLab HAR Recorder](https://gitlab.com/gitlab-org/security-products/har-recorder): Command line WARNING: HAR files may contain sensitive information such as authentication tokens, API keys, and session diff --git a/doc/user/application_security/coverage_fuzzing/index.md b/doc/user/application_security/coverage_fuzzing/index.md index 0a5a0c3a565..469945246c1 100644 --- a/doc/user/application_security/coverage_fuzzing/index.md +++ b/doc/user/application_security/coverage_fuzzing/index.md @@ -29,8 +29,10 @@ Docker image with the fuzz engine to run your app. | GoLang | [go-fuzz (libFuzzer support)](https://github.com/dvyukov/go-fuzz) | [go-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/go-fuzzing-example) | | Swift | [libfuzzer](https://github.com/apple/swift/blob/master/docs/libFuzzerIntegration.md) | [swift-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/swift-fuzzing-example) | | Rust | [cargo-fuzz (libFuzzer support)](https://github.com/rust-fuzz/cargo-fuzz) | [rust-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/rust-fuzzing-example) | -| Java | [JQF](https://github.com/rohanpadhye/JQF) | [java-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/java-fuzzing-example) | | Java | [javafuzz](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/javafuzz) (recommended) | [javafuzz-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/javafuzz-fuzzing-example) | +| Java | [JQF](https://github.com/rohanpadhye/JQF) (not preferred) | [jqf-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/java-fuzzing-example) | +| JavaScript | [jsfuzz](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/jsfuzz)| [jsfuzz-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/jsfuzz-fuzzing-example) | +| Python | [pythonfuzz](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/pythonfuzz)| [pythonfuzz-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/pythonfuzz-fuzzing-example) | ## Configuration diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md index f4401fa6445..395a8702d1b 100644 --- a/doc/user/application_security/dast/index.md +++ b/doc/user/application_security/dast/index.md @@ -86,6 +86,20 @@ variables: DAST_WEBSITE: https://example.com ``` +### Latest template + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/254325) in GitLab 13.8 + +To use the latest version of the DAST template, include +`DAST.latest.gitlab-ci.yml` instead of `DAST.gitlab-ci.yml`. +See the CI [docs](../../../development/cicd/templates.md#latest-version) +on template versioning for more information. + +Please note that the latest version may include breaking changes. Check the +[DAST troubleshooting guide](#troubleshooting) if you experience problems. + +### Template options + There are two ways to define the URL to be scanned by DAST: 1. Set the `DAST_WEBSITE` [variable](../../../ci/yaml/README.md#variables). @@ -183,6 +197,10 @@ To create masked variables for the username and password, see [Create a custom v Note that the key of the username variable must be `DAST_USERNAME` and the key of the password variable must be `DAST_PASSWORD`. +After DAST has authenticated with the application, all cookies are collected from the web browser. +For each cookie a matching session token is created for use by ZAP. This ensures ZAP is recognized +by the application as correctly authenticated. + Other variables that are related to authenticated scans are: ```yaml @@ -196,7 +214,8 @@ variables: DAST_PASSWORD_FIELD: session[password] # the name of password field at the sign-in HTML form DAST_SUBMIT_FIELD: login # the `id` or `name` of the element that when clicked will submit the login form or the password form of a multi-page login process DAST_FIRST_SUBMIT_FIELD: next # the `id` or `name` of the element that when clicked will submit the username form of a multi-page login process - DAST_AUTH_EXCLUDE_URLS: http://example.com/sign-out,http://example.com/sign-out-2 # optional, URLs to skip during the authenticated scan; comma-separated, no spaces in between + DAST_EXCLUDE_URLS: http://example.com/sign-out,http://example.com/sign-out-2 # optional, URLs to skip during the authenticated scan; comma-separated, no spaces in between + DAST_AUTH_VALIDATION_URL: http://example.com/loggedin_page # optional, a URL only accessible to logged in users that DAST can use to confirm successful authentication ``` The results are saved as a @@ -544,12 +563,14 @@ DAST can be [configured](#customizing-the-dast-settings) using environment varia | `DAST_API_SPECIFICATION` | URL or string | The API specification to import. The specification can be hosted at a URL, or the name of a file present in the `/zap/wrk` directory. `DAST_WEBSITE` must be specified if this is omitted. | | `DAST_SPIDER_START_AT_HOST` | boolean | Set to `false` to prevent DAST from resetting the target to its host before scanning. When `true`, non-host targets `http://test.site/some_path` is reset to `http://test.site` before scan. Default: `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/258805) in GitLab 13.6. | | `DAST_AUTH_URL` | URL | The URL of the page containing the sign-in HTML form on the target website. `DAST_USERNAME` and `DAST_PASSWORD` are submitted with the login form to create an authenticated scan. Not supported for API scans. | +| `DAST_AUTH_VALIDATION_URL` | URL | A URL only accessible to logged in users that DAST can use to confirm successful authentication. If provided, DAST will exit if it cannot access the URL. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/207335) in GitLab 13.8. | `DAST_USERNAME` | string | The username to authenticate to in the website. | | `DAST_PASSWORD` | string | The password to authenticate to in the website. | | `DAST_USERNAME_FIELD` | string | The name of username field at the sign-in HTML form. | | `DAST_PASSWORD_FIELD` | string | The name of password field at the sign-in HTML form. | +| `DAST_SKIP_TARGET_CHECK` | boolean | Set to `true` to prevent DAST from checking that the target is available before scanning. Default: `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/229067) in GitLab 13.8. | | `DAST_MASK_HTTP_HEADERS` | string | Comma-separated list of request and response headers to be masked (GitLab 13.1). Must contain **all** headers to be masked. Refer to [list of headers that are masked by default](#hide-sensitive-information). | -| `DAST_AUTH_EXCLUDE_URLS` | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. | +| `DAST_EXCLUDE_URLS` | URLs | The URLs to skip during the authenticated scan; comma-separated. Regular expression syntax can be used to match multiple URLs. For example, `.*` matches an arbitrary character sequence. Not supported for API scans. In [GitLab 13.7 and earlier](https://gitlab.com/gitlab-org/security-products/dast/-/merge_requests/367), was `DAST_AUTH_EXCLUDE_URLS` (which we plan to support until GitLab 14.0). | | `DAST_FULL_SCAN_ENABLED` | boolean | Set to `true` to run a [ZAP Full Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Full-Scan) instead of a [ZAP Baseline Scan](https://github.com/zaproxy/zaproxy/wiki/ZAP-Baseline-Scan). Default: `false` | | `DAST_FULL_SCAN_DOMAIN_VALIDATION_REQUIRED` | boolean | Set to `true` to require [domain validation](#domain-validation) when running DAST full scans. Not supported for API scans. Default: `false` | | `DAST_AUTO_UPDATE_ADDONS` | boolean | ZAP add-ons are pinned to specific versions in the DAST Docker image. Set to `true` to download the latest versions when the scan starts. Default: `false` | @@ -701,6 +722,49 @@ security reports without requiring internet access. Alternatively, you can use the variable `SECURE_ANALYZERS_PREFIX` to override the base registry address of the `dast` image. +## On-demand scans + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) in GitLab 13.2. +> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) in GitLab 13.3. + +An on-demand DAST scan runs outside the DevOps life cycle. Changes in your repository don't trigger +the scan. You must start it manually. + +An on-demand DAST scan: + +- Uses settings in the site profile and scanner profile you select when you run the scan, + instead of those in the `.gitlab-ci.yml` file. +- Is associated with your project's default branch. + +### On-demand scan modes + +An on-demand scan can be run in active or passive mode: + +- _Passive mode_ is the default and runs a ZAP Baseline Scan. +- _Active mode_ runs a ZAP Full Scan which is potentially harmful to the site being scanned. To + minimize the risk of accidental damage, running an active scan requires a [validated site + profile](#site-profile-validation). + +### Run an on-demand DAST scan + +NOTE: +You must have permission to run an on-demand DAST scan against a protected branch. +The default branch is automatically protected. For more information, see +[Pipeline security on protected branches](../../../ci/pipelines/index.md#pipeline-security-on-protected-branches). + +To run an on-demand DAST scan, you need: + +- A [scanner profile](#create-a-scanner-profile). +- A [site profile](#create-a-site-profile). +- If you are running an active scan the site profile must be [validated](#validate-a-site-profile). + +1. From your project's home page, go to **Security & Compliance > On-demand Scans** in the left sidebar. +1. In **Scanner profile**, select a scanner profile from the dropdown. +1. In **Site profile**, select a site profile from the dropdown. +1. Click **Run scan**. + +The on-demand DAST scan runs and the project's dashboard shows the results. + ## Site profile A site profile describes the attributes of a web site to scan on demand with DAST. A site profile is @@ -711,31 +775,115 @@ A site profile contains the following: - **Profile name**: A name you assign to the site to be scanned. - **Target URL**: The URL that DAST runs against. +## Site profile validation + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233020) in GitLab 13.8. + +Site profile validation reduces the risk of running an active scan against the wrong website. A site +must be validated before an active scan can run against it. The site validation methods are as +follows: + +- _Text file validation_ requires a text file be uploaded to the target site. The text file is + allocated a name and content that is unique to the project. The validation process checks the + file's content. +- _Header validation_ requires the header `Gitlab-On-Demand-DAST` be added to the target site, + with a value unique to the project. The validation process checks that the header is present, and + checks its value. + +Both methods are equivalent in functionality. Use whichever is feasible. + ### Create a site profile To create a site profile: 1. From your project's home page, go to **Security & Compliance > Configuration**. -1. Click **Manage** in the **DAST Profiles** row. -1. Click **New Profile > Site Profile**. -1. Type in a unique **Profile name** and **Target URL** then click **Save profile**. +1. Select **Manage** in the **DAST Profiles** row. +1. Select **New Profile > Site Profile**. +1. Type in a unique **Profile name** and **Target URL** then select **Save profile**. ### Edit a site profile To edit an existing site profile: 1. From your project's home page, go to **Security & Compliance > Configuration**. -1. Click **Manage** in the **DAST Profiles** row. -1. Click **Edit** in the row of the profile to edit. -1. Edit the **Profile name** and **Target URL**, then click **Save profile**. +1. Select **Manage** in the **DAST Profiles** row. +1. Select **Edit** in the row of the profile to edit. +1. Edit the **Profile name** and **Target URL**, then select **Save profile**. ### Delete a site profile To delete an existing site profile: 1. From your project's home page, go to **Security & Compliance > Configuration**. -1. Click **Manage** in the **DAST Profiles** row. -1. Click **{remove}** (Delete profile) in the row of the profile to delete. +1. Select **Manage** in the **DAST Profiles** row. +1. Select **{remove}** (Delete profile) in the row of the profile to delete. + +### Validate a site profile + +To validate a site profile: + +1. From your project's home page, go to **Security & Compliance > Configuration**. +1. Select **Manage** in the **DAST Profiles** row. +1. Select **Validate target site** beside the profile to validate. +1. Select the validation method. + 1. For **Text file validation**: + 1. Download the validation file listed in **Step 2**. + 1. Upload the validation file to the host. You can upload the file to the location in + **Step 3** or any location you prefer. + 1. Select **Validate**. + 1. For **Header validation**: + 1. Select the clipboard icon in **Step 2**. + 1. Edit the header of the site to validate, and paste the clipboard content. + 1. Select the input field in **Step 3** and enter the location of the header. + 1. Select **Validate**. + +The site is validated and an active scan can run against it. + +If a validated site profile's target URL is edited, the site is no longer validated. + +#### Validated site profile headers + +The following are code samples of how you could provide the required site profile header in your +application. + +##### Ruby on Rails example for on-demand scan + +Here's how you can add a custom header in a Ruby on Rails application: + +```ruby +class DastWebsiteTargetController < ActionController::Base + def dast_website_target + response.headers['Gitlab-On-Demand-DAST'] = '0dd79c9a-7b29-4e26-a815-eaaf53fcab1c' + head :ok + end +end +``` + +##### Django example for on-demand scan + +Here's how you can add a +[custom header in Django](https://docs.djangoproject.com/en/2.2/ref/request-response/#setting-header-fields): + +```python +class DastWebsiteTargetView(View): + def head(self, *args, **kwargs): + response = HttpResponse() + response['Gitlab-On-Demand-DAST'] = '0dd79c9a-7b29-4e26-a815-eaaf53fcab1c' + + return response +``` + +##### Node (with Express) example for on-demand scan + +Here's how you can add a +[custom header in Node (with Express)](http://expressjs.com/en/5x/api.html#res.append): + +```javascript +app.get('/dast-website-target', function(req, res) { + res.append('Gitlab-On-Demand-DAST', '0dd79c9a-7b29-4e26-a815-eaaf53fcab1c') + res.send('Respond to DAST ping') +}) +``` ## Scanner profile @@ -779,40 +927,6 @@ To delete a scanner profile: 1. Click **Manage** in the **DAST Profiles** row. 1. Click **{remove}** (Delete profile) in the scanner profile's row. -## On-demand scans - -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) in GitLab 13.2. -> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/218465) in GitLab 13.3. - -An on-demand DAST scan runs outside the DevOps life cycle. Changes in your repository don't trigger -the scan. You must start it manually. - -An on-demand DAST scan: - -- Uses settings in the site profile and scanner profile you select when you run the scan, - instead of those in the `.gitlab-ci.yml` file. -- Is associated with your project's default branch. - -### Run an on-demand DAST scan - -NOTE: -You must have permission to run an on-demand DAST scan against a protected branch. -The default branch is automatically protected. For more information, see -[Pipeline security on protected branches](../../../ci/pipelines/index.md#pipeline-security-on-protected-branches). - -To run an on-demand DAST scan, you need: - -- A [scanner profile](#create-a-scanner-profile). -- A [site profile](#create-a-site-profile). - -1. From your project's home page, go to **Security & Compliance > On-demand Scans** in the left sidebar. -1. Click **Create new DAST scan**. -1. In **Scanner profile**, select a scanner profile from the dropdown. -1. In **Site profile**, select a site profile from the dropdown. -1. Click **Run scan**. - -The on-demand DAST scan runs and the project's dashboard shows the results. - ## Reports The DAST tool outputs a report file in JSON format by default. However, this tool can also generate reports in @@ -940,6 +1054,25 @@ If your DAST job exceeds the job timeout and you need to reduce the scan duratio For information on this, see the [general Application Security troubleshooting section](../../../ci/pipelines/job_artifacts.md#error-message-no-files-to-upload). +### Getting error `dast job: chosen stage does not exist` when including DAST CI template + +Newer versions of the DAST CI template do not define stages in order to avoid +overwriting stages from other CI files. If you've recently started using +`DAST.latest.gitlab-ci.yml` or upgraded to a new major release of GitLab and +began receiving this error, you will need to define a `dast` stage with your +other stages. Please note that you must have a running application for DAST to +scan. If your application is set up in your pipeline, it must be deployed + in a stage _before_ the `dast` stage: + +```yaml +stages: + - deploy # DAST needs a running application to scan + - dast + +include: + - template: DAST.latest.gitlab-ci.yml +``` + <!-- ## Troubleshooting Include any troubleshooting steps that you can foresee. If you know beforehand what issues diff --git a/doc/user/application_security/dependency_scanning/index.md b/doc/user/application_security/dependency_scanning/index.md index 07774f51958..cecf818edfc 100644 --- a/doc/user/application_security/dependency_scanning/index.md +++ b/doc/user/application_security/dependency_scanning/index.md @@ -64,16 +64,19 @@ The following languages and dependency managers are supported: | [Conan](https://conan.io/) | C, C++ | [`conan.lock`](https://docs.conan.io/en/latest/versioning/lockfiles.html) | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | | [Golang](https://golang.org/) | Go | `go.sum` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | | [Gradle](https://gradle.org/), [Maven](https://maven.apache.org/) | Java | `build.gradle`, `build.gradle.kts`, `pom.xml` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | -| [npm](https://www.npmjs.com/), [yarn](https://classic.yarnpkg.com/en/) 1.x | JavaScript | `package-lock.json`, `npm-shrinkwrap.json`, `yarn.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium), [Retire.js](https://retirejs.github.io/retire.js/) | +| [npm](https://www.npmjs.com/), [yarn](https://classic.yarnpkg.com/en/) 1.x | JavaScript | `package-lock.json`, `npm-shrinkwrap.json`, `yarn.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | +| [npm](https://www.npmjs.com/), [yarn](https://classic.yarnpkg.com/en/) 1.x | JavaScript | `package.json` | [Retire.js](https://retirejs.github.io/retire.js/) | | [NuGet](https://www.nuget.org/) 4.9+ | .NET, C# | [`packages.lock.json`](https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#enabling-lock-file) | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | -| [setuptools](https://setuptools.readthedocs.io/en/latest/), [pip](https://pip.pypa.io/en/stable/), [Pipenv](https://pipenv.pypa.io/en/latest/) | Python | `setup.py`, `requirements.txt`, `requirements.pip`, `requires.txt`, `Pipfile` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | +| [setuptools](https://setuptools.readthedocs.io/en/latest/), [pip](https://pip.pypa.io/en/stable/), [Pipenv](https://pipenv.pypa.io/en/latest/) (*1*) | Python | `setup.py`, `requirements.txt`, `requirements.pip`, `requires.txt`, `Pipfile`, `Pipfile.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | | [sbt](https://www.scala-sbt.org/) 1.2 and below ([Ivy](http://ant.apache.org/ivy/)) | Scala | `build.sbt` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | +1. [Pipenv](https://pipenv.pypa.io/en/latest/) projects are scanned when a `Pipfile` is present. + Gemnasium scans the exact package versions listed in `Pipfile.lock` when this file is also present. + Plans are underway for supporting the following languages, dependency managers, and dependency files. For details, see the issue link for each. | Package Managers | Languages | Supported files | Scan tools | Issue | | ------------------- | --------- | --------------- | ---------- | ----- | -| [Pipenv](https://pipenv.pypa.io/en/latest/) | Python | `Pipfile.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#11756](https://gitlab.com/gitlab-org/gitlab/-/issues/11756) | | [Poetry](https://python-poetry.org/) | Python | `poetry.lock` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#7006](https://gitlab.com/gitlab-org/gitlab/-/issues/7006) | | [sbt](https://www.scala-sbt.org/) 1.3+ ([Coursier](https://get-coursier.io/))| Scala | `build.sbt` | [Gemnasium](https://gitlab.com/gitlab-org/security-products/gemnasium) | [GitLab#271345](https://gitlab.com/gitlab-org/gitlab/-/issues/271345) | @@ -115,7 +118,7 @@ include: - template: Dependency-Scanning.gitlab-ci.yml variables: - DS_PYTHON_VERSION: 2 + SECURE_LOG_LEVEL: error ``` Because template is [evaluated before](../../../ci/yaml/README.md#include) the pipeline @@ -489,7 +492,7 @@ ensure that it can reach your private repository. Here is an example configurati ### Referencing local dependencies using a path in JavaScript projects The [Retire.js](https://gitlab.com/gitlab-org/security-products/analyzers/retire.js) analyzer -doesn't support dependency references made with [local paths](https://docs.npmjs.com/files/package.json#local-paths) +doesn't support dependency references made with [local paths](https://docs.npmjs.com/cli/v6/configuring-npm/package-json#local-paths) in the `package.json` of JavaScript projects. The dependency scan outputs the following error for such references: @@ -504,7 +507,7 @@ As a workaround, remove the [`retire.js`](analyzers.md#selecting-specific-analyz ### `Error response from daemon: error processing tar file: docker-tar: relocation error` -This error occurs when the Docker version that runs the dependency scanning job is `19.03.00`. +This error occurs when the Docker version that runs the dependency scanning job is `19.03.0`. Consider updating to Docker `19.03.1` or greater. Older versions are not affected. Read more in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/13830#note_211354992 "Current SAST container fails"). diff --git a/doc/user/application_security/sast/analyzers.md b/doc/user/application_security/sast/analyzers.md index 15412473ab1..1f0b461c91b 100644 --- a/doc/user/application_security/sast/analyzers.md +++ b/doc/user/application_security/sast/analyzers.md @@ -68,6 +68,10 @@ the official analyzers. ### Selecting specific analyzers +WARNING: +`SAST_DEFAULT_ANALYZERS` is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50872) in GitLab 13.8, +and is scheduled for [removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/290777). + You can select the official analyzers you want to run. Here's how to enable `bandit` and `flawfinder` while disabling all the other default ones. In `.gitlab-ci.yml` define: @@ -83,9 +87,9 @@ variables: `bandit` runs first. When merging the reports, SAST removes the duplicates and keeps the `bandit` entries. -### Disabling default analyzers +### Disabling all default analyzers -Setting `SAST_DEFAULT_ANALYZERS` to an empty string disables all the official +Setting `SAST_DISABLED` to `true` disables all the official default analyzers. In `.gitlab-ci.yml` define: ```yaml @@ -93,11 +97,25 @@ include: - template: Security/SAST.gitlab-ci.yml variables: - SAST_DEFAULT_ANALYZERS: "" + SAST_DISABLED: true ``` That's needed when one totally relies on [custom analyzers](#custom-analyzers). +### Disabling specific default analyzers + +Set `SAST_EXCLUDED_ANALYZERS` to a comma-delimited string that includes the official +default analyzers that you want to avoid running. In `.gitlab-ci.yml` define the +following to prevent the `eslint` analyzer from running: + +```yaml +include: + - template: Security/SAST.gitlab-ci.yml + +variables: + SAST_EXCLUDED_ANALYZERS: "eslint" +``` + ## Custom Analyzers You can provide your own analyzers by diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md index fb3bc256e11..59887c95c67 100644 --- a/doc/user/application_security/sast/index.md +++ b/doc/user/application_security/sast/index.md @@ -431,7 +431,8 @@ The following are Docker image-related variables. |---------------------------|---------------------------------------------------------------------------------------------------------------------------------------| | `SECURE_ANALYZERS_PREFIX` | Override the name of the Docker registry providing the default images (proxy). Read more about [customizing analyzers](analyzers.md). | | `SAST_ANALYZER_IMAGE_TAG` | **DEPRECATED:** Override the Docker tag of the default images. Read more about [customizing analyzers](analyzers.md). | -| `SAST_DEFAULT_ANALYZERS` | Override the names of default images. Read more about [customizing analyzers](analyzers.md). | +| `SAST_DEFAULT_ANALYZERS` | **DEPRECATED:** Override the names of default images. Scheduled for [removal in GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/issues/290777). | +| `SAST_EXCLUDED_ANALYZERS` | Names of default images that should never run. Read more about [customizing analyzers](analyzers.md). | #### Vulnerability filters @@ -511,7 +512,7 @@ The SAST tool emits a JSON report file. For more information, see the [schema for this report](https://gitlab.com/gitlab-org/security-products/security-report-schemas/-/blob/master/dist/sast-report-format.json). The JSON report file can be downloaded from the CI pipelines page, or the -pipelines tab on merge requests. For more information see [Downloading artifacts](../../../ci/pipelines/job_artifacts.md). +pipelines tab on merge requests by [setting `artifacts: paths`](../../../ci/pipelines/job_artifacts.md#defining-artifacts-in-gitlab-ciyml) to `gl-sast-report.json`. For more information see [Downloading artifacts](../../../ci/pipelines/job_artifacts.md). Here's an example SAST report: @@ -727,3 +728,25 @@ against the given glob pattern. If the number of matches exceeds the maximum, th parameter returns `true`. Depending on the number of files in your repository, a SAST job might be triggered even if the scanner doesn't support your project. For more details about this issue, see the [`rules:exists` documentation](../../../ci/yaml/README.md#rulesexists). + +### SpotBugs UTF-8 unmappable character errors + +These errors occur when UTF-8 encoding isn't enabled on a SpotBugs build and there are UTF-8 +characters in the source code. To fix this error, enable UTF-8 for your project's build tool. + +For Gradle builds, add the following to your `build.gradle` file: + +```gradle +compileJava.options.encoding = 'UTF-8' +tasks.withType(JavaCompile) { + options.encoding = 'UTF-8' +} +``` + +For Maven builds, add the following to your `pom.xml` file: + +```xml +<properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> +</properties> +``` diff --git a/doc/user/application_security/secret_detection/index.md b/doc/user/application_security/secret_detection/index.md index 8f57e2c5535..0ae038924ec 100644 --- a/doc/user/application_security/secret_detection/index.md +++ b/doc/user/application_security/secret_detection/index.md @@ -53,6 +53,7 @@ The [default ruleset provided by Gitleaks](https://gitlab.com/gitlab-org/securit - Twitter API - Cloud SaaS vendors: - GitHub API + - Shopify API - Slack Token - Slack Webhook - Stripe API diff --git a/doc/user/application_security/security_dashboard/img/vulnerability_details_create_issue_v13_7.png b/doc/user/application_security/security_dashboard/img/vulnerability_details_create_issue_v13_7.png Binary files differindex b9b228c9430..5184ad85fa9 100644 --- a/doc/user/application_security/security_dashboard/img/vulnerability_details_create_issue_v13_7.png +++ b/doc/user/application_security/security_dashboard/img/vulnerability_details_create_issue_v13_7.png diff --git a/doc/user/application_security/security_dashboard/index.md b/doc/user/application_security/security_dashboard/index.md index 2750aa81872..10bf6202a92 100644 --- a/doc/user/application_security/security_dashboard/index.md +++ b/doc/user/application_security/security_dashboard/index.md @@ -92,7 +92,8 @@ the **Failed jobs** tab of the pipeline page. The Vulnerability Report next displays the total number of vulnerabilities by severity (for example, Critical, High, Medium, Low, Info, Unknown). Below this, a table shows each vulnerability's status, severity, -and description. Clicking a vulnerability takes you to its [Vulnerability Details](../vulnerabilities) +description and if there is a Merge Request related to it. Clicking a vulnerability takes you to its +[Vulnerability Details](../vulnerabilities) page to view more information about that vulnerability. ![Project Vulnerability Report](img/project_security_dashboard_v13_5.png) diff --git a/doc/user/application_security/vulnerabilities/severities.md b/doc/user/application_security/vulnerabilities/severities.md new file mode 100644 index 00000000000..ce2297f7a1a --- /dev/null +++ b/doc/user/application_security/vulnerabilities/severities.md @@ -0,0 +1,70 @@ +--- +type: reference +stage: Secure +group: Threat Insights +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Vulnerability severity levels + +GitLab vulnerability analyzers attempt to return vulnerability severity level values whenever +possible. The following is a list of available GitLab vulnerability severity levels, ranked from +most to least severe: + +- `Critical` +- `High` +- `Medium` +- `Low` +- `Info` +- `Unknown` + +Most GitLab vulnerability analyzers are wrappers around popular open source scanning tools. Each +open source scanning tool provides their own native vulnerability severity level value. These values +can be one of the following: + +| Native vulnerability severity level type | Examples | +|-----------------------------------------------------------------------------------------------------------------------------------|------------------------------------------------| +| String | `WARNING`, `ERROR`, `Critical`, `Negligible` | +| Integer | `1`, `2`, `5` | +| [CVSS v2.0 Rating](https://nvd.nist.gov/vuln-metrics/cvss) | `(AV:N/AC:L/Au:S/C:P/I:P/A:N)` | +| [CVSS v3.1 Qualitative Severity Rating](https://www.first.org/cvss/v3.1/specification-document#Qualitative-Severity-Rating-Scale) | `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H` | + +To provide consistent vulnerability severity level values, the GitLab vulnerability analyzers +convert from the above values to a standardized GitLab vulnerability severity level, as outlined in +the following tables: + +## SAST + +| GitLab analyzer | Outputs severity levels? | Native severity level type | Native severity level example | +|--------------------------------------------------------------------------------------------------------|--------------------------|----------------------------|------------------------------------| +| [security-code-scan](https://gitlab.com/gitlab-org/security-products/analyzers/security-code-scan) | **{dotted-circle}** No | N/A | N/A | +| [brakeman](https://gitlab.com/gitlab-org/security-products/analyzers/brakeman) | **{dotted-circle}** No | N/A | N/A | +| [sobelow](https://gitlab.com/gitlab-org/security-products/analyzers/sobelow) | **{check-circle}** Yes | N/A | Hardcodes all severity levels to `Unknown` | +| [nodejs-scan](https://gitlab.com/gitlab-org/security-products/analyzers/nodejs-scan) | **{check-circle}** Yes | String | `INFO`, `WARNING`, `ERROR` | +| [flawfinder](https://gitlab.com/gitlab-org/security-products/analyzers/flawfinder) | **{check-circle}** Yes | Integer | `0`, `1`, `2`, `3`, `4`, `5` | +| [eslint](https://gitlab.com/gitlab-org/security-products/analyzers/eslint) | **{check-circle}** Yes | N/A | Hardcodes all severity levels to `Unknown` | +| [SpotBugs](https://gitlab.com/gitlab-org/security-products/analyzers/spotbugs) | **{check-circle}** Yes | Integer | `1`, `2`, `3`, `11`, `12`, `18` | +| [gosec](https://gitlab.com/gitlab-org/security-products/analyzers/gosec) | **{check-circle}** Yes | String | `HIGH`, `MEDIUM`, `LOW` | +| [bandit](https://gitlab.com/gitlab-org/security-products/analyzers/bandit) | **{check-circle}** Yes | String | `HIGH`, `MEDIUM`, `LOW` | +| [phpcs-security-audit](https://gitlab.com/gitlab-org/security-products/analyzers/phpcs-security-audit) | **{check-circle}** Yes | String | `ERROR`, `WARNING` | +| [pmd-apex](https://gitlab.com/gitlab-org/security-products/analyzers/pmd-apex) | **{check-circle}** Yes | Integer | `1`, `2`, `3`, `4`, `5` | +| [kubesec](https://gitlab.com/gitlab-org/security-products/analyzers/kubesec) | **{check-circle}** Yes | String | `CriticalSeverity`, `InfoSeverity` | +| [secrets](https://gitlab.com/gitlab-org/security-products/analyzers/secrets) | **{check-circle}** Yes | N/A | Hardcodes all severity levels to `Critical` | + +## Dependency Scanning + +| GitLab analyzer | Outputs severity levels? | Native severity level type | Native severity level example | +|------------------------------------------------------------------------------------------|------------------------------|----------------------------|-------------------------------------| +| [bundler-audit](https://gitlab.com/gitlab-org/security-products/analyzers/bundler-audit) | **{check-circle}** Yes | String | `low`, `medium`, `high`, `critical` | +| [retire.js](https://gitlab.com/gitlab-org/security-products/analyzers/retire.js) | **{check-circle}** Yes | String | `low`, `medium`, `high`, `critical` | +| [gemnasium](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium) | **{check-circle}** Yes | CVSS v2.0 Rating and CVSS v3.1 Qualitative Severity Rating | `(AV:N/AC:L/Au:S/C:P/I:P/A:N)`, `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H` | + +## Container Scanning + +| GitLab analyzer | Outputs severity levels? | Native severity level type | Native severity level example | +|------------------------------------------------------------------------|--------------------------|----------------------------|--------------------------------------------------------------| +| [klar](https://gitlab.com/gitlab-org/security-products/analyzers/klar) | **{check-circle}** Yes | String | `Negligible`, `Low`, `Medium`, `High`, `Critical`, `Defcon1` | + +## Fuzz Testing + +All fuzz testing results are reported as Unknown. They should be reviewed and triaged manually to find exploitable faults to prioritize for fixing. diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md index 5963485aebc..2c0d9b6c9ce 100644 --- a/doc/user/clusters/agent/index.md +++ b/doc/user/clusters/agent/index.md @@ -20,9 +20,10 @@ tasks in a secure and cloud-native way. It enables: (network address translation). - Pull-based GitOps deployments by leveraging the [GitOps Engine](https://github.com/argoproj/gitops-engine). -- Real-time access to API endpoints within a cluster. +- Real-time access to API endpoints in a cluster. -Many more features are planned. Please [review our roadmap](https://gitlab.com/groups/gitlab-org/-/epics/3329). +Many more features are planned. Please review [our roadmap](https://gitlab.com/groups/gitlab-org/-/epics/3329) +and [our development documentation](../../../development/agent/index.md). ## GitLab Agent GitOps workflow @@ -169,7 +170,7 @@ gitops: GitLab [versions 13.7 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/259669) also supports manifest projects containing multiple directories (or subdirectories) of YAML files. For more information see our -documentation on the [Kubernetes Agent configuration respository](repository.md). +documentation on the [Kubernetes Agent configuration repository](repository.md). ### Create an Agent record in GitLab @@ -266,7 +267,7 @@ example [`resources.yml` file](#example-resourcesyml-file) in the following ways [Support TLS for gRPC communication issue](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/issues/7) for progress updates. - When deploying KAS through the [GitLab chart](https://docs.gitlab.com/charts/), it's possible to customize the `kas-address` for `wss` and `ws` schemes to whatever you need. - Check the [chart's KAS Ingress docs](https://docs.gitlab.com/charts/charts/gitlab/kas/#ingress) + Check the [chart's KAS Ingress documentation](https://docs.gitlab.com/charts/charts/gitlab/kas/#ingress) to learn more about it. - In the near future, Omnibus GitLab intends to provision `gitlab-kas` under a sub-domain by default, instead of the `/-/kubernetes-agent` path. Please follow [this issue](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5784) for details. - If you defined your own secret name, replace `gitlab-agent-token` with your @@ -436,12 +437,9 @@ spec: The following example projects can help you get started with the Kubernetes Agent. -### Simple NGINX deployment - -This basic GitOps example deploys NGINX: - - [Configuration repository](https://gitlab.com/gitlab-org/configure/examples/kubernetes-agent) -- [Manifest repository](https://gitlab.com/gitlab-org/configure/examples/gitops-project) +- This basic GitOps example deploys NGINX: [Manifest repository](https://gitlab.com/gitlab-org/configure/examples/gitops-project) +- [Install GitLab Runner](runner.md) ### Deploying GitLab Runner with the Agent diff --git a/doc/user/clusters/agent/runner.md b/doc/user/clusters/agent/runner.md new file mode 100644 index 00000000000..715b27f951a --- /dev/null +++ b/doc/user/clusters/agent/runner.md @@ -0,0 +1,452 @@ +--- +stage: Configure +group: Configure +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Install GitLab Runner with Kubernetes Agent **(PREMIUM ONLY)** + +These instructions to install the GitLab Runner assume the +[GitLab Kubernetes Agent](index.md) is already configured. + +1. Review the possible [Runner chart YAML values](https://gitlab.com/gitlab-org/charts/gitlab-runner/blob/master/values.yaml) in the Runner chart documentation, + and create a `runner-chart-values.yaml` file with the configuration that fits + your needs, such as: + + ```yaml + # The GitLab Server URL (with protocol) that want to register the runner against + # ref: https://docs.gitlab.com/runner/commands/README.html#gitlab-runner-register + # + gitlabUrl: https://gitlab.my.domain.example.com/ + + # The Registration Token for adding new Runners to the GitLab Server. This must + # be retrieved from your GitLab Instance. + # ref: https://docs.gitlab.com/ce/ci/runners/README.html + # + runnerRegistrationToken: "yrnZW46BrtBFqM7xDzE7dddd" + + # For RBAC support: + rbac: + create: true + + # Run all containers with the privileged flag enabled + # This will allow the docker:dind image to run if you need to run Docker + # commands. Please read the docs before turning this on: + # ref: https://docs.gitlab.com/runner/executors/kubernetes.html#using-dockerdind + runners: + privileged: true + ``` + +1. Create a single manifest file to install the Runner chart with your cluster agent, + replacing `GITLAB GITLAB-RUNNER` with your namespace: + + ```shell + helm template --namespace GITLAB GITLAB-RUNNER -f runner-chart-values.yaml gitlab/gitlab-runner > runner-manifest.yaml + ``` + + An [example file is available](#example-runner-manifest). + +1. Push your `runner-manifest.yaml` to your manifest repository. + +## Example Runner manifest + +```yaml +# This code is an example of a runner manifest looks like. +# Create your own manifest.yaml file to meet your project's needs. + +--- +# Source: gitlab-runner/templates/service-account.yaml +apiVersion: v1 +kind: ServiceAccount +metadata: + annotations: + name: gitlab-runner-gitlab-runner + labels: + app: gitlab-runner-gitlab-runner + chart: gitlab-runner-0.21.1 + release: "gitlab-runner" + heritage: "Helm" +--- +# Source: gitlab-runner/templates/secrets.yaml +apiVersion: v1 +kind: Secret +metadata: + name: "gitlab-runner-gitlab-runner" + labels: + app: gitlab-runner-gitlab-runner + chart: gitlab-runner-0.21.1 + release: "gitlab-runner" + heritage: "Helm" +type: Opaque +data: + runner-registration-token: "FAKE-TOKEN" + runner-token: "" +--- +# Source: gitlab-runner/templates/configmap.yaml +apiVersion: v1 +kind: ConfigMap +metadata: + name: gitlab-runner-gitlab-runner + labels: + app: gitlab-runner-gitlab-runner + chart: gitlab-runner-0.21.1 + release: "gitlab-runner" + heritage: "Helm" +data: + entrypoint: | + #!/bin/bash + set -e + mkdir -p /home/gitlab-runner/.gitlab-runner/ + cp /scripts/config.toml /home/gitlab-runner/.gitlab-runner/ + + # Register the runner + if [[ -f /secrets/accesskey && -f /secrets/secretkey ]]; then + export CACHE_S3_ACCESS_KEY=$(cat /secrets/accesskey) + export CACHE_S3_SECRET_KEY=$(cat /secrets/secretkey) + fi + + if [[ -f /secrets/gcs-applicaton-credentials-file ]]; then + export GOOGLE_APPLICATION_CREDENTIALS="/secrets/gcs-applicaton-credentials-file" + elif [[ -f /secrets/gcs-application-credentials-file ]]; then + export GOOGLE_APPLICATION_CREDENTIALS="/secrets/gcs-application-credentials-file" + else + if [[ -f /secrets/gcs-access-id && -f /secrets/gcs-private-key ]]; then + export CACHE_GCS_ACCESS_ID=$(cat /secrets/gcs-access-id) + # echo -e used to make private key multiline (in google json auth key private key is oneline with \n) + export CACHE_GCS_PRIVATE_KEY=$(echo -e $(cat /secrets/gcs-private-key)) + fi + fi + + if [[ -f /secrets/runner-registration-token ]]; then + export REGISTRATION_TOKEN=$(cat /secrets/runner-registration-token) + fi + + if [[ -f /secrets/runner-token ]]; then + export CI_SERVER_TOKEN=$(cat /secrets/runner-token) + fi + + if ! sh /scripts/register-the-runner; then + exit 1 + fi + + # Run pre-entrypoint-script + if ! bash /scripts/pre-entrypoint-script; then + exit 1 + fi + + # Start the runner + exec /entrypoint run --user=gitlab-runner \ + --working-directory=/home/gitlab-runner + + config.toml: | + concurrent = 10 + check_interval = 30 + log_level = "info" + listen_address = ':9252' + configure: | + set -e + cp /init-secrets/* /secrets + register-the-runner: | + #!/bin/bash + MAX_REGISTER_ATTEMPTS=30 + + for i in $(seq 1 "${MAX_REGISTER_ATTEMPTS}"); do + echo "Registration attempt ${i} of ${MAX_REGISTER_ATTEMPTS}" + /entrypoint register \ + --non-interactive + + retval=$? + + if [ ${retval} = 0 ]; then + break + elif [ ${i} = ${MAX_REGISTER_ATTEMPTS} ]; then + exit 1 + fi + + sleep 5 + done + + exit 0 + + check-live: | + #!/bin/bash + if /usr/bin/pgrep -f .*register-the-runner; then + exit 0 + elif /usr/bin/pgrep gitlab.*runner; then + exit 0 + else + exit 1 + fi + + pre-entrypoint-script: | +--- +# Source: gitlab-runner/templates/role.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: "Role" +metadata: + name: gitlab-runner-gitlab-runner + labels: + app: gitlab-runner-gitlab-runner + chart: gitlab-runner-0.21.1 + release: "gitlab-runner" + heritage: "Helm" +rules: +- apiGroups: [""] + resources: ["*"] + verbs: ["*"] +--- +# Source: gitlab-runner/templates/role-binding.yaml +apiVersion: rbac.authorization.k8s.io/v1 +kind: "RoleBinding" +metadata: + name: gitlab-runner-gitlab-runner + labels: + app: gitlab-runner-gitlab-runner + chart: gitlab-runner-0.21.1 + release: "gitlab-runner" + heritage: "Helm" +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: "Role" + name: gitlab-runner-gitlab-runner +subjects: +- kind: ServiceAccount + name: gitlab-runner-gitlab-runner + namespace: "gitlab" +--- +# Source: gitlab-runner/templates/deployment.yaml +apiVersion: apps/v1 +kind: Deployment +metadata: + name: gitlab-runner-gitlab-runner + labels: + app: gitlab-runner-gitlab-runner + chart: gitlab-runner-0.21.1 + release: "gitlab-runner" + heritage: "Helm" +spec: + replicas: 1 + selector: + matchLabels: + app: gitlab-runner-gitlab-runner + template: + metadata: + labels: + app: gitlab-runner-gitlab-runner + chart: gitlab-runner-0.21.1 + release: "gitlab-runner" + heritage: "Helm" + annotations: + checksum/configmap: a6623303f6fcc3a043e87ea937bb8399d2d0068a901aa9c3419ed5c7a5afa9db + checksum/secrets: 32c7d2c16918961b7b84a005680f748e774f61c6f4e4da30650d400d781bbb30 + prometheus.io/scrape: 'true' + prometheus.io/port: '9252' + spec: + securityContext: + runAsUser: 100 + fsGroup: 65533 + terminationGracePeriodSeconds: 3600 + initContainers: + - name: configure + command: ['sh', '/config/configure'] + image: gitlab/gitlab-runner:alpine-v13.4.1 + imagePullPolicy: "IfNotPresent" + env: + + - name: CI_SERVER_URL + value: "https://gitlab.qa.joaocunha.eu/" + - name: CLONE_URL + value: "" + - name: RUNNER_REQUEST_CONCURRENCY + value: "1" + - name: RUNNER_EXECUTOR + value: "kubernetes" + - name: REGISTER_LOCKED + value: "true" + - name: RUNNER_TAG_LIST + value: "" + - name: RUNNER_OUTPUT_LIMIT + value: "4096" + - name: KUBERNETES_IMAGE + value: "ubuntu:16.04" + + - name: KUBERNETES_PRIVILEGED + value: "true" + + - name: KUBERNETES_NAMESPACE + value: "gitlab" + - name: KUBERNETES_POLL_TIMEOUT + value: "180" + - name: KUBERNETES_CPU_LIMIT + value: "" + - name: KUBERNETES_CPU_LIMIT_OVERWRITE_MAX_ALLOWED + value: "" + - name: KUBERNETES_MEMORY_LIMIT + value: "" + - name: KUBERNETES_MEMORY_LIMIT_OVERWRITE_MAX_ALLOWED + value: "" + - name: KUBERNETES_CPU_REQUEST + value: "" + - name: KUBERNETES_CPU_REQUEST_OVERWRITE_MAX_ALLOWED + value: "" + - name: KUBERNETES_MEMORY_REQUEST + value: "" + - name: KUBERNETES_MEMORY_REQUEST_OVERWRITE_MAX_ALLOWED + value: "" + - name: KUBERNETES_SERVICE_ACCOUNT + value: "" + - name: KUBERNETES_SERVICE_CPU_LIMIT + value: "" + - name: KUBERNETES_SERVICE_MEMORY_LIMIT + value: "" + - name: KUBERNETES_SERVICE_CPU_REQUEST + value: "" + - name: KUBERNETES_SERVICE_MEMORY_REQUEST + value: "" + - name: KUBERNETES_HELPER_CPU_LIMIT + value: "" + - name: KUBERNETES_HELPER_MEMORY_LIMIT + value: "" + - name: KUBERNETES_HELPER_CPU_REQUEST + value: "" + - name: KUBERNETES_HELPER_MEMORY_REQUEST + value: "" + - name: KUBERNETES_HELPER_IMAGE + value: "" + - name: KUBERNETES_PULL_POLICY + value: "" + volumeMounts: + - name: runner-secrets + mountPath: /secrets + readOnly: false + - name: scripts + mountPath: /config + readOnly: true + - name: init-runner-secrets + mountPath: /init-secrets + readOnly: true + resources: + {} + serviceAccountName: gitlab-runner-gitlab-runner + containers: + - name: gitlab-runner-gitlab-runner + image: gitlab/gitlab-runner:alpine-v13.4.1 + imagePullPolicy: "IfNotPresent" + lifecycle: + preStop: + exec: + command: ["/entrypoint", "unregister", "--all-runners"] + command: ["/bin/bash", "/scripts/entrypoint"] + env: + + - name: CI_SERVER_URL + value: "https://gitlab.qa.joaocunha.eu/" + - name: CLONE_URL + value: "" + - name: RUNNER_REQUEST_CONCURRENCY + value: "1" + - name: RUNNER_EXECUTOR + value: "kubernetes" + - name: REGISTER_LOCKED + value: "true" + - name: RUNNER_TAG_LIST + value: "" + - name: RUNNER_OUTPUT_LIMIT + value: "4096" + - name: KUBERNETES_IMAGE + value: "ubuntu:16.04" + + - name: KUBERNETES_PRIVILEGED + value: "true" + + - name: KUBERNETES_NAMESPACE + value: "gitlab" + - name: KUBERNETES_POLL_TIMEOUT + value: "180" + - name: KUBERNETES_CPU_LIMIT + value: "" + - name: KUBERNETES_CPU_LIMIT_OVERWRITE_MAX_ALLOWED + value: "" + - name: KUBERNETES_MEMORY_LIMIT + value: "" + - name: KUBERNETES_MEMORY_LIMIT_OVERWRITE_MAX_ALLOWED + value: "" + - name: KUBERNETES_CPU_REQUEST + value: "" + - name: KUBERNETES_CPU_REQUEST_OVERWRITE_MAX_ALLOWED + value: "" + - name: KUBERNETES_MEMORY_REQUEST + value: "" + - name: KUBERNETES_MEMORY_REQUEST_OVERWRITE_MAX_ALLOWED + value: "" + - name: KUBERNETES_SERVICE_ACCOUNT + value: "" + - name: KUBERNETES_SERVICE_CPU_LIMIT + value: "" + - name: KUBERNETES_SERVICE_MEMORY_LIMIT + value: "" + - name: KUBERNETES_SERVICE_CPU_REQUEST + value: "" + - name: KUBERNETES_SERVICE_MEMORY_REQUEST + value: "" + - name: KUBERNETES_HELPER_CPU_LIMIT + value: "" + - name: KUBERNETES_HELPER_MEMORY_LIMIT + value: "" + - name: KUBERNETES_HELPER_CPU_REQUEST + value: "" + - name: KUBERNETES_HELPER_MEMORY_REQUEST + value: "" + - name: KUBERNETES_HELPER_IMAGE + value: "" + - name: KUBERNETES_PULL_POLICY + value: "" + livenessProbe: + exec: + command: ["/bin/bash", "/scripts/check-live"] + initialDelaySeconds: 60 + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + readinessProbe: + exec: + command: ["/usr/bin/pgrep","gitlab.*runner"] + initialDelaySeconds: 10 + timeoutSeconds: 1 + periodSeconds: 10 + successThreshold: 1 + failureThreshold: 3 + ports: + - name: metrics + containerPort: 9252 + volumeMounts: + - name: runner-secrets + mountPath: /secrets + - name: etc-gitlab-runner + mountPath: /home/gitlab-runner/.gitlab-runner + - name: scripts + mountPath: /scripts + resources: + {} + volumes: + - name: runner-secrets + emptyDir: + medium: "Memory" + - name: etc-gitlab-runner + emptyDir: + medium: "Memory" + - name: init-runner-secrets + projected: + sources: + - secret: + name: "gitlab-runner-gitlab-runner" + items: + - key: runner-registration-token + path: runner-registration-token + - key: runner-token + path: runner-token + - name: scripts + configMap: + name: gitlab-runner-gitlab-runner +``` diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md index 53be7e995d5..b03dfb79ae0 100644 --- a/doc/user/clusters/applications.md +++ b/doc/user/clusters/applications.md @@ -100,7 +100,7 @@ include: - template: Managed-Cluster-Applications.gitlab-ci.yml apply: - image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.34.1" + image: "registry.gitlab.com/gitlab-org/cluster-integration/cluster-applications:v0.37.0" ``` ### Use the template with a custom environment @@ -1268,6 +1268,11 @@ record. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21966) in GitLab 12.7. +WARNING: +The Web Application Firewall is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/271276) +in GitLab 13.6, and planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/271349) +in GitLab 14.0. + A Web Application Firewall (WAF) examines traffic being sent or received, and can block malicious traffic before it reaches your application. The benefits of a WAF are: @@ -1296,7 +1301,7 @@ To enable WAF, switch its respective toggle to the enabled position when install or updating [Ingress application](#ingress). If this is your first time using the GitLab WAF, we recommend you follow the -[quick start guide](../../topics/web_application_firewall/quick_start_guide.md). +[quick start guide](../project/clusters/protect/web_application_firewall/quick_start_guide.md). There is a small performance overhead by enabling ModSecurity. If this is considered significant for your application, you can disable ModSecurity's @@ -1308,7 +1313,7 @@ rule engine for your deployed application in any of the following ways: 1. Switch its respective toggle to the disabled position, and then apply changes by selecting **Save changes** to reinstall Ingress with the recent changes. -![Disabling WAF](../../topics/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png) +![Disabling WAF](../project/clusters/protect/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png) ##### Logging and blocking modes @@ -1321,7 +1326,7 @@ To help you tune your WAF rules, you can globally set your WAF to either To change your WAF's mode: 1. If you haven't already done so, - [install ModSecurity](../../topics/web_application_firewall/quick_start_guide.md). + [install ModSecurity](../project/clusters/protect/web_application_firewall/quick_start_guide.md). 1. Navigate to **Operations > Kubernetes**. 1. In **Applications**, scroll to **Ingress**. 1. Under **Global default**, select your desired mode. @@ -1337,12 +1342,12 @@ The **ModSecurity** user interface controls are disabled if the version deployed differs from the one available in GitLab. However, actions at the [Ingress](#ingress) level, such as uninstalling, can still be performed: -![WAF settings disabled](../../topics/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png) +![WAF settings disabled](../project/clusters/protect/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png) Update [Ingress](#ingress) to the most recent version to take advantage of bug fixes, security fixes, and performance improvements. To update the [Ingress application](#ingress), you must first uninstall it, and then re-install -it as described in [Install ModSecurity](../../topics/web_application_firewall/quick_start_guide.md). +it as described in [Install ModSecurity](../project/clusters/protect/web_application_firewall/quick_start_guide.md). ##### Viewing Web Application Firewall traffic diff --git a/doc/user/compliance/license_compliance/index.md b/doc/user/compliance/license_compliance/index.md index f78b6115623..1428a0d4e80 100644 --- a/doc/user/compliance/license_compliance/index.md +++ b/doc/user/compliance/license_compliance/index.md @@ -76,7 +76,7 @@ The reported licenses might be incomplete or inaccurate. | Elixir | [Mix](https://elixir-lang.org/getting-started/mix-otp/introduction-to-mix.html) | | C++/C | [Conan](https://conan.io/) | | Scala | [sbt](https://www.scala-sbt.org/) | -| Rust | [Cargo](https://crates.io) | +| Rust | [Cargo](https://crates.io/) | | PHP | [Composer](https://getcomposer.org/) | ## Requirements diff --git a/doc/user/discussions/img/threads_resolved.png b/doc/user/discussions/img/threads_resolved.png Binary files differdeleted file mode 100644 index ffb1233f2ee..00000000000 --- a/doc/user/discussions/img/threads_resolved.png +++ /dev/null diff --git a/doc/user/discussions/index.md b/doc/user/discussions/index.md index 945c082bba9..bf3e907bd24 100644 --- a/doc/user/discussions/index.md +++ b/doc/user/discussions/index.md @@ -90,27 +90,6 @@ When a link of a commit reference is found in a thread inside a merge request, it will be automatically converted to a link in the context of the current merge request. -### Jumping between unresolved threads (deprecated) - -> - [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/199718) in GitLab 13.3. -> - This button's removal is behind a feature flag enabled by default. -> - For GitLab self-managed instances, GitLab administrators with access to the - [GitLab Rails console](../../administration/feature_flags.md) can opt to disable it by running - `Feature.disable(:hide_jump_to_next_unresolved_in_threads)` (for the instance) or - `Feature.disable(:hide_jump_to_next_unresolved_in_threads, Project.find(<project id>))` - (per project.) **(CORE ONLY)** - -When a merge request has a large number of comments it can be difficult to track -what remains unresolved. You can jump between unresolved threads with the -Jump button next to the Reply field on a thread. - -You can also use keyboard shortcuts to navigate among threads: - -- Use <kbd>n</kbd> to jump to the next unresolved thread. -- Use <kbd>p</kbd> to jump to the previous unresolved thread. - -!["8/9 threads resolved"](img/threads_resolved.png) - ### Marking a comment or thread as resolved You can mark a thread as resolved by clicking the **Resolve thread** diff --git a/doc/user/gitlab_com/index.md b/doc/user/gitlab_com/index.md index 7aafa52799d..611c1105961 100644 --- a/doc/user/gitlab_com/index.md +++ b/doc/user/gitlab_com/index.md @@ -114,7 +114,7 @@ or over the repository size limit, you can [reduce your repository size with Git | Setting | GitLab.com | Default | | ----------- | ----------- | ------------- | | [Repository size including LFS](../admin_area/settings/account_and_limit_settings.md) | 10 GB | Unlimited | -| Maximum import size | 5 GB | 50 MB | +| Maximum import size | 5 GB | Unlimited | NOTE: `git push` and GitLab project imports are limited to 5 GB per request through Cloudflare. Git LFS and imports other than a file upload are not affected by this limit. @@ -132,6 +132,23 @@ All our runners are deployed into Google Cloud Platform (GCP) - any IP based firewall can be configured by looking up all [IP address ranges or CIDR blocks for GCP](https://cloud.google.com/compute/docs/faq#where_can_i_find_product_name_short_ip_ranges). +## Hostname list + +To configure allow-lists in local HTTP(S) proxies, or other +web-blocking software that govern end-user machines, +pages on GitLab.com will attempt to load content from +the following hostnames: + +- `gitlab.com` +- `*.gitlab.com` +- `*.gitlab-static.net` +- `*.gitlab.io` +- `*.gitlab.net` + +Documentation and Company pages served over `docs.gitlab.com` +and `about.gitlab.com` will attempt to also load certain page +content directly from common public CDN hostnames. + ## Webhooks A limit of: @@ -532,13 +549,10 @@ endpoints](../../user/admin_area/settings/rate_limits_on_raw_endpoints.md). ### Rate limiting responses -The [`Retry-After` -header](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Retry-After) -indicates when the client should retry. +For information on rate limiting responses, see: -Rate limits applied by HAProxy (instead of Cloudflare or the -GitLab application) have `RateLimit-Reset` and `RateLimit-ResetTime` -headers. +- [List of headers on responses to blocked requests](../admin_area/settings/user_and_ip_rate_limits.md#response-headers). +- [Customizable response text](../admin_area/settings/user_and_ip_rate_limits.md#response-text). ### Protected paths throttle @@ -548,11 +562,7 @@ paths that exceed 10 requests per **minute** per IP address. See the source below for which paths are protected. This includes user creation, user confirmation, user sign in, and password reset. -This header is included in responses to blocked requests: - -```plaintext -Retry-After: 60 -``` +[User and IP rate limits](../admin_area/settings/user_and_ip_rate_limits.md#response-headers) includes a list of the headers responded to blocked requests. See [Protected Paths](../admin_area/settings/protected_paths.md) for more details. diff --git a/doc/user/group/import/img/bulk_imports_v13_8.png b/doc/user/group/import/img/bulk_imports_v13_8.png Binary files differnew file mode 100644 index 00000000000..31234f9fcea --- /dev/null +++ b/doc/user/group/import/img/bulk_imports_v13_8.png diff --git a/doc/user/group/import/img/import_panel_v13_8.png b/doc/user/group/import/img/import_panel_v13_8.png Binary files differnew file mode 100644 index 00000000000..1fb7fbad291 --- /dev/null +++ b/doc/user/group/import/img/import_panel_v13_8.png diff --git a/doc/user/group/import/img/new_group_navigation_v13_8.png b/doc/user/group/import/img/new_group_navigation_v13_8.png Binary files differnew file mode 100644 index 00000000000..307175727c7 --- /dev/null +++ b/doc/user/group/import/img/new_group_navigation_v13_8.png diff --git a/doc/user/group/import/index.md b/doc/user/group/import/index.md new file mode 100644 index 00000000000..d051a134af1 --- /dev/null +++ b/doc/user/group/import/index.md @@ -0,0 +1,91 @@ +--- +type: reference, howto +stage: Manage +group: Import +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Import groups from another instance of GitLab **(CORE)** + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/249160) in GitLab 13.7. +> - It's [deployed behind a feature flag](../../feature_flags.md), disabled by default. +> - It's enabled on GitLab.com. + +## Overview + +WARNING: +This feature is [under construction](https://gitlab.com/groups/gitlab-org/-/epics/2771) and currently migrates only some of the Group data. Please see below for the full list of what is included in the migration at this time. + +Using GitLab Group Migration, you can migrate existing top-level groups from GitLab.com or a self-managed instance. Groups can be migrated to a target instance, as a top-level group, or as a sub-group of any existing top-level group. + +The following resources are migrated to the target instance: + +- Groups + - description + - attributes + - subgroups +- Epics + - title + - description + - state (open / closed) + - start date + - due date + - epic order on boards + - confidentiality + +Any other items are **not** migrated. + +## Enable or disable GitLab Group Migration + +Support for GitLab Group Migration is under development and not ready for production use. It is +deployed behind a feature flag that is **disabled by default**. +[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) can enable it. + +To enable it: + +```ruby +Feature.enable(:bulk_import) +``` + +To disable it: + +```ruby +Feature.disable(:bulk_import) +``` + +## Import your groups into GitLab + +Before you begin, ensure that the target instance of GitLab can communicate with the source +over HTTPS (HTTP is not supported). + +NOTE: +This might involve reconfiguring your firewall to prevent blocking connection on the side of self-managed instance. + +### Connect to the remote GitLab instance + +1. Navigate to the New Group page, either via the `+` button in the top navigation bar, or the **New subgroup** button +on an existing group's page. + + ![Navigation paths to create a new group](img/new_group_navigation_v13_8.png) + +1. On the New Group page, select the **Import group** tab. + + ![Fill in import details](img/import_panel_v13_8.png) + +1. Fill in source URL of your GitLab. +1. Fill in [personal access token](../../../user/profile/personal_access_tokens.md) for remote GitLab instance. +1. Click "Connect instance". + +### Selecting which groups to import + +After you have authorized access to GitLab instance, you are redirected to the GitLab Group Migration importer page and your remote GitLab groups are listed. + +1. By default, the proposed group namespaces match the names as they exist in remote instance, but based on your permissions, you can choose to edit these names before you proceed to import any of them. + +1. Select the **Import** button next to any number of groups. + +1. The **Status** column shows the import status of each group. You can choose to leave the page open and it will update in real-time. + +1. Once a group has been imported, click its GitLab path to open its GitLab URL. + +![Group Importer page](img/bulk_imports_v13_8.png) diff --git a/doc/user/group/index.md b/doc/user/group/index.md index a0884461da1..069dea40ba5 100644 --- a/doc/user/group/index.md +++ b/doc/user/group/index.md @@ -215,10 +215,7 @@ To remove a member from a group: > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21727) in GitLab 12.6. > - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/228675) in GitLab 13.7. -> - Improvements are [deployed behind a feature flag](../feature_flags.md), enabled by default. -> - Improvements are enabled on GitLab.com. -> - Improvements are recommended for production use. -> - For GitLab self-managed instances, GitLab administrators can opt to [disable improvements](#enable-or-disable-improvements-to-the-ability-to-filter-and-sort-group-members). **(CORE ONLY)** +> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/289911) in GitLab 13.8. The following sections illustrate how you can filter and sort members in a group. To view these options, navigate to your desired group, go to **Members**, and include the noted search terms. @@ -269,30 +266,6 @@ You can sort members by **Account**, **Access granted**, **Max role**, or **Last ![Group members sort](img/group_members_sort_13_7.png) -### Enable or disable improvements to the ability to filter and sort group members **(CORE ONLY)** - -Group member filtering and sorting improvements are deployed behind a feature flag that is **enabled by default**. -[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) -can opt to disable the improvements. - -To disable them: - -```ruby -# For the instance -Feature.disable(:group_members_filtered_search) -# For a single group -Feature.disable(:group_members_filtered_search, Group.find(<group id>)) -``` - -To enable them: - -```ruby -# For the instance -Feature.enable(:group_members_filtered_search) -# For a single group -Feature.enable(:group_members_filtered_search, Group.find(<group id>)) -``` - ## Changing the default branch protection of a group > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7583) in GitLab 12.9. @@ -487,7 +460,7 @@ and above. There are a few limitations compared to project wikis: - Git LFS is not supported. -- Group wikis are not included in global search, group exports, backups, and Geo replication. +- Group wikis are not included in global search, group exports, and Geo replication. - Changes to group wikis don't show up in the group's activity feed. - Group wikis [can't be moved](../../api/project_repository_storage_moves.md#limitations) using the project repository moves API. @@ -664,6 +637,12 @@ request to add a new user to a project through API will not be possible. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1985) in [GitLab Ultimate and Gold](https://about.gitlab.com/pricing/) 12.0. > - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215410) to [GitLab Premium and Silver](https://about.gitlab.com/pricing/) in 13.1. +NOTE: +IP Access Restrictions are currently not functioning as expected on GitLab.com. Some users +may experience blocked Git operations or have difficulties accessing projects. Please +review the [following bug report](https://gitlab.com/gitlab-org/gitlab/-/issues/271673) for +more information. + To make sure only people from within your organization can access particular resources, you have the option to restrict access to groups and their underlying projects, issues, etc, by IP address. This can help ensure that diff --git a/doc/user/group/iterations/index.md b/doc/user/group/iterations/index.md index a06c7a8f325..65d3129a825 100644 --- a/doc/user/group/iterations/index.md +++ b/doc/user/group/iterations/index.md @@ -88,6 +88,22 @@ similar to how they appear when viewing a [milestone](../../project/milestones/i Burndown charts help track completion progress of total scope, and burnup charts track the daily total count and weight of issues added to and completed in a given timebox. +### Group issues by label + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/225500) in GitLab 13.8. + +You can group the list of issues by label. +This can help you view issues that have your team's label, +and get a more accurate understanding of scope attributable to each label. + +To group issues by label: + +1. In the **Group by** dropdown, select **Label**. +1. Select the **Filter by label** dropdown. +1. Select the labels you want to group by in the labels dropdown. + You can also search for labels by typing in the search input. +1. Click or tap outside of the label dropdown. The page is now grouped by the selected labels. + ## Disable iterations **(STARTER ONLY)** GitLab Iterations feature is deployed with a feature flag that is **enabled by default**. diff --git a/doc/user/group/roadmap/img/roadmap_filters_v13_7.png b/doc/user/group/roadmap/img/roadmap_filters_v13_7.png Binary files differdeleted file mode 100644 index 00505a7f34f..00000000000 --- a/doc/user/group/roadmap/img/roadmap_filters_v13_7.png +++ /dev/null diff --git a/doc/user/group/roadmap/img/roadmap_filters_v13_8.png b/doc/user/group/roadmap/img/roadmap_filters_v13_8.png Binary files differnew file mode 100644 index 00000000000..d826909b022 --- /dev/null +++ b/doc/user/group/roadmap/img/roadmap_filters_v13_8.png diff --git a/doc/user/group/roadmap/index.md b/doc/user/group/roadmap/index.md index 6dfa7641dbb..f3b7be536ae 100644 --- a/doc/user/group/roadmap/index.md +++ b/doc/user/group/roadmap/index.md @@ -67,8 +67,9 @@ You can also filter epics in the Roadmap view by: - Author - Label - Milestone +- Confidentiality of epics -![roadmap date range in weeks](img/roadmap_filters_v13_7.png) +![roadmap date range in weeks](img/roadmap_filters_v13_8.png) Roadmaps can also be [visualized inside an epic](../epics/index.md#roadmap-in-epics). diff --git a/doc/user/group/saml_sso/group_managed_accounts.md b/doc/user/group/saml_sso/group_managed_accounts.md index 15dd91bece2..7158b7bc86b 100644 --- a/doc/user/group/saml_sso/group_managed_accounts.md +++ b/doc/user/group/saml_sso/group_managed_accounts.md @@ -52,11 +52,13 @@ assertions to be able to create a user. ## Feature flag **(PREMIUM ONLY)** -The group-managed accounts feature is behind a feature flag: `group_managed_accounts`. The flag is disabled by default. +The group-managed accounts feature is behind these feature flags: `group_managed_accounts`, `sign_up_on_sso` and `convert_user_to_group_managed_accounts`. The flags are disabled by default. To activate the feature, ask a GitLab administrator with Rails console access to run: ```ruby Feature.enable(:group_managed_accounts) +Feature.enable(:sign_up_on_sso) +Feature.enable(:convert_user_to_group_managed_accounts) ``` ## Project restrictions for Group-managed accounts diff --git a/doc/user/group/saml_sso/index.md b/doc/user/group/saml_sso/index.md index 62431747911..0ce92eac1a3 100644 --- a/doc/user/group/saml_sso/index.md +++ b/doc/user/group/saml_sso/index.md @@ -80,10 +80,14 @@ Please note that the certificate [fingerprint algorithm](#additional-providers-a - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/5291) in GitLab 11.8. - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/9255) in GitLab 11.11 with ongoing enforcement in the GitLab UI. +- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/292811) in GitLab 13.8, with an updated timeout experience. +- [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/211962) in GitLab 13.8 with allowing group owners to not go through SSO. With this option enabled, users must go through your group's GitLab single sign-on URL. They may also be added via SCIM, if configured. Users can't be added manually, and may only access project/group resources via the UI by signing in through the SSO URL. -However, users are not prompted to sign in through SSO on each visit. GitLab checks whether a user has authenticated through SSO, and only prompts the user to sign in via SSO if the session has expired. +However, users are not prompted to sign in through SSO on each visit. GitLab checks whether a user +has authenticated through SSO. If it's been more than 7 days since the last sign-in, GitLab +prompts the user to sign in again through SSO. You can see more information about how long a session is valid in our [user profile documentation](../../profile/#why-do-i-keep-getting-signed-out). We intend to add a similar SSO requirement for [Git and API activity](https://gitlab.com/gitlab-org/gitlab/-/issues/9152). @@ -93,11 +97,10 @@ When SSO enforcement is enabled for a group, users can't share a project in the ## Providers NOTE: -GitLab is unable to provide support for IdPs that are not listed here. +GitLab is unable to provide full support for integrating identify providers that are not listed here. | Provider | Documentation | |----------|---------------| -| ADFS (Active Directory Federation Services) | [Create a Relying Party Trust](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust) | | Azure | [Configuring single sign-on to applications](https://docs.microsoft.com/en-us/azure/active-directory/manage-apps/view-applications-portal) | | Okta | [Setting up a SAML application in Okta](https://developer.okta.com/docs/guides/build-sso-integration/saml2/overview/) | | OneLogin | [Use the OneLogin SAML Test Connector](https://onelogin.service-now.com/support?id=kb_article&sys_id=93f95543db109700d5505eea4b96198f) | @@ -164,8 +167,9 @@ For more information, see our [discussion on providers](#providers). Your identity provider may have relevant documentation. It may be generic SAML documentation, or specifically targeted for GitLab. Examples: +- [ADFS (Active Directory Federation Services)](https://docs.microsoft.com/en-us/windows-server/identity/ad-fs/operations/create-a-relying-party-trust) - [Auth0](https://auth0.com/docs/protocols/saml-configuration-options/configure-auth0-as-saml-identity-provider) -- [G Suite](https://support.google.com/a/answer/6087519?hl=en) +- [Google Workspace](https://support.google.com/a/answer/6087519?hl=en) - [JumpCloud](https://support.jumpcloud.com/support/s/article/single-sign-on-sso-with-gitlab-2019-08-21-10-36-47) - [PingOne by Ping Identity](https://docs.pingidentity.com/bundle/pingone/page/xsh1564020480660-1.html) @@ -209,7 +213,7 @@ When a user tries to sign in with Group SSO, GitLab attempts to find or create a To link SAML to your existing GitLab.com account: 1. Sign in to your GitLab.com account. -1. Locate and visit the **GitLab single sign-on URL** for the group you're signing in to. A group Admin can find this on the group's **Settings > SAML SSO** page. If the sign-in URL is configured, users can connect to the GitLab app from the Identity Provider. +1. Locate and visit the **GitLab single sign-on URL** for the group you're signing in to. A group owner can find this on the group's **Settings > SAML SSO** page. If the sign-in URL is configured, users can connect to the GitLab app from the Identity Provider. 1. Click **Authorize**. 1. Enter your credentials on the Identity Provider if prompted. 1. You are then redirected back to GitLab.com and should now have access to the group. In the future, you can use SAML to sign in to GitLab.com. diff --git a/doc/user/group/saml_sso/scim_setup.md b/doc/user/group/saml_sso/scim_setup.md index 40c036e1fc0..cd3e99ae541 100644 --- a/doc/user/group/saml_sso/scim_setup.md +++ b/doc/user/group/saml_sso/scim_setup.md @@ -232,7 +232,7 @@ It is important that this SCIM `id` and SCIM `externalId` are configured to the Group owners can see the list of users and the `externalId` stored for each user in the group SAML SSO Settings page. -A possible alternative is to use the [SCIM API](../../../api/scim.md#get-a-list-of-saml-users) to manually retrieve the `externalId` we have stored for users, also called the `external_uid` or `NameId`. +A possible alternative is to use the [SCIM API](../../../api/scim.md#get-a-list-of-scim-provisioned-users) to manually retrieve the `externalId` we have stored for users, also called the `external_uid` or `NameId`. To see how the `external_uid` compares to the value returned as the SAML NameId, you can have the user use a [SAML Tracer](index.md#saml-debugging-tools). @@ -251,7 +251,7 @@ you can address the problem in the following ways: - You can have users unlink and relink themselves, based on the ["SAML authentication failed: User has already been taken"](index.md#message-saml-authentication-failed-user-has-already-been-taken) section. - You can unlink all users simultaneously, by removing all users from the SAML app while provisioning is turned on. -- It may be possible to use the [SCIM API](../../../api/scim.md#update-a-single-saml-user) to manually correct the `externalId` stored for users to match the SAML `NameId`. +- It may be possible to use the [SCIM API](../../../api/scim.md#update-a-single-scim-provisioned-user) to manually correct the `externalId` stored for users to match the SAML `NameId`. To look up a user, you'll need to know the desired value that matches the `NameId` as well as the current `externalId`. It is important not to update these to incorrect values, since this will cause users to be unable to sign in. It is also important not to assign a value to the wrong user, as this would cause users to get signed into the wrong account. @@ -269,7 +269,7 @@ Changing the SAML or SCIM configuration or provider can cause the following prob | Problem | Solution | |------------------------------------------------------------------------------|--------------------| | SAML and SCIM identity mismatch. | First [verify that the user's SAML NameId matches the SCIM externalId](#how-do-i-verify-users-saml-nameid-matches-the-scim-externalid) and then [update or fix the mismatched SCIM externalId and SAML NameId](#update-or-fix-mismatched-scim-externalid-and-saml-nameid). | -| SCIM identity mismatch between GitLab and the Identify Provider SCIM app. | You can confirm whether you're hitting the error because of your SCIM identity mismatch between your SCIM app and GitLab.com by using [SCIM API](../../../api/scim.md#update-a-single-saml-user) which shows up in the `id` key and compares it with the user `externalId` in the SCIM app. You can use the same [SCIM API](../../../api/scim.md#update-a-single-saml-user) to update the SCIM `id` for the user on GitLab.com. | +| SCIM identity mismatch between GitLab and the Identify Provider SCIM app. | You can confirm whether you're hitting the error because of your SCIM identity mismatch between your SCIM app and GitLab.com by using [SCIM API](../../../api/scim.md#update-a-single-scim-provisioned-user) which shows up in the `id` key and compares it with the user `externalId` in the SCIM app. You can use the same [SCIM API](../../../api/scim.md#update-a-single-scim-provisioned-user) to update the SCIM `id` for the user on GitLab.com. | ### Azure diff --git a/doc/user/group/settings/import_export.md b/doc/user/group/settings/import_export.md index 2aee8706194..6b95388bf2e 100644 --- a/doc/user/group/settings/import_export.md +++ b/doc/user/group/settings/import_export.md @@ -76,7 +76,7 @@ For more details on the specific data persisted in a group export, see the file from there by clicking **Download export**, or generate a new file by clicking **Regenerate export**. NOTE: -The maximum import file size can be set by the Administrator, default is 50MB. +The maximum import file size can be set by the Administrator, default is `0` (unlimited). As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](../../../api/settings.md#change-application-settings) or the [Admin UI](../../admin_area/settings/account_and_limit_settings.md). ### Between CE and EE diff --git a/doc/user/group/subgroups/img/group_members_filter_v12_6.png b/doc/user/group/subgroups/img/group_members_filter_v12_6.png Binary files differdeleted file mode 100644 index 692fdfe00a1..00000000000 --- a/doc/user/group/subgroups/img/group_members_filter_v12_6.png +++ /dev/null diff --git a/doc/user/group/subgroups/index.md b/doc/user/group/subgroups/index.md index 8af075fc0c0..59812fc2b2f 100644 --- a/doc/user/group/subgroups/index.md +++ b/doc/user/group/subgroups/index.md @@ -117,7 +117,7 @@ Follow the same process to create any subsequent groups. ## Membership When you add a member to a group, that member is also added to all subgroups. -Permission level is inherited from the group’s parent. This model allows access to +Permission level is inherited from the group’s parent. This model allows access to subgroups if you have membership in one of its parents. Jobs for pipelines in subgroups can use [runners](../../../ci/runners/README.md) registered to the parent group(s). diff --git a/doc/user/group/value_stream_analytics/index.md b/doc/user/group/value_stream_analytics/index.md index 0f9afdef995..438769872c0 100644 --- a/doc/user/group/value_stream_analytics/index.md +++ b/doc/user/group/value_stream_analytics/index.md @@ -316,15 +316,6 @@ To delete a custom value stream: ![Delete value stream](img/delete_value_stream_v13.4.png "Deleting a custom value stream") -### Disabling custom value streams - -Custom value streams are enabled by default. If you have a self-managed instance, an -administrator can open a Rails console and disable them with the following command: - -```ruby -Feature.disable(:value_stream_analytics_create_multiple_value_streams) -``` - ## Days to completion chart > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/21631) in GitLab 12.6. diff --git a/doc/user/infrastructure/img/terraform_list_view_actions_v13_8.png b/doc/user/infrastructure/img/terraform_list_view_actions_v13_8.png Binary files differnew file mode 100644 index 00000000000..7d619b6ad7e --- /dev/null +++ b/doc/user/infrastructure/img/terraform_list_view_actions_v13_8.png diff --git a/doc/user/infrastructure/img/terraform_list_view_v13_5.png b/doc/user/infrastructure/img/terraform_list_view_v13_5.png Binary files differdeleted file mode 100644 index b23dfa6289e..00000000000 --- a/doc/user/infrastructure/img/terraform_list_view_v13_5.png +++ /dev/null diff --git a/doc/user/infrastructure/img/terraform_list_view_v13_8.png b/doc/user/infrastructure/img/terraform_list_view_v13_8.png Binary files differnew file mode 100644 index 00000000000..6eb85285e81 --- /dev/null +++ b/doc/user/infrastructure/img/terraform_list_view_v13_8.png diff --git a/doc/user/infrastructure/index.md b/doc/user/infrastructure/index.md index 4c012fbf1d9..60453b007ba 100644 --- a/doc/user/infrastructure/index.md +++ b/doc/user/infrastructure/index.md @@ -8,11 +8,37 @@ info: To determine the technical writer assigned to the Stage/Group associated w ## Motivation -The Terraform integration features within GitLab enable your GitOps / Infrastructure-as-Code (IaC) +The Terraform integration features in GitLab enable your GitOps / Infrastructure-as-Code (IaC) workflows to tie into GitLab authentication and authorization. These features focus on -lowering the barrier to entry for teams to adopt Terraform, collaborate effectively within +lowering the barrier to entry for teams to adopt Terraform, collaborate effectively in GitLab, and support Terraform best practices. +## Quick Start + +Use the following `.gitlab-ci.yml` to set up a basic Terraform project integration +for GitLab versions 13.5 and later: + +```yaml +include: + - template: Terraform.latest.gitlab-ci.yml + +variables: + # If not using GitLab's HTTP backend, remove this line and specify TF_HTTP_* variables + TF_STATE_NAME: default + TF_CACHE_KEY: default +``` + +This template uses `.latest.`, instead of stable, and may include breaking changes. +This template also includes some opinionated decisions, which you can override: + +- Including the latest [GitLab Terraform Image](https://gitlab.com/gitlab-org/terraform-images). +- Using the [GitLab managed Terraform State](#gitlab-managed-terraform-state) as + the Terraform state storage backend. +- Creating [four pipeline stages](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml): + `init`, `validate`, `build`, and `deploy`. These stages + [run the Terraform commands](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml) + `init`, `validate`, `plan`, `plan-json`, and `apply`. The `apply` command only runs on `master`. + ## GitLab Managed Terraform state [Terraform remote backends](https://www.terraform.io/docs/backends/index.html) @@ -22,7 +48,7 @@ to securely store the state files in local storage (the default) or [the remote store of your choice](../../administration/terraform_state.md). The GitLab managed Terraform state backend can store your Terraform state easily and -securely, and spares you from setting up additional remote resources like +securely. It spares you from setting up additional remote resources like Amazon S3 or Google Cloud Storage. Its features include: - Supporting encryption of the state file both in transit and at rest. @@ -39,32 +65,23 @@ recommends encrypting plan output or modifying the project visibility settings. ## Terraform integration in Merge Requests -Collaborating around Infrastructure as Code (IaC) changes requires both code changes and expected infrastructure changes to be checked and approved. GitLab provides a solution to help collaboration around Terraform code changes and their expected effects using the Merge Request pages. This way users don't have to build custom tools or rely on 3rd party solutions to streamline their IaC workflows. +Collaborating around Infrastructure as Code (IaC) changes requires both code changes +and expected infrastructure changes to be checked and approved. GitLab provides a +solution to help collaboration around Terraform code changes and their expected +effects using the Merge Request pages. This way users don't have to build custom +tools or rely on 3rd party solutions to streamline their IaC workflows. Read more on setting up and [using the merge request integrations](mr_integration.md). -## Quick Start - -Use the following `.gitlab-ci.yml` to set up a simple Terraform project integration -for GitLab versions 13.5 and greater: +## The GitLab terraform provider -```yaml -include: - - template: Terraform.latest.gitlab-ci.yml - -variables: - # If not using GitLab's HTTP backend, remove this line and specify TF_HTTP_* variables - TF_STATE_NAME: default - TF_CACHE_KEY: default -``` +WARNING: +The GitLab Terraform provider is released separately from GitLab. +We are working on migrating the GitLab Terraform provider for GitLab.com. -This template uses `.latest.`, instead of stable, and may include breaking changes. -This template also includes some opinionated decisions, which you can override: +You can use the [GitLab Terraform provider](https://github.com/gitlabhq/terraform-provider-gitlab) +to manage various aspects of GitLab using Terraform. The provider is an open source project, +owned by GitLab, where everyone can contribute. -- Including the latest [GitLab Terraform Image](https://gitlab.com/gitlab-org/terraform-images). -- Using the [GitLab managed Terraform State](#gitlab-managed-terraform-state) as - the Terraform state storage backend. -- Creating [four pipeline stages](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform.latest.gitlab-ci.yml): - `init`, `validate`, `build`, and `deploy`. These stages - [run the Terraform commands](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Terraform/Base.latest.gitlab-ci.yml) - `init`, `validate`, `plan`, `plan-json`, and `apply`. The `apply` command only runs on `master`. +The [documentation of the provider](https://registry.terraform.io/providers/gitlabhq/gitlab/latest/docs) +is available as part of the official Terraform provider documentations. diff --git a/doc/user/infrastructure/mr_integration.md b/doc/user/infrastructure/mr_integration.md index c86e5ddf1db..2704e7b7c8d 100644 --- a/doc/user/infrastructure/mr_integration.md +++ b/doc/user/infrastructure/mr_integration.md @@ -72,10 +72,10 @@ To manually configure a GitLab Terraform Report artifact requires the following terraform: $PLAN_JSON ``` - For a full example using the pre-built image, see [Example `.gitlab-ci.yaml` - file](#example-gitlab-ciyaml-file). + For a full example using the pre-built image, see [Example `.gitlab-ci.yml` + file](#example-gitlab-ciyml-file). - For an example displaying multiple reports, see [`.gitlab-ci.yaml` multiple reports file](#multiple-terraform-plan-reports). + For an example displaying multiple reports, see [`.gitlab-ci.yml` multiple reports file](#multiple-terraform-plan-reports). 1. Running the pipeline displays the widget in the merge request, like this: @@ -86,7 +86,7 @@ To manually configure a GitLab Terraform Report artifact requires the following ![Terraform plan logs](img/terraform_plan_log_v13_0.png) -### Example `.gitlab-ci.yaml` file +### Example `.gitlab-ci.yml` file ```yaml default: diff --git a/doc/user/infrastructure/terraform_state.md b/doc/user/infrastructure/terraform_state.md index cbd2a63524d..30838b1cabd 100644 --- a/doc/user/infrastructure/terraform_state.md +++ b/doc/user/infrastructure/terraform_state.md @@ -62,7 +62,7 @@ local machine, this is a simple way to get started: 1. On your local machine, run `terraform init`, passing in the following options, replacing `<YOUR-STATE-NAME>`, `<YOUR-PROJECT-ID>`, `<YOUR-USERNAME>` and `<YOUR-ACCESS-TOKEN>` with the relevant values. This command initializes your - Terraform state, and stores that state within your GitLab project. The name of + Terraform state, and stores that state in your GitLab project. The name of your state can contain only uppercase and lowercase letters, decimal digits, hyphens, and underscores. This example uses `gitlab.com`: @@ -104,7 +104,7 @@ and the CI YAML file: ``` 1. In the root directory of your project repository, configure a - `.gitlab-ci.yaml` file. This example uses a pre-built image which includes a + `.gitlab-ci.yml` file. This example uses a pre-built image which includes a `gitlab-terraform` helper. For supported Terraform versions, see the [GitLab Terraform Images project](https://gitlab.com/gitlab-org/terraform-images). @@ -112,7 +112,7 @@ and the CI YAML file: image: registry.gitlab.com/gitlab-org/terraform-images/stable:latest ``` -1. In the `.gitlab-ci.yaml` file, define some environment variables to ease +1. In the `.gitlab-ci.yml` file, define some environment variables to ease development. In this example, `TF_ROOT` is the directory where the Terraform commands must be executed, `TF_ADDRESS` is the URL to the state on the GitLab instance where this pipeline runs, and the final path segment in `TF_ADDRESS` @@ -194,7 +194,7 @@ recommends encrypting plan output or modifying the project visibility settings. ### Example project -See [this reference project](https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-aws) using GitLab and Terraform to deploy a basic AWS EC2 within a custom VPC. +See [this reference project](https://gitlab.com/gitlab-org/configure/examples/gitlab-terraform-aws) using GitLab and Terraform to deploy a basic AWS EC2 in a custom VPC. ## Using a GitLab managed Terraform state backend as a remote data source @@ -234,7 +234,7 @@ An example setup is shown below: } ``` -Outputs from the data source can now be referenced within your Terraform resources +Outputs from the data source can now be referenced in your Terraform resources using `data.terraform_remote_state.example.outputs.<OUTPUT-NAME>`. You need at least [developer access](../permissions.md) to the target project @@ -340,21 +340,76 @@ commands will detect it and remind you to do so if necessary. ``` If you type `yes`, it copies your state from the old location to the new -location. You can then go back to running it from within GitLab CI. +location. You can then go back to running it in GitLab CI/CD. ## Managing state files +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/273592) in GitLab 13.8. + +Users with Developer and greater [permissions](../permissions.md) can view the +state files attached to a project at **Operations > Terraform**. Users with +Maintainer permissions can perform commands on the state files. The user interface +contains these fields: + +![Terraform state list](img/terraform_list_view_v13_8.png) + +- **Name**: The name of the environment, with a locked (**{lock}**) icon if the + state file is locked. +- **Pipeline**: A link to the most recent pipeline and its status. +- **Details**: Information about when the state file was created or changed. +- **Actions**: Actions you can take on the state file, including downloading, + locking, unlocking, or [removing](#remove-a-state-file) the state file and versions: + + ![Terraform state list](img/terraform_list_view_actions_v13_8.png) + NOTE: -We are currently working on [providing a graphical interface for managing state files](https://gitlab.com/groups/gitlab-org/-/epics/4563). +Additional improvements to the +[graphical interface for managing state files](https://gitlab.com/groups/gitlab-org/-/epics/4563) +are planned. + +## Remove a state file + +Users with Maintainer and greater [permissions](../permissions.md) can use the +following options to remove a state file: -![Terraform state list](img/terraform_list_view_v13_5.png) +- **GitLab UI**: Go to **Operations > Terraform**. In the **Actions** column, + click the vertical ellipsis (**{ellipsis_v}**) button and select + **Remove state file and versions**. +- **GitLab REST API**: You can remove a state file by making a request to the + REST API. For example: -The state files attached to a project can be found under Operations / Terraform. + ```shell + curl --header "Private-Token: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>" + ``` -## Removing a State file +- [GitLab GraphQL API](#remove-a-state-file-with-the-gitlab-graphql-api). -You can only remove a state file by making a request to the API, like the following example: +### Remove a state file with the GitLab GraphQL API + +You can remove a state file by making a GraphQL API request. For example: + +```shell +mutation deleteState { + terraformStateDelete(input: { id: "<global_id_for_the_state>" }) { + errors + } +} +``` + +You can obtain the `<global_id_for_the_state>` by querying the list of states: ```shell -curl --header "Private-Token: <your_access_token>" --request DELETE "https://gitlab.example.com/api/v4/projects/<your_project_id>/terraform/state/<your_state_name>" +query ProjectTerraformStates { + project(fullPath: "<your_project_path>") { + terraformStates { + nodes { + id + name + } + } + } +} ``` + +For those new to the GitLab GraphQL API, read +[Getting started with GitLab GraphQL API](../../api/graphql/getting_started.md). diff --git a/doc/user/packages/composer_repository/index.md b/doc/user/packages/composer_repository/index.md index 751915f84a0..6159ea395fa 100644 --- a/doc/user/packages/composer_repository/index.md +++ b/doc/user/packages/composer_repository/index.md @@ -21,6 +21,11 @@ If you do not have a Composer package, create one and check it in to a repository. This example shows a GitLab repository, but the repository can be any public or private repository. +WARNING: +If you are using a GitLab repository, the project must have been created from +a group's namespace, rather than a user's namespace. Composer packages +[can't be published to projects created from a user's namespace](https://gitlab.com/gitlab-org/gitlab/-/issues/235467). + 1. Create a directory called `my-composer-package` and change to that directory: ```shell @@ -72,8 +77,8 @@ Prerequisites: - A package in a GitLab repository. Composer packages should be versioned based on the [Composer specification](https://getcomposer.org/doc/04-schema.md#version). - If the version is not valid, for example, it has three dots (`1.0.0.0`), an - error (`Validation failed: Version is invalid`) occurs when you publish. + If the version is not valid, for example, it has three dots (`1.0.0.0`), an + error (`Validation failed: Version is invalid`) occurs when you publish. - A valid `composer.json` file. - The Packages feature is enabled in a GitLab repository. - The project ID, which is on the project's home page. @@ -132,6 +137,13 @@ A more detailed Composer CI/CD file is also available as a `.gitlab-ci.yml` temp WARNING: Do not save unless you want to overwrite the existing CI/CD file. +## Publishing packages with the same name or version + +When you publish: + +- The same package with different data, it overwrites the existing package. +- The same package with the same data, a `404 Bad request` error occurs. + ## Install a Composer package Install a package from the Package Registry so you can use it as a dependency. @@ -260,6 +272,6 @@ Output indicates that the package has been successfully installed. WARNING: Never commit the `auth.json` file to your repository. To install packages from a CI/CD job, -consider using the [`composer config`](https://getcomposer.org/doc/articles/handling-private-packages-with-satis.md#authentication) tool with your personal access token +consider using the [`composer config`](https://getcomposer.org/doc/articles/handling-private-packages.md#satis) tool with your personal access token stored in a [GitLab CI/CD environment variable](../../../ci/variables/README.md) or in [HashiCorp Vault](../../../ci/secrets/index.md). diff --git a/doc/user/packages/conan_repository/index.md b/doc/user/packages/conan_repository/index.md index 73798d363af..f90c220a622 100644 --- a/doc/user/packages/conan_repository/index.md +++ b/doc/user/packages/conan_repository/index.md @@ -47,7 +47,7 @@ Conan version 1.20.5 ### Install CMake When you develop with C++ and Conan, you can select from many available -compilers. This example uses the CMake compiler. +compilers. This example uses the CMake build system generator. To install CMake: @@ -283,6 +283,9 @@ Additional Conan images to use as the basis of your CI file are available in the Install a Conan package from the Package Registry so you can use it as a dependency. +WARNING: +Project-level packages [cannot be downloaded currently](https://gitlab.com/gitlab-org/gitlab/-/issues/270129). + Conan packages are often installed as dependencies by using the `conanfile.txt` file. @@ -384,3 +387,16 @@ The GitLab Conan repository supports the following Conan CLI commands: packages you have permission to view. - `conan info`: View the information on a given package from the Package Registry. - `conan remove`: Delete the package from the Package Registry. + +## Troubleshooting Conan packages + +### `ERROR: <package> was not found in remote <remote>` + +When you attempt to install a Conan package, you might receive a `404` error +like `ERROR: <package> was not found in remote <remote>`. + +This issue occurs when you request a download from the project-level Conan API. +The resulting URL is missing is project's `/<id>` and Conan commands, like +`conan install`, fail. + +For more information, see [issue 270129](https://gitlab.com/gitlab-org/gitlab/-/issues/270129). diff --git a/doc/user/packages/container_registry/index.md b/doc/user/packages/container_registry/index.md index 4e8d105adfa..8c284ccb9a3 100644 --- a/doc/user/packages/container_registry/index.md +++ b/doc/user/packages/container_registry/index.md @@ -305,7 +305,7 @@ is set to `always`. To use your own Docker images for Docker-in-Docker, follow these steps in addition to the steps in the -[Docker-in-Docker](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor) section: +[Docker-in-Docker](../../../ci/docker/using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker) section: 1. Update the `image` and `service` to point to your registry. 1. Add a service [alias](../../../ci/yaml/README.md#servicesalias). @@ -666,6 +666,23 @@ For example, you may have two individual images, one for `amd64` and another for As a workaround, you should include the architecture in the tag name of individual images. For example, use `mygroup/myapp:1.0.0-amd64` instead of using sub repositories, like `mygroup/myapp/amd64:1.0.0`. You can then tag the manifest list with `mygroup/myapp:1.0.0`. +### The cleanup policy doesn't delete any tags + +In GitLab 13.6 and earlier, when you run the cleanup policy, +you may expect it to delete tags and it does not. + +This issue occurs when the cleanup policy was saved without +editing the value in the **Remove tags matching** field. + +This field had a grayed out `.*` value as a placeholder. +Unless `.*` (or other regex pattern) was entered explicitly into the +field, a `nil` value was submitted. This value prevents the +saved cleanup policy from matching any tags. + +As a workaround, edit the cleanup policy. In the **Remove tags matching** +field, enter `.*` and save. This value indicates that all tags should +be removed. + ### Troubleshoot as a GitLab server admin Troubleshooting the GitLab Container Registry, most of the times, requires diff --git a/doc/user/packages/dependency_proxy/index.md b/doc/user/packages/dependency_proxy/index.md index fbede6d13b7..5e5aadfae2b 100644 --- a/doc/user/packages/dependency_proxy/index.md +++ b/doc/user/packages/dependency_proxy/index.md @@ -141,11 +141,10 @@ You can use the Dependency Proxy to pull your base image. bXlfdXNlcm5hbWU6bXlfcGFzc3dvcmQ= ``` - This can also be other credentials such as: + This can also be a [personal access token](../../../user/profile/personal_access_tokens.md) such as: ```shell echo -n "my_username:personal_access_token" | base64 - echo -n "deploy_token_username:deploy_token" | base64 ``` 1. Create a [custom environment variables](../../../ci/variables/README.md#custom-environment-variables) diff --git a/doc/user/packages/generic_packages/index.md b/doc/user/packages/generic_packages/index.md index c9859840c9c..82c72481984 100644 --- a/doc/user/packages/generic_packages/index.md +++ b/doc/user/packages/generic_packages/index.md @@ -20,16 +20,24 @@ Publish generic files, like release binaries, in your project’s Package Regist ## Authenticate to the Package Registry -To authenticate to the Package Registry, you need either a [personal access token](../../../api/README.md#personalproject-access-tokens) -or [CI job token](../../../api/README.md#gitlab-ci-job-token). +To authenticate to the Package Registry, you need either a [personal access token](../../../api/README.md#personalproject-access-tokens), +[CI job token](../../../api/README.md#gitlab-ci-job-token), or [deploy token](../../project/deploy_tokens/index.md). + +In addition to the standard API authentication mechanisms, the generic package +API allows authentication with HTTP Basic authentication for use with tools that +do not support the other available mechanisms. The `user-id` is not checked and +may be any value, and the `password` must be either a [personal access token](../../../api/README.md#personalproject-access-tokens), +a [CI job token](../../../api/README.md#gitlab-ci-job-token), or a [deploy token](../../project/deploy_tokens/index.md). ## Publish a package file When you publish a package file, if the package does not exist, it is created. +If a package with the same name, version, and filename already exists, it is also created. It does not overwrite the existing package. + Prerequisites: -- You need to [authenticate with the API](../../../api/README.md#authentication). +- You need to [authenticate with the API](../../../api/README.md#authentication). If authenticating with a deploy token, it must be configured with the `write_package_registry` scope. ```plaintext PUT /projects/:id/packages/generic/:package_name/:package_version/:file_name @@ -62,11 +70,13 @@ Example response: ## Download package file -Install a package file. +Download a package file. + +If multiple packages have the same name, version, and filename, then the most recent one is retrieved. Prerequisites: -- You need to [authenticate with the API](../../../api/README.md#authentication). +- You need to [authenticate with the API](../../../api/README.md#authentication). If authenticating with a deploy token, it must be configured with the `read_package_registry` and/or `write_package_registry` scope. ```plaintext GET /projects/:id/packages/generic/:package_name/:package_version/:file_name @@ -88,6 +98,13 @@ curl --header "PRIVATE-TOKEN: <your_access_token>" \ "https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt" ``` +Example request that uses HTTP Basic authentication: + +```shell +curl --user "user:<your_access_token>" \ + https://gitlab.example.com/api/v4/projects/24/packages/generic/my_package/0.0.1/file.txt +``` + ## Publish a generic package by using CI/CD To work with generic packages in [GitLab CI/CD](../../../ci/README.md), you can use diff --git a/doc/user/packages/npm_registry/index.md b/doc/user/packages/npm_registry/index.md index 51b41b842fa..c16fea1d00a 100644 --- a/doc/user/packages/npm_registry/index.md +++ b/doc/user/packages/npm_registry/index.md @@ -94,7 +94,10 @@ Some features such as [publishing](#publish-an-npm-package) a package is only av ## Authenticate to the Package Registry -To authenticate to the Package Registry, you must use one of the following: +You must authenticate with the Package Registry when the project +is private. Public projects do not require authentication. + +To authenticate, use one of the following: - A [personal access token](../../../user/profile/personal_access_tokens.md) (required for two-factor authentication (2FA)), with the scope set to `api`. @@ -102,7 +105,7 @@ To authenticate to the Package Registry, you must use one of the following: - It's not recommended, but you can use [OAuth tokens](../../../api/oauth2.md#resource-owner-password-credentials-flow). Standard OAuth tokens cannot authenticate to the GitLab NPM Registry. You must use a personal access token with OAuth headers. - A [CI job token](#authenticate-with-a-ci-job-token). -- Your NPM package name must be in the format of [@scope:package-name](#package-naming-convention). It must match exactly, including the case. +- Your NPM package name must be in the format of [@scope/package-name](#package-naming-convention). It must match exactly, including the case. ### Authenticate with a personal access token or deploy token @@ -201,7 +204,7 @@ Then, you can run `npm publish` either locally or by using GitLab CI/CD. ## Package naming convention -Your NPM package name must be in the format of `@scope:package-name`. +Your NPM package name must be in the format of `@scope/package-name`. - The `@scope` is the root namespace of the GitLab project. It must match exactly, including the case. - The `package-name` can be whatever you want. @@ -241,7 +244,7 @@ Prerequisites: - [Authenticate](#authenticate-to-the-package-registry) to the Package Registry. - Set a [project-level NPM endpoint](#use-the-gitlab-endpoint-for-npm-packages). -- Your NPM package name must be in the format of [@scope:package-name](#package-naming-convention). It must match exactly, including the case. +- Your NPM package name must be in the format of [@scope/package-name](#package-naming-convention). It must match exactly, including the case. To upload an NPM package to your project, run this command: @@ -461,7 +464,30 @@ If you get this error, ensure that: ### `npm publish` returns `npm ERR! 400 Bad Request` If you get this error, your package name may not meet the -[@scope:package-name package naming convention](#package-naming-convention). +[@scope/package-name package naming convention](#package-naming-convention). Ensure the name meets the convention exactly, including the case. Then try to publish again. + +### `npm publish` returns `npm ERR! 500 Internal Server Error - PUT` + +This is a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/238950) in GitLab +13.3.x and later. The error in the logs will appear as: + +```plaintext +>NoMethodError - undefined method `preferred_language' for #<Rack::Response +``` + +This might be accompanied by another error: + +```plaintext +>Errno::EACCES","exception.message":"Permission denied +``` + +This is usually a permissions issue with either: + +- `'packages_storage_path'` default `/var/opt/gitlab/gitlab-rails/shared/packages/`. +- The remote bucket if [object storage](../../../administration/packages/#using-object-storage) + is used. + +In the latter case, ensure the bucket exists and the GitLab has write access to it. diff --git a/doc/user/packages/nuget_repository/index.md b/doc/user/packages/nuget_repository/index.md index bdf50ecef0b..35172663cc1 100644 --- a/doc/user/packages/nuget_repository/index.md +++ b/doc/user/packages/nuget_repository/index.md @@ -60,6 +60,21 @@ NuGet CLI. mono nuget.exe ``` +## Use the GitLab endpoint for NuGet Packages + +To use the GitLab endpoint for NuGet Packages, choose an option: + +- **Project-level**: Use when you have few NuGet packages and they are not in + the same GitLab group. +- **Group-level**: Use when you have many NuGet packages in different within the + same GitLab group. + +Some features such as [publishing](#publish-a-nuget-package) a package are only available on the project-level endpoint. + +WARNING: +Because of how NuGet handles credentials, the Package Registry rejects anonymous requests on the group-level endpoint. +To work around this limitation, set up [authentication](#add-the-package-registry-as-a-source-for-nuget-packages). + ## Add the Package Registry as a source for NuGet packages To publish and install packages to the Package Registry, you must add the @@ -75,7 +90,9 @@ Prerequisites: with the scope set to `read_package_registry`, `write_package_registry`, or both. - A name for your source. -- Your project ID, which is found on your project's home page. +- Depending on the [endpoint level](#use-the-gitlab-endpoint-for-nuget-packages) you use, either: + - Your project ID, which is found on your project's home page. + - Your group ID, which is found on your group's home page. You can now add a new source to NuGet with: @@ -85,7 +102,9 @@ You can now add a new source to NuGet with: ### Add a source with the NuGet CLI -To add the Package Registry as a source with `nuget`: +#### Project-level endpoint + +To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages) NuGet endpoint, add the Package Registry as a source with `nuget`: ```shell nuget source Add -Name <source_name> -Source "https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/nuget/index.json" -UserName <gitlab_username or deploy_token_username> -Password <gitlab_personal_access_token or deploy_token> @@ -99,9 +118,27 @@ For example: nuget source Add -Name "GitLab" -Source "https://gitlab.example.com/api/v4/projects/10/packages/nuget/index.json" -UserName carol -Password 12345678asdf ``` +#### Group-level endpoint + +To use the [group-level](#use-the-gitlab-endpoint-for-nuget-packages) NuGet endpoint, add the Package Registry as a source with `nuget`: + +```shell +nuget source Add -Name <source_name> -Source "https://gitlab.example.com/api/v4/groups/<your_group_id>/-/packages/nuget/index.json" -UserName <gitlab_username or deploy_token_username> -Password <gitlab_personal_access_token or deploy_token> +``` + +- `<source_name>` is the desired source name. + +For example: + +```shell +nuget source Add -Name "GitLab" -Source "https://gitlab.example.com/api/v4/groups/23/-/packages/nuget/index.json" -UserName carol -Password 12345678asdf +``` + ### Add a source with Visual Studio -To add the Package Registry as a source with Visual Studio: +#### Project-level endpoint + +To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages) NuGet endpoint, add the Package Registry as a source with Visual Studio: 1. Open [Visual Studio](https://visualstudio.microsoft.com/vs/). 1. In Windows, select **File > Options**. On macOS, select **Visual Studio > Preferences**. @@ -126,9 +163,38 @@ The source is displayed in your list. If you get a warning, ensure that the **Location**, **Username**, and **Password** are correct. +#### Group-level endpoint + +To use the [group-level](#use-the-gitlab-endpoint-for-nuget-packages) NuGet endpoint, add the Package Registry as a source with Visual Studio: + +1. Open [Visual Studio](https://visualstudio.microsoft.com/vs/). +1. In Windows, select **File > Options**. On macOS, select **Visual Studio > Preferences**. +1. In the **NuGet** section, select **Sources** to view a list of all your NuGet sources. +1. Select **Add**. +1. Complete the following fields: + - **Name**: Name for the source. + - **Location**: `https://gitlab.example.com/api/v4/groups/<your_group_id>/-/packages/nuget/index.json`, + where `<your_group_id>` is your group ID, and `gitlab.example.com` is + your domain name. + - **Username**: Your GitLab username or deploy token username. + - **Password**: Your personal access token or deploy token. + + ![Visual Studio Adding a NuGet source](img/visual_studio_adding_nuget_source.png) + +1. Click **Save**. + +The source is displayed in your list. + +![Visual Studio NuGet source added](img/visual_studio_nuget_source_added.png) + +If you get a warning, ensure that the **Location**, **Username**, and +**Password** are correct. + ### Add a source with the .NET CLI -To add the Package Registry as a source for .NET: +#### Project-level endpoint + +To use the [project-level](#use-the-gitlab-endpoint-for-nuget-packages) Package Registry as a source for .NET: 1. In the root of your project, create a file named `nuget.config`. 1. Add this content: @@ -138,7 +204,30 @@ To add the Package Registry as a source for .NET: <configuration> <packageSources> <clear /> - <add key="gitlab" value="https://gitlab.example.com/api/v4/projects/<your_project_id>/packages/nuget/index.json" /> + <add key="gitlab" value="https://gitlab.example.com/api/v4/project/<your_project_id>/packages/nuget/index.json" /> + </packageSources> + <packageSourceCredentials> + <gitlab> + <add key="Username" value="<gitlab_username or deploy_token_username>" /> + <add key="ClearTextPassword" value="<gitlab_personal_access_token or deploy_token>" /> + </gitlab> + </packageSourceCredentials> + </configuration> + ``` + +#### Group-level endpoint + +To use the [group-level](#use-the-gitlab-endpoint-for-nuget-packages) Package Registry as a source for .NET: + +1. In the root of your project, create a file named `nuget.config`. +1. Add this content: + + ```xml + <?xml version="1.0" encoding="utf-8"?> + <configuration> + <packageSources> + <clear /> + <add key="gitlab" value="https://gitlab.example.com/api/v4/groups/<your_group_id>/-/packages/nuget/index.json" /> </packageSources> <packageSourceCredentials> <gitlab> @@ -151,6 +240,10 @@ To add the Package Registry as a source for .NET: ## Publish a NuGet package +Prerequisite: + +- Set up the [source](#https://docs.gitlab.com/ee/user/packages/nuget_repository/#add-the-package-registry-as-a-source-for-nuget-packages) with a [project-level endpoint](#use-the-gitlab-endpoint-for-nuget-packages). + When publishing packages: - The Package Registry on GitLab.com can store up to 500 MB of content. @@ -164,9 +257,10 @@ When publishing packages: ### Publish a package with the NuGet CLI -Prerequisite: +Prerequisites: - [A NuGet package created with NuGet CLI](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package). +- Set a [project-level endpoint](#use-the-gitlab-endpoint-for-nuget-packages). Publish a package by running this command: @@ -179,9 +273,10 @@ nuget push <package_file> -Source <source_name> ### Publish a package with the .NET CLI -Prerequisite: +Prerequisites: - [A NuGet package created with .NET CLI](https://docs.microsoft.com/en-us/nuget/create-packages/creating-a-package-dotnet-cli). +- Set a [project-level endpoint](#use-the-gitlab-endpoint-for-nuget-packages). Publish a package by running this command: diff --git a/doc/user/packages/pypi_repository/index.md b/doc/user/packages/pypi_repository/index.md index e78224f89d1..376c0439f32 100644 --- a/doc/user/packages/pypi_repository/index.md +++ b/doc/user/packages/pypi_repository/index.md @@ -233,11 +233,16 @@ password = ${env.CI_JOB_TOKEN} ## Publish a PyPI package -When publishing packages, note that: +Prerequisites: -- The maximum allowed size is 50 MB. +- You must [authenticate with the Package Registry](#authenticate-with-the-package-registry). +- Your [version string must be valid](#ensure-your-version-string-is-valid). +- The maximum allowed package size is 5 GB. - You can't upload the same version of a package multiple times. If you try, - you receive the error `Validation failed: File name has already been taken`. + you receive the error `400 Bad Request`. +- You cannot publish PyPI packages to a group, only to a project. + +You can then [publish a package by using twine](#publish-a-pypi-package-by-using-twine). ### Ensure your version string is valid @@ -301,6 +306,12 @@ python -m twine upload --repository <source_name> dist/<package_file> - `<package_file>` is your package filename, ending in `.tar.gz` or `.whl`. - `<source_name>` is the [source name used during setup](#authenticate-with-the-package-registry). +### Publishing packages with the same name or version + +You cannot publish a package if a package of the same name and version already exists. +You must delete the existing package first. If you attempt to publish the same package +more than once, a `404 Bad Request` error occurs. + ## Install a PyPI package To install the latest version of a package, use the following command: diff --git a/doc/user/packages/workflows/project_registry.md b/doc/user/packages/workflows/project_registry.md index aea1238b9da..d20c75e2d7a 100644 --- a/doc/user/packages/workflows/project_registry.md +++ b/doc/user/packages/workflows/project_registry.md @@ -68,7 +68,7 @@ For Conan, you need to add GitLab as a Conan registry remote. Follow the instruc Then, create your package using the plus-separated (`+`) project path as your Conan user. For example, if your project is located at `https://gitlab.com/foo/bar/my-proj`, [create your Conan package](../conan_repository/index.md) using `conan create . foo+bar+my-proj/channel`. -`channel` is your package channel (such as `stable` or `beta`). +`channel` is your package channel (such as `stable` or `beta`). After you create your package, you're ready to [publish your package](../conan_repository/index.md#publish-a-conan-package), depending on your final package recipe. For example: diff --git a/doc/user/permissions.md b/doc/user/permissions.md index 0dd7d6f7696..3dbae78ccc4 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -75,6 +75,7 @@ The following table depicts the various user permission levels in a project. | Manage user-starred metrics dashboards (*7*) | ✓ | ✓ | ✓ | ✓ | ✓ | | View confidential issues | (*2*) | ✓ | ✓ | ✓ | ✓ | | Assign issues | | ✓ | ✓ | ✓ | ✓ | +| Assign reviewers | | ✓ | ✓ | ✓ | ✓ | | Label issues | | ✓ | ✓ | ✓ | ✓ | | Set issue weight | | ✓ | ✓ | ✓ | ✓ | | Lock issue threads | | ✓ | ✓ | ✓ | ✓ | @@ -94,7 +95,7 @@ The following table depicts the various user permission levels in a project. | View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ | | Archive/reopen requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | | Create/edit requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | -| Import requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | +| Import/export requirements **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | | Create new [test case](../ci/test_cases/index.md) | | ✓ | ✓ | ✓ | ✓ | | Archive [test case](../ci/test_cases/index.md) | | ✓ | ✓ | ✓ | ✓ | | Move [test case](../ci/test_cases/index.md) | | ✓ | ✓ | ✓ | ✓ | @@ -322,7 +323,7 @@ project and should only have access to that project. External users: -- Cannot create groups, projects, or personal snippets. +- Cannot create projects (including forks), groups, or personal snippets. - Can only access public projects and projects to which they are explicitly granted access, thus hiding all other internal or private ones from them (like being logged out). diff --git a/doc/user/profile/account/two_factor_authentication.md b/doc/user/profile/account/two_factor_authentication.md index c25535cbf65..6cdd2d6f161 100644 --- a/doc/user/profile/account/two_factor_authentication.md +++ b/doc/user/profile/account/two_factor_authentication.md @@ -245,7 +245,7 @@ Search for `security.webauth.u2f` and double click on it to toggle to `true`. To set up 2FA with a U2F device: -1. Log in to your GitLab account. +1. Sign in to your GitLab account. 1. Go to your [**Profile settings**](../index.md#profile-settings). 1. Go to **Account**. 1. Click **Enable Two-Factor Authentication**. @@ -298,11 +298,11 @@ NOTE: Recovery codes are not generated for U2F / WebAuthn devices. WARNING: -Each code can be used only once to log in to your account. +Each code can be used only once to sign in to your account. Immediately after successfully enabling two-factor authentication, you're prompted to download a set of generated recovery codes. Should you ever lose access -to your one-time password authenticator, you can use one of these recovery codes to log in to +to your one-time password authenticator, you can use one of these recovery codes to sign in to your account. We suggest copying and printing them, or downloading them using the **Download codes** button for storage in a safe place. If you choose to download them, the file is called `gitlab-recovery-codes.txt`. @@ -314,41 +314,41 @@ If you lose the recovery codes or just want to generate new ones, you can do so from the [two-factor authentication account settings page](#regenerate-2fa-recovery-codes) or [using SSH](#generate-new-recovery-codes-using-ssh). -## Logging in with 2FA Enabled +## Signing in with 2FA Enabled -Logging in with 2FA enabled is only slightly different than a normal login. +Signing in with 2FA enabled is only slightly different than the normal sign-in process. Enter your username and password credentials as you normally would, and you're presented with a second prompt, depending on which type of 2FA you've enabled. -### Log in via a one-time password +### Sign in by using a one-time password When asked, enter the pin from your one time password authenticator's application or a -recovery code to log in. +recovery code to sign in. -### Log in via U2F device +### Sign in by using a U2F device -To log in via a U2F device: +To sign in by using a U2F device: 1. Click **Login via U2F Device**. 1. A light begins blinking on your device. Activate it by touching/pressing its button. A message displays, indicating that your device responded to the authentication -request, and you're automatically logged in. +request, and you're automatically signed in. -### Log in via WebAuthn device +### Sign in by using a WebAuthn device In supported browsers you should be automatically prompted to activate your WebAuthn device (e.g. by touching/pressing its button) after entering your credentials. A message displays, indicating that your device responded to the authentication -request and you're automatically logged in. +request and you're automatically signed in. ## Disabling 2FA If you ever need to disable 2FA: -1. Log in to your GitLab account. +1. Sign in to your GitLab account. 1. Go to your [**Profile settings**](../index.md#profile-settings). 1. Go to **Account**. 1. Click **Disable**, under **Two-Factor Authentication**. @@ -356,6 +356,9 @@ If you ever need to disable 2FA: This clears all your two-factor authentication registrations, including mobile applications and U2F / WebAuthn devices. +Support for disabling 2FA is limited, depending on your subscription level. For more information, see the +[Account Recovery](https://about.gitlab.com/support/#account-recovery) section of our website. + ## Personal access tokens When 2FA is enabled, you can no longer use your normal account password to @@ -393,9 +396,13 @@ a new set of recovery codes with SSH: 1. Run: ```shell - ssh git@gitlab.example.com 2fa_recovery_codes + ssh git@gitlab.com 2fa_recovery_codes ``` + NOTE: + On self-managed instances, replace **`gitlab.com`** in the command above + with the GitLab server hostname (`gitlab.example.com`). + 1. You are prompted to confirm that you want to generate new codes. Continuing this process invalidates previously saved codes: @@ -465,9 +472,9 @@ Sign in and re-enable two-factor authentication as soon as possible. For example, if a user is trying to access a GitLab instance from `first.host.xyz` and `second.host.xyz`: - - The user logs in via `first.host.xyz` and registers their U2F key. - - The user logs out and attempts to log in via `first.host.xyz` - U2F authentication succeeds. - - The user logs out and attempts to log in via `second.host.xyz` - U2F authentication fails, because + - The user signs in by using `first.host.xyz` and registers their U2F key. + - The user signs out and attempts to sign in by using `first.host.xyz` - U2F authentication succeeds. + - The user signs out and attempts to sign in by using `second.host.xyz` - U2F authentication fails, because the U2F key has only been registered on `first.host.xyz`. - To enforce 2FA at the system or group levels see [Enforce Two-factor Authentication](../../../security/two_factor_authentication.md). diff --git a/doc/user/profile/index.md b/doc/user/profile/index.md index d60fb528499..a96975fea92 100644 --- a/doc/user/profile/index.md +++ b/doc/user/profile/index.md @@ -203,11 +203,12 @@ If you previously selected the "Busy" checkbox, remember to deselect it when you ## Busy status indicator -> - Introduced in GitLab 13.6. -> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default. -> - It's disabled on GitLab.com. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/259649) in GitLab 13.6. +> - It was [deployed behind a feature flag](../feature_flags.md), disabled by default. +> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/281073) in GitLab 13.8. +> - It's enabled on GitLab.com. > - It's not recommended for production use. -> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-busy-status-feature). +> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-busy-status-feature). To indicate to others that you are busy, you can set an indicator @@ -228,10 +229,16 @@ To set the busy status indicator, either: 1. Click **Edit profile** (**{pencil}**). 1. Select the **Busy** checkbox -### Enable busy status feature +### Disable busy status feature -The busy status feature is deployed behind a feature flag and is **disabled by default**. -[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) can enable it for your instance from the [rails console](../../administration/feature_flags.md#start-the-gitlab-rails-console). +The busy status feature is deployed behind a feature flag and is **enabled by default**. +[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) can disable it for your instance from the [rails console](../../administration/feature_flags.md#start-the-gitlab-rails-console). + +To disable it: + +```ruby +Feature.disable(:set_user_availability_status) +``` To enable it: @@ -288,7 +295,7 @@ git config --global user.email <your email address> When signing in to the main GitLab application, a `_gitlab_session` cookie is set. `_gitlab_session` is cleared client-side when you close your browser and expires after "Application settings -> Session duration (minutes)"/`session_expire_delay` -(defaults to `10080` minutes = 7 days). +(defaults to `10080` minutes = 7 days) of no activity. When signing in to the main GitLab application, you can also check the "Remember me" option which sets the `remember_user_token` @@ -316,7 +323,9 @@ The `remember_user_token` lifetime of a cookie can now extend beyond the deadlin GitLab uses both session and persistent cookies: -- Session cookie: Session cookies are normally removed at the end of the browser session when the browser is closed. The `_gitlab_session` cookie has no expiration date. +- Session cookie: Session cookies are normally removed at the end of the browser session when + the browser is closed. The `_gitlab_session` cookie has no fixed expiration date. However, + it expires based on its [`session_expire_delay`](#why-do-i-keep-getting-signed-out). - Persistent cookie: The `remember_user_token` is a cookie with an expiration date of two weeks. GitLab activates this cookie if you click Remember Me when you sign in. By default, the server sets a time-to-live (TTL) of 1-week on any session that is used. diff --git a/doc/user/profile/notifications.md b/doc/user/profile/notifications.md index 8974505cf02..38ef01b7537 100644 --- a/doc/user/profile/notifications.md +++ b/doc/user/profile/notifications.md @@ -146,13 +146,15 @@ Users are notified of the following events: | New email added | User | Security email, always sent. | | Email changed | User | Security email, always sent. | | Password changed | User | Security email, always sent when user changes their own password | -| Password changed by administrator | User | Security email, always sent when an administrator changes the password of another user | +| Password changed by administrator | User | Security email, always sent when an administrator changes the password of another user | | Two-factor authentication disabled | User | Security email, always sent. | | New user created | User | Sent on user creation, except for OmniAuth (LDAP)| | User added to project | User | Sent when user is added to project | | Project access level changed | User | Sent when user project access level is changed | | User added to group | User | Sent when user is added to group | | Group access level changed | User | Sent when user group access level is changed | +| Personal Access Tokens expiring soon <!-- Do not delete or lint this instance of future tense --> | User | Security email, always sent. | +| Personal Access Tokens have expired | User | Security email, always sent. | | Project moved | Project members (1) | (1) not disabled | | New release | Project members | Custom notification | diff --git a/doc/user/profile/personal_access_tokens.md b/doc/user/profile/personal_access_tokens.md index cfc70c5a6f0..49889cd3017 100644 --- a/doc/user/profile/personal_access_tokens.md +++ b/doc/user/profile/personal_access_tokens.md @@ -112,7 +112,7 @@ token = PersonalAccessToken.find_by_token('token-string-here123') token.revoke! ``` -This can be shorted into a single-line shell command using the +This can be shortened into a single-line shell command using the [Rails runner](../../administration/troubleshooting/debug.md#using-the-rails-runner): ```shell diff --git a/doc/user/project/canary_deployments.md b/doc/user/project/canary_deployments.md index 52c825932fa..85ac641f6e4 100644 --- a/doc/user/project/canary_deployments.md +++ b/doc/user/project/canary_deployments.md @@ -4,9 +4,10 @@ group: unassigned info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -# Canary Deployments **(PREMIUM)** +# Canary Deployments **(CORE)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1659) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.1. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1659) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.1. +> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212320) to GitLab Core in 13.8. A popular [Continuous Deployment](https://en.wikipedia.org/wiki/Continuous_deployment) strategy, where a small portion of the fleet is updated to the new version of @@ -71,7 +72,7 @@ can easily notice them. ### Advanced traffic control with Canary Ingress > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/215501) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6. -> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212320) to Core in GitLab 13.7. +> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/212320) to Core in GitLab 13.8. Canary deployments can be more strategic with [Canary Ingress](https://kubernetes.github.io/ingress-nginx/user-guide/nginx-configuration/annotations/#canary), which is an advanced traffic routing service that controls incoming HTTP diff --git a/doc/user/project/clusters/add_eks_clusters.md b/doc/user/project/clusters/add_eks_clusters.md index 4fae10c58eb..9047e564598 100644 --- a/doc/user/project/clusters/add_eks_clusters.md +++ b/doc/user/project/clusters/add_eks_clusters.md @@ -122,6 +122,7 @@ To create and add a new Kubernetes cluster to your project, group, or instance: "iam:CreateInstanceProfile", "iam:CreateServiceLinkedRole", "iam:GetRole", + "iam:listAttachedRolePolicies", "iam:ListRoles", "iam:PassRole", "ssm:GetParameters" diff --git a/doc/user/project/clusters/add_remove_clusters.md b/doc/user/project/clusters/add_remove_clusters.md index 8ee9b1f37dd..beb8b71b917 100644 --- a/doc/user/project/clusters/add_remove_clusters.md +++ b/doc/user/project/clusters/add_remove_clusters.md @@ -189,7 +189,7 @@ To add a Kubernetes cluster to your project, group, or instance: Get the API URL by running this command: ```shell - kubectl cluster-info | grep 'Kubernetes master' | awk '/http/ {print $NF}' + kubectl cluster-info | grep -E 'Kubernetes master|Kubernetes control plane' | awk '/http/ {print $NF}' ``` 1. **CA certificate** (required) - A valid Kubernetes certificate is needed to authenticate to the cluster. We use the certificate created by default. diff --git a/doc/user/project/clusters/index.md b/doc/user/project/clusters/index.md index 55467c8a468..a06846e33a6 100644 --- a/doc/user/project/clusters/index.md +++ b/doc/user/project/clusters/index.md @@ -20,7 +20,7 @@ Using the GitLab project Kubernetes integration, you can: - Detect and [monitor Kubernetes](#monitoring-your-kubernetes-cluster). - Use it with [Auto DevOps](#auto-devops). - Use [Web terminals](#web-terminals). -- Use [Deploy Boards](#deploy-boards). **(PREMIUM)** +- Use [Deploy Boards](#deploy-boards). - Use [Canary Deployments](#canary-deployments). **(PREMIUM)** - Use [deployment variables](#deployment-variables). - Use [role-based or attribute-based access controls](add_remove_clusters.md#access-controls). @@ -248,9 +248,17 @@ Deployment variables require a valid [Deploy Token](../deploy_tokens/index.md) n [`gitlab-deploy-token`](../deploy_tokens/index.md#gitlab-deploy-token), and the following command in your deployment job script, for Kubernetes to access the registry: -```plaintext -kubectl create secret docker-registry gitlab-registry --docker-server="$CI_REGISTRY" --docker-username="$CI_DEPLOY_USER" --docker-password="$CI_DEPLOY_PASSWORD" --docker-email="$GITLAB_USER_EMAIL" -o yaml --dry-run | kubectl apply -f - -``` +- Using Kubernetes 1.18+: + + ```shell + kubectl create secret docker-registry gitlab-registry --docker-server="$CI_REGISTRY" --docker-username="$CI_DEPLOY_USER" --docker-password="$CI_DEPLOY_PASSWORD" --docker-email="$GITLAB_USER_EMAIL" -o yaml --dry-run=client | kubectl apply -f - + ``` + +- Using Kubernetes <1.18: + + ```shell + kubectl create secret docker-registry gitlab-registry --docker-server="$CI_REGISTRY" --docker-username="$CI_DEPLOY_USER" --docker-password="$CI_DEPLOY_PASSWORD" --docker-email="$GITLAB_USER_EMAIL" -o yaml --dry-run | kubectl apply -f - + ``` The Kubernetes cluster integration exposes the following [deployment variables](../../../ci/variables/README.md#deployment-environment-variables) in the @@ -308,7 +316,7 @@ combined with either ### Integrations -#### Canary Deployments **(PREMIUM)** +#### Canary Deployments Leverage [Kubernetes' Canary deployments](https://kubernetes.io/docs/concepts/cluster-administration/manage-deployment/#canary-deployments) and visualize your canary deployments right inside the Deploy Board, without @@ -316,7 +324,7 @@ the need to leave GitLab. [Read more about Canary Deployments](../canary_deployments.md) -#### Deploy Boards **(PREMIUM)** +#### Deploy Boards GitLab Deploy Boards offer a consolidated view of the current health and status of each CI [environment](../../../ci/environments/index.md) running on Kubernetes, diff --git a/doc/user/project/clusters/protect/container_host_security/index.md b/doc/user/project/clusters/protect/container_host_security/index.md new file mode 100644 index 00000000000..102001d4f87 --- /dev/null +++ b/doc/user/project/clusters/protect/container_host_security/index.md @@ -0,0 +1,59 @@ +--- +stage: Protect +group: Container Security +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + +# Container Host Security + +Container Host Security in GitLab provides Intrusion Detection and Prevention capabilities that can +monitor and (optionally) block activity inside the containers themselves. This is done by leveraging +an integration with Falco to provide the monitoring capabilities and an integration with Pod +Security Policies and AppArmor to provide blocking capabilities. + +## Overview + +Container Host Security can be used to monitor and block activity inside a container as well as to +enforce security policies across the entire Kubernetes cluster. Falco profiles allow for users to +define the activity they want to monitor for and detect. Among other things, this can include system +log entries, process starts, file activity, and network ports opened. AppArmor is used to block any +undesired activity via AppArmor profiles. These profiles are loaded into the cluster when +referenced by Pod Security Policies. + +By default, Container Host Security is deployed into the cluster in monitor mode only, with no +default profiles or rules running out-of-the-box. Activity monitoring and blocking begins only when +users define profiles for these technologies. + +## Installation + +See the [installation guide](quick_start_guide.md) for the recommended steps to install the +Container Host Security capabilities. This guide shows the recommended way of installing Container +Host Security through GMAv2. However, it's also possible to do a manual installation through our +Helm chart. + +## Features + +- Prevent containers from starting as root. +- Limit the privileges and system calls available to containers. +- Monitor system logs, process starts, files read/written/deleted, and network ports opened. +- Optionally block processes from starting or files from being read/written/deleted. + +## Supported container orchestrators + +Kubernetes v1.14+ is the only supported container orchestrator. OpenShift and other container +orchestrators aren't supported. + +## Supported Kubernetes providers + +The following cloud providers are supported: + +- Amazon EKS +- Google GKE + +Although Container Host Security may function on Azure or self-managed Kubernetes instances, it isn't +officially tested and supported on those providers. + +## Roadmap + +See the [Category Direction page](https://about.gitlab.com/direction/protect/container_host_security/) +for more information on the product direction of Container Host Security. diff --git a/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md b/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md new file mode 100644 index 00000000000..0c4ec72ed5b --- /dev/null +++ b/doc/user/project/clusters/protect/container_host_security/quick_start_guide.md @@ -0,0 +1,81 @@ +--- +stage: Protect +group: Container Security +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + +# Getting started with Container Host Security + +The following steps are recommended for installing Container Host Security. Although you can install +some capabilities through GMAv1, we [recommend](#using-gmav1-with-gmav2) that you install +applications through GMAv2 exclusively when using Container Network Security. + +## Installation steps + +The following steps are recommended to install and use Container Host Security through GitLab: + +1. [Install at least one runner and connect it to GitLab](https://docs.gitlab.com/runner/). +1. [Create a group](../../../../group/#create-a-new-group). +1. [Connect a Kubernetes cluster to the group](../../add_remove_clusters.md). +1. [Create a cluster management project and associate it with the Kubernetes cluster](../../../../clusters/management_project.md). + +1. Install and configure an Ingress node: + + - [Install the Ingress node via CI/CD (GMAv2)](../../../../clusters/applications.md#install-ingress-using-gitlab-cicd). + - [Determine the external endpoint via the manual method](../../../../clusters/applications.md#determining-the-external-endpoint-manually). + - Navigate to the Kubernetes page and enter the [DNS address for the external endpoint](../../index.md#base-domain) + into the **Base domain** field on the **Details** tab. Save the changes to the Kubernetes + cluster. + +1. [Install and configure Falco](../../../../clusters/applications.md#install-falco-using-gitlab-cicd) + for activity monitoring. +1. [Install and configure AppArmor](../../../../clusters/applications.md#install-apparmor-using-gitlab-cicd) + for activity blocking. +1. [Configure Pod Security Policies](../../../../clusters/applications.md#using-podsecuritypolicy-in-your-deployments) + (required to be able to load AppArmor profiles). + +It's possible to install and manage Falco and AppArmor in other ways, such as installing them +manually in a Kubernetes cluster and then connecting it back to GitLab. These methods aren't +supported or documented. + +## Viewing the logs + +Falco logs can be viewed by running the following command in your Kubernetes cluster: + +```shell +kubectl -n gitlab-managed-apps logs -l app=falco +``` + +## Troubleshooting + +### Trouble connecting to the cluster + +Your CI/CD pipeline may occasionally fail or have trouble connecting to the cluster. Here are some +initial troubleshooting steps that resolve the most common problems: + +1. [Clear the cluster cache](../../index.md#clearing-the-cluster-cache) +1. If things still aren't working, a more assertive set of actions may help get things back to a + good state: + + - Stop and [delete the problematic environment](../../../../../ci/environments/#delete-environments-through-the-ui) + in GitLab. + - Delete the relevant namespace in Kubernetes by running + `kubectl delete namespaces <insert-some-namespace-name>` in your Kubernetes cluster. + - Rerun the application project pipeline to redeploy the application. + +### Using GMAv1 with GMAv2 + +When GMAv1 and GMAv2 are used together on the same cluster, users may experience problems with +applications being uninstalled or removed from the cluster. This is because GMAv2 actively +uninstalls applications that are installed with GMAv1 and not configured to be installed with GMAv2. +It's possible to use a mixture of applications installed with GMAv1 and GMAv2 by ensuring that the +GMAv1 applications are installed **after** the GMAv2 cluster management project pipeline runs. GMAv1 +applications must be reinstalled after each run of that pipeline. This approach isn't recommended as +it's error-prone and can lead to downtime as applications are uninstalled and later reinstalled. +When using Container Network Security, the preferred and recommended path is to install all +necessary components with GMAv2 and the cluster management project. + +**Related documentation links:** + +- [GitLab Managed Apps v1 (GMAv1)](../../../../clusters/applications.md#install-with-one-click) +- [GitLab Managed Apps v2 (GMAv2)](../../../../clusters/management_project.md) diff --git a/doc/user/project/clusters/protect/container_network_security/index.md b/doc/user/project/clusters/protect/container_network_security/index.md new file mode 100644 index 00000000000..8299844e511 --- /dev/null +++ b/doc/user/project/clusters/protect/container_network_security/index.md @@ -0,0 +1,70 @@ +--- +stage: Protect +group: Container Security +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + +# Container Network Security + +Container Network Security in GitLab provides basic firewall functionality by leveraging Cilium +NetworkPolicies to filter traffic going in and out of the cluster as well as traffic between pods +inside the cluster. Container Network Security can be used to enforce L3, L4, and L7 policies and +can prevent an attacker with control over one pod from spreading laterally to access other pods in +the same cluster. Both Ingress and Egress rules are supported. + +By default, Cilium is deployed in Detection-only mode and only logs attack attempts. GitLab provides +a set of out-of-the-box policies as examples and to help users get started. These policies are +disabled by default, as they must usually be customized to match application-specific needs. + +## Installation + +See the [installation guide](quick_start_guide.md) for the recommended steps to install GitLab +Container Network Security. This guide shows the recommended way of installing Container Network +Security through GMAv2. However, it's also possible to install Cilium manually through our Helm +chart. + +## Features + +- GitLab managed installation of Cilium. +- Support for L3, L4, and L7 policies. +- Ability to export logs to a SIEM. +- Statistics page showing volume of packets processed and dropped over time (Gold/Ultimate users + only). +- Management of NetworkPolicies through code in a project (Available for auto DevOps users only). +- Management of CiliumNetworkPolicies through a UI policy manager (Gold/Ultimate users only). + +## Supported container orchestrators + +Kubernetes v1.14+ is the only supported container orchestrator. OpenShift and other container +orchestrators aren't supported. + +## Supported Kubernetes providers + +The following cloud providers are supported: + +- Amazon EKS +- Google GKE + +Although Container Network Security may function on Azure or self-managed Kubernetes instances, it +isn't officially tested and supported on those providers. + +## Supported NetworkPolicies + +GitLab only supports the use of CiliumNetworkPolicies. Although generic Kubernetes NetworkPolicies +or other kinds of NetworkPolicies may work, GitLab doesn't test or support them. + +## Managing NetworkPolicies through GitLab vs your cloud provider + +Some cloud providers offer integrations with Cilium or offer other ways to manage NetworkPolicies in +Kubernetes. GitLab Container Network Security doesn't support deployments that have NetworkPolicies +managed by an external provider. By choosing to manage NetworkPolicies through GitLab, you can take +advantage of the following benefits: + +- Support for handling NetworkPolicy infrastructure as code. +- Full revision history and audit log of all changes made. +- Ability to revert back to a previous version at any time. + +## Roadmap + +See the [Category Direction page](https://about.gitlab.com/direction/protect/container_network_security/) +for more information on the product direction of Container Network Security. diff --git a/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md b/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md new file mode 100644 index 00000000000..10f9380a1f2 --- /dev/null +++ b/doc/user/project/clusters/protect/container_network_security/quick_start_guide.md @@ -0,0 +1,153 @@ +--- +stage: Protect +group: Container Security +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + +# Getting started with Container Network Security + +The following steps are recommended for installing Container Network Security. Although you can +install some capabilities through GMAv1, we [recommend](#using-gmav1-with-gmav2) that you install +applications through GMAv2 exclusively when using Container Network Security. + +## Installation steps + +The following steps are recommended to install and use Container Network Security through GitLab: + +1. [Install at least one runner and connect it to GitLab](https://docs.gitlab.com/runner/). +1. [Create a group](../../../../group/#create-a-new-group). +1. [Connect a Kubernetes cluster to the group](../../add_remove_clusters.md). +1. [Create a cluster management project and associate it with the Kubernetes cluster](../../../../clusters/management_project.md). + +1. Install and configure an Ingress node: + + - [Install the Ingress node via CI/CD (GMAv2)](../../../../clusters/applications.md#install-ingress-using-gitlab-cicd). + - [Determine the external endpoint via the manual method](../../../../clusters/applications.md#determining-the-external-endpoint-manually). + - Navigate to the Kubernetes page and enter the [DNS address for the external endpoint](../../index.md#base-domain) + into the **Base domain** field on the **Details** tab. Save the changes to the Kubernetes + cluster. + +1. [Install and configure Cilium](../../../../clusters/applications.md#install-cilium-using-gitlab-cicd). +1. Be sure to restart all pods that were running before Cilium was installed by running this command + in your cluster: + + `kubectl get pods --all-namespaces -o custom-columns=NAMESPACE:.metadata.namespace,NAME:.metadata.name,HOSTNETWORK:.spec.hostNetwork --no-headers=true | grep '<none>' | awk '{print "-n "$1" "$2}' | xargs -L 1 -r kubectl delete pod` + +It's possible to install and manage Cilium in other ways. For example, you could use the GitLab Helm +chart to install Cilium manually in a Kubernetes cluster, and then connect it back to GitLab. +However, such methods aren't documented or officially supported by GitLab. + +## Managing Network Policies + +Managing NetworkPolicies through GitLab is advantageous over managing the policies in Kubernetes +directly. Kubernetes doesn't provide a GUI editor, a change control process, or a revision history. +Network Policies can be managed through GitLab in one of two ways: + +- Management through a YAML file in each application's project (for projects using Auto DevOps). For + more information, see the [Network Policy documentation](../../../../../topics/autodevops/stages.md#network-policy). +- Management through the GitLab Policy management UI (for projects not using Auto DevOps). For more + information, see the [Container Network Policy documentation](../../../../application_security/threat_monitoring/index.md#container-network-policy-management) (Ultimate/Gold only). + +Each method has benefits and drawbacks: + +| | YAML method | UI method (Ultimate/Gold only) | +|--|:------------|:-------------------------------| +| **Benefits** | A change control process is possible by requiring [MR Approvals](../../../merge_requests/merge_request_approvals.md). All changes are fully tracked and audited in the same way that Git tracks the history of any file in its repository. | The UI provides a simple rules editor for users who are less familiar with the YAML syntax of NetworkPolicies. This view is a live representation of the policies currently deployed in the Kubernetes cluster. The UI also allows for multiple network policies to be created per environment. | +| **Drawbacks** | Only one network policy can be deployed per environment (although that policy can be as detailed as needed). Also, if changes were made in Kubernetes directly rather than through the `auto-deploy-values.yaml` file, the YAML file's contents don't represent the actual state of policies deployed in Kubernetes. | Policy changes aren't audited and a change control process isn't available. | + +Users are encouraged to choose one of the two methods to manage their policies. If users attempt to +use both methods simultaneously, when the application project pipeline runs the contents of the +NetworkPolicy in the `auto-deploy-values.yaml` file may override policies configured in the UI +editor. + +## Monitoring throughput `**(ULTIMATE)**` + +To view statistics for Container Network Security, you must follow the installation steps above and +configure GitLab integration with Prometheus. Also, if you use custom Helm values for Cilium, you +must enable Hubble with flow metrics for each namespace by adding the following lines to +your [Cilium values](../../../../clusters/applications.md#install-cilium-using-gitlab-cicd): +your [Cilium values](../../../../clusters/applications.md#install-cilium-using-gitlab-cicd): + +```yaml +global: + hubble: + enabled: true + metrics: + enabled: + - 'flow:sourceContext=namespace;destinationContext=namespace' +``` + +Additional information about the statistics page is available in the +[documentation that describes the Threat Management UI](../../../../application_security/threat_monitoring/index.md#container-network-policy). + +## Forwarding logs to a SIEM + +Cilium logs can be forwarded to a SIEM or an external logging system through syslog protocol by +installing and configuring Fluentd. Fluentd can be installed through GitLab in two ways: + +- The [GMAv1 method](../../../../clusters/applications.md#fluentd) +- The [GMAv2 method](../../../../clusters/applications.md#install-fluentd-using-gitlab-cicd) + +GitLab strongly encourages using only the GMAv2 method to install Fluentd. + +## Viewing the logs + +Cilium logs can be viewed by running the following command in your Kubernetes cluster: + +```shell +kubectl -n gitlab-managed-apps logs -l k8s-app=cilium -c cilium-monitor +``` + +## Troubleshooting + +### Traffic is not being blocked as expected + +By default, Cilium is installed in Audit mode only, meaning that NetworkPolicies log policy +violations but don't block any traffic. To set Cilium to Blocking mode, you must add the following +lines to the `.gitlab/managed-apps/cilium/values.yaml` file in your cluster management project: + +```yaml +config: + policyAuditMode: false + +agent: + monitor: + eventTypes: ["drop"] +``` + +### Traffic is not being allowed as expected + +Keep in mind that when Cilium is set to blocking mode (rather than Audit mode), NetworkPolicies +operate on an allow-list basis. If one or more NetworkPolicies apply to a node, then all traffic +that doesn't match at least one Policy is blocked. To resolve, add NetworkPolicies defining the +traffic that you want to allow in the node. + +### Trouble connecting to the cluster + +Occasionally, your CI/CD pipeline may fail or have trouble connecting to the cluster. Here are some +initial troubleshooting steps that resolve the most common problems: + +1. [Clear the cluster cache](../../index.md#clearing-the-cluster-cache). +1. If things still aren't working, a more assertive set of actions may help get things back into a + good state: + + - Stop and [delete the problematic environment](../../../../../ci/environments/index.md#delete-environments-through-the-ui) in GitLab. + - Delete the relevant namespace in Kubernetes by running `kubectl delete namespaces <insert-some-namespace-name>` in your Kubernetes cluster. + - Rerun the application project pipeline to redeploy the application. + +### Using GMAv1 with GMAv2 + +When GMAv1 and GMAv2 are used together on the same cluster, users may experience problems with +applications being uninstalled or removed from the cluster. This is because GMAv2 actively +uninstalls applications that are installed with GMAv1 and not configured to be installed with GMAv2. +It's possible to use a mixture of applications installed with GMAv1 and GMAv2 by ensuring that the +GMAv1 applications are installed **after** the GMAv2 cluster management project pipeline runs. GMAv1 +applications must be reinstalled after each run of that pipeline. This approach isn't recommended as +it's error-prone and can lead to downtime as applications are uninstalled and later reinstalled. +When using Container Network Security, the preferred and recommended path is to install all +necessary components with GMAv2 and the cluster management project. + +**Related documentation links:** + +- [GitLab Managed Apps v1 (GMAv1)](../../../../clusters/applications.md#install-with-one-click) +- [GitLab Managed Apps v2 (GMAv2)](../../../../clusters/management_project.md) diff --git a/doc/user/project/clusters/protect/index.md b/doc/user/project/clusters/protect/index.md new file mode 100644 index 00000000000..c489a0ddd30 --- /dev/null +++ b/doc/user/project/clusters/protect/index.md @@ -0,0 +1,29 @@ +--- +stage: Protect +group: Container Security +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#designated-technical-writers +--- + +# Protecting your deployed applications + +GitLab makes it straightforward to protect applications deployed in [connected Kubernetes clusters](index.md). +These protections are available in the Kubernetes network layer and in the container itself. At +the network layer, the Container Network Security capabilities in GitLab provide basic firewall +functionality by leveraging Cilium NetworkPolicies to filter traffic going in and out of the cluster +and traffic between pods inside the cluster. Inside the container, Container Host Security provides +Intrusion Detection and Prevention capabilities that can monitor and block activity inside the +containers themselves. + +## Capabilities + +The following capabilities are available to protect deployed applications in Kubernetes: + +- Web Application Firewall + - [Overview](web_application_firewall/index.md) + - [Installation guide](web_application_firewall/quick_start_guide.md) +- Container Network Security + - [Overview](container_network_security/index.md) + - [Installation guide](container_network_security/quick_start_guide.md) +- Container Host Security + - [Overview](container_host_security/index.md) + - [Installation guide](container_host_security/quick_start_guide.md) diff --git a/doc/topics/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png Binary files differindex 2dd6df3d37b..2dd6df3d37b 100644 --- a/doc/topics/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png +++ b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_disabled_settings_v12_10.png diff --git a/doc/topics/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png Binary files differindex e88f62a2eba..e88f62a2eba 100644 --- a/doc/topics/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png +++ b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_installation_v12_10.png diff --git a/doc/topics/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png Binary files differindex 1c99d4f7f96..1c99d4f7f96 100644 --- a/doc/topics/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png +++ b/doc/user/project/clusters/protect/web_application_firewall/img/guide_waf_ingress_save_changes_v12_10.png diff --git a/doc/user/project/clusters/protect/web_application_firewall/index.md b/doc/user/project/clusters/protect/web_application_firewall/index.md new file mode 100644 index 00000000000..6e2e71c6ced --- /dev/null +++ b/doc/user/project/clusters/protect/web_application_firewall/index.md @@ -0,0 +1,103 @@ +--- +stage: Protect +group: Container Security +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Web Application Firewall + +WARNING: +The Web Application Firewall is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/271276) +in GitLab 13.6, and planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/271349) +in GitLab 14.0. + +A web application firewall (or WAF) filters, monitors, and blocks HTTP traffic to +and from a web application. By inspecting HTTP traffic, it can prevent attacks +stemming from web application security flaws. It can be used to detect SQL injection, +Cross-Site Scripting (XSS), Remote File Inclusion, Security Misconfigurations, and +much more. + +## Overview + +GitLab provides a WAF out of the box after Ingress is deployed. All you need to do is deploy your +application along with a service and Ingress resource. In the GitLab [Ingress](../../../../clusters/applications.md#ingress) +deployment, the [ModSecurity](https://modsecurity.org/) +module is loaded into Ingress-NGINX by default and monitors the traffic to the applications +which have an Ingress. The ModSecurity module runs with the [OWASP Core Rule Set (CRS)](https://coreruleset.org/) +by default. The OWASP CRS detects and logs a wide range of common attacks. + +By default, the WAF is deployed in Detection-only mode and only logs attack attempts. + +## Requirements + +The Web Application Firewall requires: + +- **Kubernetes** + + To enable the WAF, you need: + + - Kubernetes 1.12+. + - A load balancer. You can use NGINX-Ingress by deploying it to your + Kubernetes cluster by either: + - Using the [`nginx-ingress` Helm chart](https://github.com/helm/charts/tree/master/stable/nginx-ingress). + - Installing the [Ingress GitLab Managed App](../../../../clusters/applications.md#ingress) with WAF enabled. + +- **Configured Kubernetes objects** + + To use the WAF on an application, you need to deploy the following Kubernetes resources: + + - [Deployment](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) + - [Service](https://kubernetes.io/docs/concepts/services-networking/service/) + - [Ingress Resource](https://kubernetes.io/docs/concepts/services-networking/ingress/) + +## Quick start + +If you are using GitLab.com, see the [quick start guide](quick_start_guide.md) for +how to use the WAF with GitLab.com and a Kubernetes cluster on Google Kubernetes Engine (GKE). + +If you are using a self-managed instance of GitLab, you must configure the +[Google OAuth2 OmniAuth Provider](../../../../../integration/google.md) before +you can configure a cluster on GKE. Once this is set up, you can follow the steps on the +[quick start guide](quick_start_guide.md) +to get started. + +NOTE: +This guide shows how the WAF can be deployed using Auto DevOps. The WAF +is available by default to all applications no matter how they are deployed, +as long as they are using Ingress. + +## Network firewall vs. Web Application Firewall + +A network firewall or packet filter looks at traffic at the Network (L3) and Transport (L4) layers +of the [OSI Model](https://en.wikipedia.org/wiki/OSI_model), and denies packets from entry based on +a set of rules regarding the network in general. + +A Web Application Firewall operates at the Application (L7) layer of the OSI Model and can +examine all the packets traveling to and from a specific application. A WAF can set +more advanced rules around threat detection. + +## Features + +ModSecurity is enabled with the [OWASP Core Rule Set (CRS)](https://github.com/coreruleset/coreruleset/) by +default. The OWASP CRS logs attempts to the following attacks: + +- [SQL Injection](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_SQL_Injection) +- [Cross-Site Scripting](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_Cross-Site_Scripting_(XSS)) +- [Local File Inclusion](https://wiki.owasp.org/index.php/Testing_for_Local_File_Inclusion) +- [Remote File Inclusion](https://wiki.owasp.org/index.php/OWASP_Periodic_Table_of_Vulnerabilities_-_Remote_File_Inclusion) +- [Code Injection](https://wiki.owasp.org/index.php/Code_Injection) +- [Session Fixation](https://wiki.owasp.org/index.php/Session_fixation) +- [Scanner Detection](https://wiki.owasp.org/index.php/Category:Vulnerability_Scanning_Tools) +- [Metadata/Error Leakages](https://wiki.owasp.org/index.php/Improper_Error_Handling) + +It is good to have a basic knowledge of the following: + +- [Kubernetes](https://kubernetes.io/docs/home/) +- [Ingress](https://kubernetes.github.io/ingress-nginx/) +- [ModSecurity](https://www.modsecurity.org/) +- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/) + +## Roadmap + +You can find more information on the product direction of the WAF in +[Category Direction - Web Application Firewall](https://about.gitlab.com/direction/protect/web_application_firewall/). diff --git a/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md b/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md new file mode 100644 index 00000000000..e9a05b58fec --- /dev/null +++ b/doc/user/project/clusters/protect/web_application_firewall/quick_start_guide.md @@ -0,0 +1,265 @@ +--- +stage: Protect +group: Container Security +info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +--- + +# Getting started with the Web Application Firewall + +WARNING: +The Web Application Firewall is in its end-of-life process. It is [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/271276) +in GitLab 13.6, and planned for [removal](https://gitlab.com/gitlab-org/gitlab/-/issues/271349) +in GitLab 14.0. + +This is a step-by-step guide to help you use the GitLab [Web Application Firewall](index.md) after +deploying a project hosted on GitLab.com to Google Kubernetes Engine using [Auto DevOps](../../../../../topics/autodevops/index.md). + +The GitLab native Kubernetes integration is used, so you do not need +to create a Kubernetes cluster manually using the Google Cloud Platform console. +A simple application is created and deployed based on a GitLab template. + +These instructions also work for a self-managed GitLab instance. However, you +need to ensure your own [runners are configured](../../../../../ci/runners/README.md) and +[Google OAuth is enabled](../../../../../integration/google.md). + +The GitLab Web Application Firewall is deployed with [Ingress](../../../../clusters/applications.md#ingress), +so it is available to your applications no matter how you deploy them to Kubernetes. + +## Configuring your Google account + +Before creating and connecting your Kubernetes cluster to your GitLab project, +you need a Google Cloud Platform account. If you do not already have one, +sign up at <https://console.cloud.google.com>. You need to either sign in with an existing +Google account (for example, one that you use to access Gmail, Drive, etc.) or create a new one. + +1. To enable the required APIs and related services, follow the steps in the ["Before you begin" section of the Kubernetes Engine docs](https://cloud.google.com/kubernetes-engine/docs/quickstart#before-you-begin). +1. Make sure you have created a [billing account](https://cloud.google.com/billing/docs/how-to/manage-billing-account). + +NOTE: +Every new Google Cloud Platform (GCP) account receives [$300 in credit](https://console.cloud.google.com/freetrial), +and in partnership with Google, GitLab is able to offer an additional $200 for new GCP accounts to get started with the GitLab +Google Kubernetes Engine integration. All you have to do is [follow this link](https://cloud.google.com/partners/partnercredit/?PCN=a0n60000006Vpz4AAC) and apply for credit. + +## Creating a new project from a template + +We use a GitLab project templates to get started. As the name suggests, +those projects provide a barebones application built on some well-known frameworks. + +1. In GitLab, click the plus icon (**+**) at the top of the navigation bar and select + **New project**. +1. Go to the **Create from template** tab where you can choose for example a Ruby on + Rails, Spring, or NodeJS Express project. + Use the Ruby on Rails template. + + ![Select project template](../../../../../topics/autodevops/img/guide_project_template_v12_3.png) + +1. Give your project a name, optionally a description, and make it public so that + you can take advantage of the features available in the + [GitLab Gold plan](https://about.gitlab.com/pricing/#gitlab-com). + + ![Create project](../../../../../topics/autodevops/img/guide_create_project_v12_3.png) + +1. Click **Create project**. + +Now that the project is created, the next step is to create the Kubernetes cluster +to deploy this application under. + +## Creating a Kubernetes cluster from within GitLab + +1. On the project's landing page, click **Add Kubernetes cluster** + (note that this option is also available when you navigate to **Operations > Kubernetes**). + + ![Project landing page](../../../../../topics/autodevops/img/guide_project_landing_page_v12_10.png) + +1. On the **Create new cluster on GKE** tab, click **Sign in with Google**. + + ![Google sign in](../../../../../topics/autodevops/img/guide_google_signin_v12_3.png) + +1. Connect with your Google account and click **Allow** when asked (this + appears only the first time you connect GitLab with your Google account). + + ![Google auth](../../../../../topics/autodevops/img/guide_google_auth_v12_3.png) + +1. The last step is to provide the cluster details. + 1. Give it a name, leave the environment scope as is, and choose the GCP project under which to create the cluster. + (Per the instructions to [configure your Google account](#configuring-your-google-account), a project should have already been created for you.) + 1. Choose the [region/zone](https://cloud.google.com/compute/docs/regions-zones/) to create the cluster in. + 1. Enter the number of nodes you want it to have. + 1. Choose the [machine type](https://cloud.google.com/compute/docs/machine-types). + + ![GitLab GKE cluster details](../../../../../topics/autodevops/img/guide_gitlab_gke_details_v12_3.png) + +1. Click **Create Kubernetes cluster**. + +After a couple of minutes, the cluster is created. You can also see its +status on your [GCP dashboard](https://console.cloud.google.com/kubernetes). + +The next step is to install some applications on your cluster that are needed +to take full advantage of Auto DevOps. + +## Install Ingress + +The GitLab Kubernetes integration comes with some +[pre-defined applications](../../index.md#installing-applications) +for you to install. + +![Cluster applications](../../../../../topics/autodevops/img/guide_cluster_apps_v12_3.png) + +For this guide, we need to install Ingress. Ingress provides load balancing, +SSL termination, and name-based virtual hosting, using NGINX behind +the scenes. Make sure to switch the toggle to the enabled position before installing. + +Both logging and blocking modes are available for WAF. While logging mode is useful for +auditing anomalous traffic, blocking mode ensures the traffic doesn't reach past Ingress. + +![Cluster applications](img/guide_waf_ingress_installation_v12_10.png) + +After Ingress is installed, wait a few seconds and copy the IP address that +is displayed in order to add in your base **Domain** at the top of the page. For +the purpose of this guide, we use the one suggested by GitLab. Once you have +filled in the domain, click **Save changes**. + +![Cluster Base Domain](../../../../../topics/autodevops/img/guide_base_domain_v12_3.png) + +Prometheus should also be installed. It is an open-source monitoring and +alerting system that is used to supervise the deployed application. +Installing GitLab Runner is not required as we use the shared runners that +GitLab.com provides. + +## Enabling Auto DevOps (optional) + +Starting with GitLab 11.3, Auto DevOps is enabled by default. However, it is possible to disable +Auto DevOps at both the instance-level (for self-managed instances) and the group-level. +Follow these steps if Auto DevOps has been manually disabled: + +1. Navigate to **Settings > CI/CD > Auto DevOps**. +1. Select **Default to Auto DevOps pipeline**. +1. Select the [continuous deployment strategy](../../../../../topics/autodevops/index.md#deployment-strategy) + which automatically deploys the application to production once the pipeline + successfully runs on the `master` branch. +1. Click **Save changes**. + + ![Auto DevOps settings](../../../../../topics/autodevops/img/guide_enable_autodevops_v12_3.png) + +Once you complete all the above and save your changes, a new pipeline is +automatically created. To view the pipeline, go to **CI/CD > Pipelines**. + +![First pipeline](../../../../../topics/autodevops/img/guide_first_pipeline_v12_3.png) + +The next section explains what each pipeline job does. + +## Deploying the application + +By now you should see the pipeline running, but what is it running exactly? + +To navigate inside the pipeline, click its status badge (its status should be "Running"). +The pipeline is split into a few stages, each running a couple of jobs. + +![Pipeline stages](../../../../../topics/autodevops/img/guide_pipeline_stages_v13_0.png) + +In the **build** stage, the application is built into a Docker image and then +uploaded to your project's [Container Registry](../../../../packages/container_registry/index.md) +([Auto Build](../../../../../topics/autodevops/stages.md#auto-build)). + +In the **test** stage, GitLab runs various checks on the application. + +The **production** stage is run after the tests and checks finish, and it automatically +deploys the application in Kubernetes ([Auto Deploy](../../../../../topics/autodevops/stages.md#auto-deploy)). + +The **production** stage creates Kubernetes objects +like a Deployment, Service, and Ingress resource. The +application is monitored by the WAF automatically. + +## Validating Ingress is running ModSecurity + +Now we can make sure that Ingress is running properly with ModSecurity and send +a request to ensure our application is responding correctly. You must connect to +your cluster either using [Cloud Shell](https://cloud.google.com/shell/) or the [Google Cloud SDK](https://cloud.google.com/sdk/docs/install). + +1. After connecting to your cluster, check if the Ingress-NGINX controller is running and ModSecurity is enabled. + + This is done by running the following commands: + + ```shell + $ kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' + ingress-nginx-ingress-controller-55f9cf6584-dxljn 2/2 Running + + $ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- cat /etc/nginx/nginx.conf | grep 'modsecurity on;' + modsecurity on; + ``` + +1. Verify the Rails application has been installed properly. + + ```shell + $ kubectl get ns + auto-devv-2-16730183-production Active + + $ kubectl get pods -n auto-devv-2-16730183-production + NAME READY STATUS RESTARTS + production-5778cfcfcd-nqjcm 1/1 Running 0 + production-postgres-6449f8cc98-r7xgg 1/1 Running 0 + ``` + +1. To make sure the Rails application is responding, send a request to it by running: + + ```shell + $ kubectl get ing -n auto-devv-2-16730183-production + NAME HOSTS PORTS + production-auto-deploy fjdiaz-auto-devv-2.34.68.60.207.nip.io,le-16730183.34.68.60.207.nip.io 80, 443 + + $ curl --location --insecure "fjdiaz-auto-devv-2.34.68.60.207.nip.io" | grep 'Rails!' --after 2 --before 2 + <body> + <p>You're on Rails!</p> + </body> + ``` + +Now that we have confirmed our system is properly setup, we can go ahead and test +the WAF with OWASP CRS! + +## Testing out the OWASP Core Rule Set + +Now let's send a potentially malicious request, as if we were a scanner, +checking for vulnerabilities within our application and examine the ModSecurity logs: + +```shell +$ curl --location --insecure "fjdiaz-auto-devv-2.34.68.60.207.nip.io" --header "User-Agent: absinthe" | grep 'Rails!' --after 2 --before 2 +<body> + <p>You're on Rails!</p> +</body> + +$ kubectl -n gitlab-managed-apps exec -it $(kubectl get pods -n gitlab-managed-apps | grep 'ingress-controller' | awk '{print $1}') -- cat /var/log/modsec/audit.log | grep 'absinthe' +{ + "message": "Found User-Agent associated with security scanner", + "details": { + "match": "Matched \"Operator `PmFromFile' with parameter `scanners-user-agents.data' against variable `REQUEST_HEADERS:user-agent' (Value: `absinthe' )", + "reference": "o0,8v84,8t:lowercase", + "ruleId": "913100", + "file": "/etc/nginx/owasp-modsecurity-crs/rules/REQUEST-913-SCANNER-DETECTION.conf", + "lineNumber": "33", + "data": "Matched Data: absinthe found within REQUEST_HEADERS:user-agent: absinthe", + "severity": "2", + "ver": "OWASP_CRS/3.2.0", + "rev": "", + "tags": ["application-multi", "language-multi", "platform-multi", "attack-reputation-scanner", "OWASP_CRS", "OWASP_CRS/AUTOMATION/SECURITY_SCANNER", "WASCTC/WASC-21", "OWASP_TOP_10/A7", "PCI/6.5.10"], + "maturity": "0", + "accuracy": "0" + } +} +``` + +You can see that ModSecurity logs the suspicious behavior. By sending a request +with the `User Agent: absinthe` header, which [absinthe](https://github.com/cameronhotchkies/Absinthe), +a tool for testing for SQL injections uses, we can detect that someone was +searching for vulnerabilities on our system. Detecting scanners is useful, because we +can learn if someone is trying to exploit our system. + +## Conclusion + +You can now see the benefits of a using a Web Application Firewall. +ModSecurity and the OWASP Core Rule Set, offer many more benefits. +You can explore them in more detail: + +- [Category Direction - Web Application Firewall](https://about.gitlab.com/direction/protect/web_application_firewall/) +- [ModSecurity](https://www.modsecurity.org/) +- [OWASP Core Rule Set](https://github.com/coreruleset/coreruleset/) +- [AutoDevOps](../../../../../topics/autodevops/index.md) diff --git a/doc/user/project/clusters/runbooks/index.md b/doc/user/project/clusters/runbooks/index.md index 332c1f35d89..8572ab850e4 100644 --- a/doc/user/project/clusters/runbooks/index.md +++ b/doc/user/project/clusters/runbooks/index.md @@ -103,7 +103,7 @@ the components outlined above and the pre-loaded demo runbook. Enter these values, maintaining the single quotes as follows: ```sql - PRIVATE_TOKEN = 'n671WNGecHugsdEDPsyo' + PRIVATE_TOKEN = '<your_access_token>' PROJECT_ID = '1234567' ``` diff --git a/doc/user/project/clusters/securing.md b/doc/user/project/clusters/securing.md index fa80bd6423b..d734db6bac9 100644 --- a/doc/user/project/clusters/securing.md +++ b/doc/user/project/clusters/securing.md @@ -1,155 +1,8 @@ --- -stage: Protect -group: Container Security -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments +redirect_to: 'protect/index.md' --- -# Securing your deployed applications +This document was moved to [another location](protect/index.md). -GitLab makes it easy to secure applications deployed in [connected Kubernetes clusters](index.md). -You can benefit from the protection of a [Web Application Firewall](../../../topics/web_application_firewall/quick_start_guide.md), -[Network Policies](../../../topics/autodevops/stages.md#network-policy), -and [Container Host Security](../../clusters/applications.md#install-falco-using-gitlab-cicd). - -This page contains full end-to-end steps and instructions to connect your cluster to GitLab and -install these features, whether or not your applications are deployed through GitLab CI/CD. If you -use [Auto DevOps](../../../topics/autodevops/index.md) -to build and deploy your application with GitLab, see the documentation for the respective -[GitLab Managed Applications](../../clusters/applications.md) -above. - -## Overview - -At a high level, the required steps include the following: - -- Connect the cluster to GitLab. -- Set up one or more runners. -- Set up a cluster management project. -- Install a Web Application Firewall, and/or Network Policies, and/or Container Host - Security. -- Install Prometheus to get statistics and metrics in the - [threat monitoring](../../application_security/threat_monitoring/) - dashboard. - -### Requirements - -Minimum requirements (depending on the GitLab Manage Application you want to install): - -- Your cluster is connected to GitLab (ModSecurity, Cilium, and Falco). -- At least one runner is installed (Cilium and Falco only). - -### Understanding how GitLab Managed Apps are installed - -NOTE: -These diagrams use the term _Kubernetes_ for simplicity. In practice, Sidekiq connects to a Helm -command runner pod in the cluster. - -You install GitLab Managed Apps from the GitLab web interface with a one-click setup process. GitLab -uses Sidekiq (a background processing service) to facilitate this. - -```mermaid - sequenceDiagram - autonumber - GitLab->>+Sidekiq: Install a GitLab Managed App - Sidekiq->>+Kubernetes: Helm install - Kubernetes-->>-Sidekiq: Installation complete - Sidekiq-->>-GitLab: Refresh UI -``` - -Although this installation method is easier because it's a point-and-click action in the user -interface, it's inflexible and harder to debug. If something goes wrong, you can't see the -deployment logs. The Web Application Firewall feature uses this installation method. - -However, the next generation of GitLab Managed Apps V2 ([CI/CD-based GitLab Managed Apps](https://gitlab.com/groups/gitlab-org/-/epics/2103)) -don't use Sidekiq to deploy. All the applications are deployed using a GitLab CI/CD pipeline and -therefore, by runners. - -```mermaid -sequenceDiagram - autonumber - GitLab->>+GitLab: Trigger pipeline - GitLab->>+Runner: Run deployment job - Runner->>+Kubernetes: Helm install - Kubernetes-->>-Runner: Installation is complete - Runner-->>-GitLab: Report job status and update pipeline -``` - -Debugging is easier because you have access to the raw logs of these jobs (the Helm Tiller output is -available as an artifact in case of failure), and the flexibility is much better. Since these -deployments are only triggered when a pipeline is running (most likely when there's a new commit in -the cluster management repository), every action has a paper trail and follows the classic merge -request workflow (approvals, merge, deploy). The Network Policy (Cilium) Managed App, and Container -Host Security (Falco) are deployed with this model. - -## Connect the cluster to GitLab - -To deploy GitLab Managed Apps to your cluster, you must first -[add your cluster](add_remove_clusters.md) -to GitLab. Then [install](../../clusters/applications.md#install-with-one-click) -the Web Application Firewall from the project or group Kubernetes page. - -Note that your project doesn't have to be hosted or deployed through GitLab. You can manage a -cluster independent of the applications that use the cluster. - -## Set up a runner - -To install CI/CD-based GitLab Managed Apps, a pipeline using a runner must be running in -GitLab. You can [install a runner](../../clusters/applications.md#gitlab-runner) -in the Kubernetes cluster added in the previous step, or use one of the shared runners provided by -GitLab if you're using GitLab.com. - -With your cluster connected to GitLab and a runner in place, you can proceed to the next -steps and start installing the Cilium and Falco GitLab Managed Apps to secure your applications -hosted on this cluster. - -## Create a Cluster Management Project - -A [Cluster Management Project](../../clusters/management_project.md) -is a GitLab project that contains a `.gitlab-ci.yml` file to deploy GitLab Managed Apps to your -cluster. This project runs the required charts with the Kubernetes -[`cluster-admin`](https://kubernetes.io/docs/reference/access-authn-authz/rbac/#user-facing-roles) -privileges. - -The creation of this project starts like any other GitLab project. Use an empty -project and add a `gitlab-ci.yml` file at the root, containing this template: - -```yaml -include: - - template: Managed-Cluster-Applications.gitlab-ci.yml -``` - -To make this project a Cluster Management Project, follow these -[instructions](../../clusters/management_project.md#selecting-a-cluster-management-project). -This project can be designated as such even if your application isn't hosted on GitLab. In this -case, create a new empty project where you can select your newly created Cluster Management Project. - -## Install GitLab Container Network Policy - -GitLab Container Network Policy is based on [Cilium](https://cilium.io/). To -install the Cilium GitLab Managed App, add a -`.gitlab/managed-apps/config.yaml` file to your Cluster Management project: - -```yaml -# possible values are gke, eks or you can leave it blank -clusterType: gke - -cilium: - installed: true -``` - -Your application doesn't have to be managed or deployed by GitLab to leverage this feature. -[Read more](../../clusters/applications.md#install-cilium-using-gitlab-cicd) -about configuring Container Network Policy. - -## Install GitLab Container Host Security - -Similarly, you can install Container Host Security, based on -[Falco](https://falco.org/), in your `.gitlab/managed-apps/config.yaml`: - -```yaml -falco: - installed: true -``` - -[Read more](../../clusters/applications.md#install-falco-using-gitlab-cicd) -about configuring Container Host Security. +<!-- This redirect file can be deleted after <2021-04-01>. --> +<!-- Before deletion, see: https://docs.gitlab.com/ee/development/documentation/#move-or-rename-a-page --> diff --git a/doc/user/project/clusters/serverless/index.md b/doc/user/project/clusters/serverless/index.md index fcbf85121b2..043c5e4ca79 100644 --- a/doc/user/project/clusters/serverless/index.md +++ b/doc/user/project/clusters/serverless/index.md @@ -560,7 +560,6 @@ Or: By default, a GitLab serverless deployment is served over `http`. To serve over `https`, you must manually obtain and install TLS certificates. -12345678901234567890123456789012345678901234567890123456789012345678901234567890 The simplest way to accomplish this is to use Certbot to [manually obtain Let's Encrypt certificates](https://knative.dev/docs/serving/using-a-tls-cert/#using-certbot-to-manually-obtain-let-s-encrypt-certificates). Certbot is a free, open source software tool for automatically using Let’s Encrypt diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md index d0e89400d88..63ea84e42c9 100644 --- a/doc/user/project/code_owners.md +++ b/doc/user/project/code_owners.md @@ -225,6 +225,52 @@ the rules for "Groups" and "Documentation" sections: ![MR widget - Sectional Code Owners](img/sectional_code_owners_v13.2.png) +#### Optional Code Owners Sections **(PREMIUM)** + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232995) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.8 behind a feature flag, enabled by default. + +When you want to make a certain section optional, you can do so by adding a code owners section prepended with the caret `^` character. Approvals from owners listed in the section will **not** be required. For example: + +```plaintext +[Documentation] +*.md @root + +[Ruby] +*.rb @root + +^[Go] +*.go @root +``` + +The optional code owners section will be displayed in merge requests under the **Approval Rules** area: + +![MR widget - Optional Code Owners Sections](img/optional_code_owners_sections_v13_8.png) + +If a section is duplicated in the file, and one of them is marked as optional and the other isn't, the requirement prevails. + +For example, the code owners of the "Documentation" section below will still be required to approve merge requests: + +```plaintext +[Documentation] +*.md @root + +[Ruby] +*.rb @root + +^[Go] +*.go @root + +^[Documentation] +*.txt @root +``` + +Optional sections in the code owners file are currently treated as optional only +when changes are submitted via merge requests. If a change is submitted directly +to the protected branch, approval from code owners will still be required, even if the +section is marked as optional. We plan to change this in a +[future release](https://gitlab.com/gitlab-org/gitlab/-/issues/297638), +where direct pushes to the protected branch will be allowed for sections marked as optional. + ## Example `CODEOWNERS` file ```plaintext diff --git a/doc/user/project/deploy_boards.md b/doc/user/project/deploy_boards.md index 33bec99767a..831a8803622 100644 --- a/doc/user/project/deploy_boards.md +++ b/doc/user/project/deploy_boards.md @@ -5,9 +5,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w type: howto, reference --- -# Deploy Boards **(PREMIUM)** +# Deploy Boards **(CORE)** -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1589) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/1589) in [GitLab Premium](https://about.gitlab.com/pricing/) 9.0. +> - [Moved](<https://gitlab.com/gitlab-org/gitlab/-/issues/212320>) to GitLab Core in 13.8. GitLab Deploy Boards offer a consolidated view of the current health and status of each CI [environment](../../ci/environments/index.md) running on [Kubernetes](https://kubernetes.io), displaying the status @@ -53,8 +54,8 @@ specific environment, there are a lot of use cases. To name a few: - You want to promote what's running in staging, to production. You go to the environments list, verify that what's running in staging is what you think is running, then click on the [manual action](../../ci/yaml/README.md#whenmanual) to deploy to production. -- You trigger a deploy, and you've got lots of containers to upgrade so you know - it'll take a while (you've also throttled your deploy to only take down X +- You trigger a deploy, and you have many containers to upgrade so you know + this takes a while (you've also throttled your deploy to only take down X containers at a time). But you need to tell someone when it's deployed, so you go to the environments list, look at the production environment to see what the progress is in real-time as each pod is rolled. @@ -75,8 +76,8 @@ To display the Deploy Boards for a specific [environment](../../ci/environments/ 1. Have a Kubernetes cluster up and running. NOTE: - If you are using OpenShift, ensure that you're using the `Deployment` resource - instead of `DeploymentConfiguration`. Otherwise, the Deploy Boards won't render + If you're using OpenShift, ensure that you're using the `Deployment` resource + instead of `DeploymentConfiguration`. Otherwise, the Deploy Boards don't render correctly. For more information, read the [OpenShift docs](https://docs.openshift.com/container-platform/3.7/dev_guide/deployments/kubernetes_deployments.html#kubernetes-deployments-vs-deployment-configurations) and [GitLab issue #4584](https://gitlab.com/gitlab-org/gitlab/-/issues/4584). @@ -84,7 +85,7 @@ To display the Deploy Boards for a specific [environment](../../ci/environments/ 1. [Configure GitLab Runner](../../ci/runners/README.md) with the [`docker`](https://docs.gitlab.com/runner/executors/docker.html) or [`kubernetes`](https://docs.gitlab.com/runner/executors/kubernetes.html) executor. 1. Configure the [Kubernetes integration](clusters/index.md) in your project for the - cluster. The Kubernetes namespace is of particular note as you will need it + cluster. The Kubernetes namespace is of particular note as you need it for your deployment scripts (exposed by the `KUBE_NAMESPACE` environment variable). 1. Ensure Kubernetes annotations of `app.gitlab.com/env: $CI_ENVIRONMENT_SLUG` and `app.gitlab.com/app: $CI_PROJECT_PATH_SLUG` are applied to the @@ -94,7 +95,7 @@ To display the Deploy Boards for a specific [environment](../../ci/environments/ than one. These resources should be contained in the namespace defined in the Kubernetes service setting. You can use an [Autodeploy](../../topics/autodevops/stages.md#auto-deploy) `.gitlab-ci.yml` template which has predefined stages and commands to use, and automatically - applies the annotations. Each project will need to have a unique namespace in + applies the annotations. Each project must have a unique namespace in Kubernetes as well. The image below demonstrates how this is shown inside Kubernetes. @@ -105,7 +106,7 @@ To display the Deploy Boards for a specific [environment](../../ci/environments/ re-deploy your application. If you are using Auto DevOps, this will be done automatically and no action is necessary. - If you are using GCP to manage clusters, you can see the deployment details in GCP itself by going to **Workloads > deployment name > Details**: + If you use GCP to manage clusters, you can see the deployment details in GCP itself by navigating to **Workloads > deployment name > Details**: ![Deploy Boards Kubernetes Label](img/deploy_boards_kubernetes_label.png) @@ -141,7 +142,7 @@ spec: app.gitlab.com/env: ${CI_ENVIRONMENT_SLUG} ``` -The annotations will be applied to the deployments, replica sets, and pods. By changing the number of replicas, like `kubectl scale --replicas=3 deploy APPLICATION_NAME -n ${KUBE_NAMESPACE}`, you can follow the instances' pods from the board. +The annotations are applied to the deployments, replica sets, and pods. By changing the number of replicas, like `kubectl scale --replicas=3 deploy APPLICATION_NAME -n ${KUBE_NAMESPACE}`, you can follow the instances' pods from the board. NOTE: The YAML file is static. If you apply it using `kubectl apply`, you must diff --git a/doc/user/project/deploy_keys/index.md b/doc/user/project/deploy_keys/index.md index 39b790544c1..93ed1030e1f 100644 --- a/doc/user/project/deploy_keys/index.md +++ b/doc/user/project/deploy_keys/index.md @@ -92,7 +92,7 @@ There are three lists of Project Deploy Keys: ![Deploy Keys section](img/deploy_keys_v13_0.png) -After you add a key, it will be enabled for this project by default, and it'll appear +After you add a key, it's enabled for this project by default and it appears in the **Enabled deploy keys** tab. In the **Privately accessible deploy keys** tab, you can enable a private key which @@ -111,7 +111,7 @@ and `read-write` access. NOTE: If you have enabled a privately or publicly accessible or deploy key for your project, and if you then update the access level for this key from `read-only` to -`read-write`, the change will be only for the **current project**. +`read-write`, the change is only for the **current project**. ### Public deploy keys @@ -131,7 +131,7 @@ Instance administrators can add public deploy keys: ![Public Deploy Keys section](img/public_deploy_key_v13_0.png) -After adding a key, it will be available to any shared systems. Project maintainers +After adding a key, it's available to any shared systems. Project maintainers or higher can [authorize a public deploy key](#project-deploy-keys) to start using it with the project. NOTE: @@ -155,8 +155,8 @@ until a project maintainer chooses to make use of it. ### Deploy Key cannot push to a protected branch -If the owner of this deploy key does not have access to a [protected -branch](../protected_branches.md), then this deploy key won't have access to +If the owner of this deploy key doesn't have access to a [protected +branch](../protected_branches.md), then this deploy key doesn't have access to the branch either. In addition to this, choosing the **No one** value in [the "Allowed to push" section](../protected_branches.md#configuring-protected-branches) means that no users **and** no services using deploy keys can push to that selected branch. diff --git a/doc/user/project/deploy_tokens/img/deploy_tokens_ui.png b/doc/user/project/deploy_tokens/img/deploy_tokens_ui.png Binary files differindex 83f59b8f6f0..4ab6a45aee1 100644 --- a/doc/user/project/deploy_tokens/img/deploy_tokens_ui.png +++ b/doc/user/project/deploy_tokens/img/deploy_tokens_ui.png diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md index ac19c44c58a..5a62730d989 100644 --- a/doc/user/project/deploy_tokens/index.md +++ b/doc/user/project/deploy_tokens/index.md @@ -36,7 +36,7 @@ project. Alternatively, you can also create [group-scoped deploy tokens](#group- 1. Choose the [desired scopes](#limiting-scopes-of-a-deploy-token). 1. Select **Create deploy token**. 1. Save the deploy token somewhere safe. After you leave or refresh - the page, **you won't be able to access it again**. + the page, **you can't access it again**. ![Personal access tokens page](img/deploy_tokens_ui.png) @@ -89,7 +89,7 @@ Replace `<username>` and `<deploy_token>` with the proper values. ### Read Container Registry images -To read the container registry images, you'll need to: +To read the container registry images, you must: 1. Create a Deploy Token with `read_registry` as a scope. 1. Take note of your `username` and `token`. @@ -106,7 +106,7 @@ pull images from your Container Registry. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22743) in GitLab 12.10. -To push the container registry images, you'll need to: +To push the container registry images, you must: 1. Create a Deploy Token with `write_registry` as a scope. 1. Take note of your `username` and `token`. @@ -123,7 +123,7 @@ push images to your Container Registry. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) in GitLab 13.0. -To pull packages in the GitLab package registry, you'll need to: +To pull packages in the GitLab package registry, you must: 1. Create a Deploy Token with `read_package_registry` as a scope. 1. Take note of your `username` and `token`. @@ -134,7 +134,7 @@ To pull packages in the GitLab package registry, you'll need to: > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213566) in GitLab 13.0. -To upload packages in the GitLab package registry, you'll need to: +To upload packages in the GitLab package registry, you must: 1. Create a Deploy Token with `write_package_registry` as a scope. 1. Take note of your `username` and `token`. @@ -160,7 +160,7 @@ To use a group deploy token: 1. Use it the same way you use a project deploy token when [cloning a repository](#git-clone-a-repository). -The scopes applied to a group deploy token (such as `read_repository`) will +The scopes applied to a group deploy token (such as `read_repository`) apply consistently when cloning the repository of related projects. ### GitLab Deploy Token @@ -168,7 +168,7 @@ apply consistently when cloning the repository of related projects. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18414) in GitLab 10.8. There's a special case when it comes to Deploy Tokens. If a user creates one -named `gitlab-deploy-token`, the username and token of the Deploy Token will be +named `gitlab-deploy-token`, the username and token of the Deploy Token is automatically exposed to the CI/CD jobs as environment variables: `CI_DEPLOY_USER` and `CI_DEPLOY_PASSWORD`, respectively. diff --git a/doc/user/project/description_templates.md b/doc/user/project/description_templates.md index db2631f9596..3108bdda7a0 100644 --- a/doc/user/project/description_templates.md +++ b/doc/user/project/description_templates.md @@ -108,7 +108,7 @@ you should be fine. ![Default issue description templates](img/description_templates_issue_settings.png) After you add the description, hit **Save changes** for the settings to take -effect. Now, every time a new merge request or issue is created, it is +effect. Now, every time a new merge request or issue is created, it is pre-filled with the text you entered in the template(s). ## Description template example diff --git a/doc/user/project/img/canary_weight.png b/doc/user/project/img/canary_weight.png Binary files differindex e6544358c15..fe17c62bdea 100644 --- a/doc/user/project/img/canary_weight.png +++ b/doc/user/project/img/canary_weight.png diff --git a/doc/user/project/img/description_templates_issue_settings.png b/doc/user/project/img/description_templates_issue_settings.png Binary files differindex 657b6ae1269..7f354f7c288 100644 --- a/doc/user/project/img/description_templates_issue_settings.png +++ b/doc/user/project/img/description_templates_issue_settings.png diff --git a/doc/user/project/img/optional_code_owners_sections_v13_8.png b/doc/user/project/img/optional_code_owners_sections_v13_8.png Binary files differnew file mode 100644 index 00000000000..7a5a2fab6e3 --- /dev/null +++ b/doc/user/project/img/optional_code_owners_sections_v13_8.png diff --git a/doc/user/project/img/protected_branches_deploy_keys_v13_5.png b/doc/user/project/img/protected_branches_deploy_keys_v13_5.png Binary files differindex 6eda7a671b2..ccd23dbe160 100644 --- a/doc/user/project/img/protected_branches_deploy_keys_v13_5.png +++ b/doc/user/project/img/protected_branches_deploy_keys_v13_5.png diff --git a/doc/user/project/img/service_desk_custom_email_address_v13_0.png b/doc/user/project/img/service_desk_custom_email_address_v13_0.png Binary files differdeleted file mode 100644 index 3789e039904..00000000000 --- a/doc/user/project/img/service_desk_custom_email_address_v13_0.png +++ /dev/null diff --git a/doc/user/project/img/service_desk_enabled.png b/doc/user/project/img/service_desk_enabled.png Binary files differdeleted file mode 100644 index 33d51227e5f..00000000000 --- a/doc/user/project/img/service_desk_enabled.png +++ /dev/null diff --git a/doc/user/project/import/github.md b/doc/user/project/import/github.md index 8b6d86b14c9..c135b1be54a 100644 --- a/doc/user/project/import/github.md +++ b/doc/user/project/import/github.md @@ -63,7 +63,7 @@ must meet one of the following conditions prior to the import: - Have previously logged in to a GitLab account using the GitHub icon. - Have a GitHub account with a publicly visible [primary email address](https://docs.github.com/en/free-pro-team@latest/rest/reference/users#get-a-user) - on their profile that matches their GitLab account's email address. + on their profile that matches their GitLab account's primary or secondary email address. If a user referenced in the project is not found in the GitLab database, the project creator (typically the user that initiated the import process) is set as the author/assignee, but a note on the issue mentioning the original diff --git a/doc/user/project/integrations/gitlab_slack_application.md b/doc/user/project/integrations/gitlab_slack_application.md index 8344baebd82..ccf4b6cb303 100644 --- a/doc/user/project/integrations/gitlab_slack_application.md +++ b/doc/user/project/integrations/gitlab_slack_application.md @@ -37,7 +37,7 @@ integration settings. Keep in mind that you need to have the appropriate permissions for your Slack team in order to be able to install a new application, read more in Slack's -docs on [Adding an app to your workspace](https://slack.com/help/articles/202035138-Add-an-app-to-your-workspace). +docs on [Adding an app to your workspace](https://slack.com/help/articles/202035138-Add-apps-to-your-Slack-workspace). To enable the GitLab service for your Slack team: diff --git a/doc/user/project/integrations/img/webhooks_ssl.png b/doc/user/project/integrations/img/webhooks_ssl.png Binary files differdeleted file mode 100644 index e5777a2e99b..00000000000 --- a/doc/user/project/integrations/img/webhooks_ssl.png +++ /dev/null diff --git a/doc/user/project/integrations/jira_integrations.md b/doc/user/project/integrations/jira_integrations.md index f15a5ee4429..3c91fd3549f 100644 --- a/doc/user/project/integrations/jira_integrations.md +++ b/doc/user/project/integrations/jira_integrations.md @@ -30,6 +30,6 @@ The following Jira integrations allow different types of cross-referencing betwe | Mention of Jira issue ID in GitLab issue/MR is reflected in the Jira issue | Yes, as a Jira comment with the GitLab issue/MR title and a link back to it. Its first mention also adds the GitLab page to the Jira issue under “Web links”. | Yes, in the issue’s Development panel | | Mention of Jira issue ID in GitLab commit message is reflected in the issue | Yes. The entire commit message is added to the Jira issue as a comment and under “Web links”, each with a link back to the commit in GitLab. | Yes, in the issue’s Development panel and optionally with a custom comment on the Jira issue using Jira Smart Commits. | | Mention of Jira issue ID in GitLab branch names is reflected in Jira issue | No | Yes, in the issue’s Development panel | -| Record Jira time tracking info against an issue | No | Yes. Time can be specified via Jira Smart Commits. | +| Record Jira time tracking information against an issue | No | Yes. Time can be specified via Jira Smart Commits. | | Transition or close a Jira issue with a Git commit or merge request | Yes. Only a single transition type, typically configured to close the issue by setting it to Done. | Yes. Transition to any state using Jira Smart Commits. | | Display a list of Jira issues | Yes **(PREMIUM)** | No | diff --git a/doc/user/project/integrations/prometheus.md b/doc/user/project/integrations/prometheus.md index 9d7960790ff..959c4cc623b 100644 --- a/doc/user/project/integrations/prometheus.md +++ b/doc/user/project/integrations/prometheus.md @@ -199,7 +199,6 @@ to integrate with. ### Precedence with multiple Prometheus configurations -12345678901234567890123456789012345678901234567890123456789012345678901234567890 Although you can enable both a [manual configuration](#manual-configuration-of-prometheus) and [auto configuration](#managed-prometheus-on-kubernetes) of Prometheus, you can use only one: diff --git a/doc/user/project/integrations/webhooks.md b/doc/user/project/integrations/webhooks.md index d8b51e8b777..47a44e53b47 100644 --- a/doc/user/project/integrations/webhooks.md +++ b/doc/user/project/integrations/webhooks.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Webhooks -Project webhooks allow you to trigger a URL if for example new code is pushed or +Project webhooks allow you to trigger a percent-encoded URL if, for example, new code is pushed or a new issue is created. You can configure webhooks to listen for specific events like pushes, issues or merge requests. GitLab sends a POST request with data to the webhook URL. @@ -28,32 +28,15 @@ notify bug tracking systems. Webhooks can be used to update an external issue tracker, trigger CI jobs, update a backup mirror, or even deploy to your production server. -They are available **per project** for GitLab Community Edition, -and **per project and per group** for **GitLab Enterprise Edition**. -Navigate to the webhooks page at your project's **Settings > Webhooks**. +Webhooks are available: + +- Per project, at a project's **Settings > Webhooks** menu. **(CORE)** +- Additionally per group, at a group's **Settings > Webhooks** menu. **(PREMIUM)** NOTE: On GitLab.com, the [maximum number of webhooks and their size](../../../user/gitlab_com/index.md#webhooks) per project, and per group, is limited. -## Version history - -Starting from GitLab 8.5: - -- the `repository` key is deprecated in favor of the `project` key -- the `project.ssh_url` key is deprecated in favor of the `project.git_ssh_url` key -- the `project.http_url` key is deprecated in favor of the `project.git_http_url` key - -Starting from GitLab 11.1, the logs of webhooks are automatically removed after -one month. - -Starting from GitLab 11.2: - -- The `description` field for issues, merge requests, comments, and wiki pages - is rewritten so that simple Markdown image references (like - `![](/uploads/...)`) have their target URL changed to an absolute URL. See - [image URL rewriting](#image-url-rewriting) for more details. - ## Possible uses for webhooks - You can set up a webhook in GitLab to send a notification to @@ -91,8 +74,6 @@ be self-signed. You can turn this off in the webhook settings in your GitLab projects. -![SSL Verification](img/webhooks_ssl.png) - ## Branch filtering > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/20338) in GitLab 11.3. @@ -115,6 +96,10 @@ attribute only contains the first 20 for performance reasons. Loading detailed commit data is expensive. Note that despite only 20 commits being present in the `commits` attribute, the `total_commits_count` attribute contains the actual total. +NOTE: +If a branch creation push event is generated without new commits being introduced, the +`commits` attribute in the payload is empty. + Also, if a single push includes changes for more than three (by default, depending on [`push_event_hooks_limit` setting](../../../api/settings.md#list-of-settings-that-can-be-accessed-via-api-calls)) branches, this hook isn't executed. @@ -276,6 +261,7 @@ X-Gitlab-Event: Issue Hook "object_kind": "issue", "event_type": "issue", "user": { + "id": 1, "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", @@ -439,9 +425,11 @@ X-Gitlab-Event: Note Hook { "object_kind": "note", "user": { + "id": 1, "name": "Administrator", "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", + "email": "admin@example.com" }, "project_id": 5, "project":{ @@ -519,9 +507,11 @@ X-Gitlab-Event: Note Hook { "object_kind": "note", "user": { + "id": 1, "name": "Administrator", "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", + "email": "admin@example.com" }, "project_id": 5, "project":{ @@ -646,9 +636,11 @@ X-Gitlab-Event: Note Hook { "object_kind": "note", "user": { + "id": 1, "name": "Administrator", "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", + "email": "admin@example.com" }, "project_id": 5, "project":{ @@ -752,9 +744,11 @@ X-Gitlab-Event: Note Hook { "object_kind": "note", "user": { + "id": 1, "name": "Administrator", "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", + "email": "admin@example.com" }, "project_id": 5, "project":{ @@ -828,9 +822,11 @@ X-Gitlab-Event: Merge Request Hook { "object_kind": "merge_request", "user": { + "id": 1, "name": "Administrator", "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=40\u0026d=identicon", + "email": "admin@example.com" }, "project": { "id": 1, @@ -989,9 +985,11 @@ X-Gitlab-Event: Wiki Page Hook { "object_kind": "wiki_page", "user": { + "id": 1, "name": "Administrator", "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80\u0026d=identicon", + "email": "admin@example.com" }, "project": { "id": 1, @@ -1080,6 +1078,7 @@ X-Gitlab-Event: Pipeline Hook "url": "http://192.168.64.1:3005/gitlab-org/gitlab-test/merge_requests/1" }, "user":{ + "id": 1, "name": "Administrator", "username": "root", "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", @@ -1121,9 +1120,11 @@ X-Gitlab-Event: Pipeline Hook "manual": true, "allow_failure": false, "user":{ + "id": 1, "name": "Administrator", "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", + "email": "admin@example.com" }, "runner": null, "artifacts_file":{ @@ -1143,9 +1144,11 @@ X-Gitlab-Event: Pipeline Hook "manual": false, "allow_failure": false, "user":{ + "id": 1, "name": "Administrator", "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", + "email": "admin@example.com" }, "runner": { "id":380987, @@ -1170,9 +1173,11 @@ X-Gitlab-Event: Pipeline Hook "manual": false, "allow_failure": false, "user":{ + "id": 1, "name": "Administrator", "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", + "email": "admin@example.com" }, "runner": { "id":380987, @@ -1197,9 +1202,11 @@ X-Gitlab-Event: Pipeline Hook "manual": false, "allow_failure": false, "user":{ + "id": 1, "name": "Administrator", "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", + "email": "admin@example.com" }, "runner": { "id":380987, @@ -1224,9 +1231,11 @@ X-Gitlab-Event: Pipeline Hook "manual": false, "allow_failure": false, "user":{ + "id": 1, "name": "Administrator", "username": "root", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", + "email": "admin@example.com" }, "runner": null, "artifacts_file":{ @@ -1273,7 +1282,8 @@ X-Gitlab-Event: Job Hook "id": 3, "name": "User", "email": "user@gitlab.com", - "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon" + "avatar_url": "http://www.gravatar.com/avatar/e32bd13e2add097461cb96824b7a829c?s=80\u0026d=identicon", + "email": "admin@example.com" }, "commit": { "id": 2366, @@ -1349,6 +1359,7 @@ X-Gitlab-Event: Deployment Hook }, "short_sha": "279484c0", "user": { + "id": 1, "name": "Administrator", "username": "root", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", @@ -1362,11 +1373,18 @@ X-Gitlab-Event: Deployment Hook Note that `deployable_id` is the ID of the CI job. -### Member events +### Group member events **(PREMIUM)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/260347) in GitLab 13.7. -Triggered when a user is added as a group member. +Member events are triggered when: + +- A user is added as a group member +- The access level of a user has changed +- The expiration date for user access has been updated +- A user has been removed from the group + +#### Add member to group **Request Header**: @@ -1394,6 +1412,62 @@ X-Gitlab-Event: Member Hook } ``` +#### Update member access level or expiration date + +**Request Header**: + +```plaintext +X-Gitlab-Event: Member Hook +``` + +**Request Body**: + +```json +{ + "created_at": "2020-12-11T04:57:22Z", + "updated_at": "2020-12-12T08:48:19Z", + "group_name": "webhook-test", + "group_path": "webhook-test", + "group_id": 100, + "user_username": "test_user", + "user_name": "Test User", + "user_email": "testuser@webhooktest.com", + "user_id": 64, + "group_access": "Developer", + "group_plan": null, + "expires_at": "2020-12-20T00:00:00Z", + "event_name": "user_update_for_group" +} +``` + +#### Remove member from group + +**Request Header**: + +```plaintext +X-Gitlab-Event: Member Hook +``` + +**Request Body**: + +```json +{ + "created_at": "2020-12-11T04:57:22Z", + "updated_at": "2020-12-12T08:52:34Z", + "group_name": "webhook-test", + "group_path": "webhook-test", + "group_id": 100, + "user_username": "test_user", + "user_name": "Test User", + "user_email": "testuser@webhooktest.com", + "user_id": 64, + "group_access": "Guest", + "group_plan": null, + "expires_at": "2020-12-14T00:00:00Z", + "event_name": "user_remove_from_group" +} +``` + ### Feature Flag events Triggered when a feature flag is turned on or off. @@ -1428,6 +1502,7 @@ X-Gitlab-Event: Feature Flag Hook "http_url":"http://example.com/gitlabhq/gitlab-test.git" }, "user": { + "id": 1, "name": "Administrator", "username": "root", "avatar_url": "https://www.gravatar.com/avatar/e64c7d89f26bd1972efa854d13d7dd61?s=80&d=identicon", @@ -1554,7 +1629,7 @@ Markdown features, like link labels. ## Testing webhooks You can trigger the webhook manually. Sample data from the project is used. -> For example: for triggering `Push Events` your project should have at least one commit. +For example, for triggering `Push Events` your project should have at least one commit. ![Webhook testing](img/webhook_testing.png) diff --git a/doc/user/project/issue_board.md b/doc/user/project/issue_board.md index e0f66013454..7119970fca0 100644 --- a/doc/user/project/issue_board.md +++ b/doc/user/project/issue_board.md @@ -4,7 +4,7 @@ group: Project Management info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments --- -# Issue Boards +# Issue Boards **(CORE)** > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/5554) in [GitLab 8.11](https://about.gitlab.com/releases/2016/08/22/gitlab-8-11-released/#issue-board). @@ -233,17 +233,18 @@ advanced functionality is present in [higher tiers only](https://about.gitlab.co ### Configurable issue boards **(STARTER)** -> [Introduced](https://about.gitlab.com/releases/2017/11/22/gitlab-10-2-released/#issue-boards-configuration) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2. +> - [Introduced](https://about.gitlab.com/releases/2017/11/22/gitlab-10-2-released/#issue-boards-configuration) in GitLab 10.2. +> - Setting current iteration as scope [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/196804) in GitLab 13.8. -An issue board can be associated with a GitLab [Milestone](milestones/index.md#milestones), -[Labels](labels.md), Assignee and Weight +An issue board can be associated with a [milestone](milestones/index.md#milestones), +[labels](labels.md), assignee, weight, and current [iteration](../group/iterations/index.md), which automatically filter the board issues accordingly. This allows you to create unique boards according to your team's need. ![Create scoped board](img/issue_board_creation_v13_6.png) You can define the scope of your board when creating it or by clicking the **Edit board** button. -After a milestone, assignee or weight is assigned to an issue board, you can no longer +After a milestone, iteration, assignee, or weight is assigned to an issue board, you can no longer filter through these in the search bar. In order to do that, you need to remove the desired scope (for example, milestone, assignee, or weight) from the issue board. @@ -320,7 +321,8 @@ As in other list types, click the trash icon to remove a list. ### Group issues in swimlanes **(PREMIUM)** -> Grouping by epic [introduced](https://gitlab.com/groups/gitlab-org/-/epics/3352) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6. +> - Grouping by epic [introduced](https://gitlab.com/groups/gitlab-org/-/epics/3352) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.6. +> - Editing issue titles in the issue sidebar [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232745) in GitLab 13.8. With swimlanes you can visualize issues grouped by epic. Your issue board keeps all the other features, but with a different visual organization of issues. @@ -336,6 +338,19 @@ To group issues by epic in an issue board: ![Epics Swimlanes](img/epics_swimlanes_v13.6.png) +To edit an issue without leaving this view, select the issue card (not its title), and a sidebar +appears on the right. There you can see and edit the issue's: + +- Title +- Assignees +- Epic **PREMIUM** +- Milestone +- Time tracking value (view only) +- Due date +- Labels +- Weight +- Notifications setting + You can also [drag issues](#drag-issues-between-lists) to change their position and epic assignment: - To reorder an issue, drag it to the new position within a list. diff --git a/doc/user/project/issues/confidential_issues.md b/doc/user/project/issues/confidential_issues.md index 02cb0313a74..d4fbc4fb10b 100644 --- a/doc/user/project/issues/confidential_issues.md +++ b/doc/user/project/issues/confidential_issues.md @@ -29,8 +29,8 @@ confidential checkbox and hit **Save changes**. There are two ways to change an issue's confidentiality. -The first way is to edit the issue and mark/unmark the confidential checkbox. -Once you save the issue, it will change the confidentiality of the issue. +The first way is to edit the issue and toggle the confidentiality checkbox. +After you save the issue, the confidentiality of the issue is updated. The second way is to locate the Confidentiality section in the sidebar and click **Edit**. A popup should appear and give you the option to turn on or turn off confidentiality. @@ -46,20 +46,19 @@ system note in the issue's comments. ## Indications of a confidential issue -NOTE: -If you don't have [enough permissions](#permissions-and-access-to-confidential-issues), -you won't be able to see the confidential issues at all. - There are a few things that visually separate a confidential issue from a regular one. In the issues index page view, you can see the eye-slash icon next to the issues that are marked as confidential. ![Confidential issues index page](img/confidential_issues_index_page.png) +If you don't have [enough permissions](#permissions-and-access-to-confidential-issues), +you cannot see confidential issues at all. + --- Likewise, while inside the issue, you can see the eye-slash icon right next to -the issue number, but there is also an indicator in the comment area that the +the issue number. There is also an indicator in the comment area that the issue you are commenting on is confidential. ![Confidential issue page](img/confidential_issues_issue_page.png) @@ -83,7 +82,7 @@ project's search results respectively. | Maintainer access | Guest access | | :-----------: | :----------: | -| ![Confidential issues search master](img/confidential_issues_search_master.png) | ![Confidential issues search guest](img/confidential_issues_search_guest.png) | +| ![Confidential issues search by maintainer](img/confidential_issues_search_master.png) | ![Confidential issues search by guest](img/confidential_issues_search_guest.png) | ## Merge Requests for Confidential Issues @@ -93,24 +92,24 @@ To help prevent confidential information being leaked from a public project in the process of resolving a confidential issue, confidential issues can be resolved by creating a merge request from a private fork. -The merge request created will target the default branch of the private fork, +The created merge request targets the default branch of the private fork, not the default branch of the public upstream project. This prevents the merge request, branch, and commits entering the public repository, and revealing -confidential information prematurely. When the confidential commits are ready -to be made public, this can be done by opening a merge request from the private -fork to the public upstream project. +confidential information prematurely. To make a confidential commit public, +open a merge request from the private fork to the public upstream project. -NOTE: -If you create a long-lived private fork in the same group or in a sub-group of -the original upstream, all the users with Developer membership to the public -project will also have the same permissions in the private project. This way, -all the Developers, who have access to view confidential issues, will have a -streamlined workflow for fixing them. +Permissions are inherited from parent groups. Developers have the same permissions +for private forks created in the same group or in a sub-group of the original +Permissions are inherited from parent groups. When private forks are created +in the same group or sub-group as the original upstream repository, users +receive the same permissions in both projects. This inheritance ensures +Developer users have the needed permissions to both view confidential issues and +resolve them. ### How it works On a confidential issue, a **Create confidential merge request** button is -available. Clicking on it will open a dropdown where you can choose to +available. Clicking on it opens a dropdown where you can choose to **Create confidential merge request and branch** or **Create branch**: | Create confidential merge request | Create branch | @@ -121,12 +120,12 @@ The **Project** dropdown includes the list of private forks the user is a member of as at least a Developer and merge requests are enabled. Whenever the **Branch name** and **Source (branch or tag)** fields change, the -availability of the target or source branch will be checked. Both branches should -be available in the private fork selected. +availability of the target and source branch are checked. Both branches should +be available in the selected private fork. -By clicking the **Create confidential merge request** button, GitLab will create +By clicking the **Create confidential merge request** button, GitLab creates the branch and merge request in the private fork. When you choose -**Create branch**, GitLab will only create the branch. +**Create branch**, GitLab creates only the branch. -Once the branch is created in the private fork, developers can now push code to +After the branch is created in the private fork, developers can push code to that branch to fix the confidential issue. diff --git a/doc/user/project/issues/crosslinking_issues.md b/doc/user/project/issues/crosslinking_issues.md index b5d3b71e679..250fa618dd8 100644 --- a/doc/user/project/issues/crosslinking_issues.md +++ b/doc/user/project/issues/crosslinking_issues.md @@ -31,10 +31,9 @@ git commit -m "this is my commit message. Related to https://gitlab.com/<usernam Of course, you can replace `gitlab.com` with the URL of your own GitLab instance. -NOTE: -Linking your first commit to your issue is going to be relevant +Linking your first commit to your issue is relevant for tracking your process with [GitLab Value Stream Analytics](https://about.gitlab.com/stages-devops-lifecycle/value-stream-analytics/). -It will measure the time taken for planning the implementation of that issue, +It measures the time taken for planning the implementation of that issue, which is the time between creating an issue and making the first commit. ## From Related Issues @@ -45,7 +44,7 @@ issues regarding the same topic. You do that as explained above, when [mentioning an issue from a commit message](#from-commit-messages). -When mentioning issue `#111` in issue `#222`, issue `#111` will also display a notification +When mentioning issue `#111` in issue `#222`, issue `#111` also displays a notification in its tracker. That is, you only need to mention the relationship once for it to display in both issues. The same is valid when mentioning issues in [merge requests](#from-merge-requests). @@ -56,8 +55,8 @@ display in both issues. The same is valid when mentioning issues in [merge reque Mentioning issues in merge request comments works exactly the same way as they do for [related issues](#from-related-issues). -When you mention an issue in a merge request description, it will simply -[link the issue and merge request together](#from-related-issues). Additionally, +When you mention an issue in a merge request description, it +[links the issue and merge request together](#from-related-issues). Additionally, you can also [set an issue to close automatically](managing_issues.md#closing-issues-automatically) as soon as the merge request is merged. diff --git a/doc/user/project/issues/csv_export.md b/doc/user/project/issues/csv_export.md index 023a8ee57bc..e7cd1377603 100644 --- a/doc/user/project/issues/csv_export.md +++ b/doc/user/project/issues/csv_export.md @@ -53,7 +53,7 @@ Exported issues are always sorted by `Issue ID`. > > **Weight** and **Locked** columns were [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/5300) in GitLab Starter 10.8. -Data wis encoded with a comma as the column delimiter, with `"` used to quote fields if needed, and newlines to separate rows. The first row contains the headers, which are listed in the following table along with a description of the values: +Data is encoded with a comma as the column delimiter, with `"` used to quote fields if needed, and newlines to separate rows. The first row contains the headers, which are listed in the following table along with a description of the values: | Column | Description | |---------|-------------| diff --git a/doc/user/project/issues/due_dates.md b/doc/user/project/issues/due_dates.md index 63cd784333a..34e9340067c 100644 --- a/doc/user/project/issues/due_dates.md +++ b/doc/user/project/issues/due_dates.md @@ -11,14 +11,14 @@ info: To determine the technical writer assigned to the Stage/Group associated w Please read through the [GitLab Issue Documentation](index.md) for an overview on GitLab Issues. Due dates can be used in issues to keep track of deadlines and make sure features are -shipped on time. Users must have at least [Reporter permissions](../../permissions.md) -to be able to edit them, but they can be seen by everybody with permission to view -the issue. +shipped on time. Users need at least [Reporter permissions](../../permissions.md) +to be able to edit the due date. All users with permission to view +the issue can view the due date. ## Setting a due date -When creating or editing an issue, you can click in the **due date** field and a calendar -will appear to help you choose the date you want. To remove the date, select the date +When creating an issue, select the **Due date** field to make a calendar +appear for choosing the date. To remove the date, select the date text and delete it. The date is related to the server's timezone, not the timezone of the user setting the due date. @@ -37,18 +37,17 @@ The last way to set a due date is by using [quick actions](../quick_actions.md), ## Making use of due dates -Issues that have a due date can be easily seen in the issue tracker, -displaying a date next to them. Issues where the date is overdue will have -the icon and the date colored red. You can sort issues by those that are -`Due soon` or `Due later` from the dropdown menu on the right. - -![Issues with due dates in the issues index page](img/due_dates_issues_index_page.png) +You can see issues with their due dates in the [issues list](index.md#issues-list). +Overdue issues have their icon and date colored red. +To sort issues by their due dates, select **Due date** from the dropdown menu on the right. +Issues are then sorted from the earliest due date to the latest. +To display isses with the latest due dates at the top, select **Sort direction** (**{sort-lowest}**). Due dates also appear in your [to-do list](../../todos.md). ![Issues with due dates in the to dos](img/due_dates_todos.png) -The day before an open issue is due, an email will be sent to all participants +The day before an open issue is due, an email is sent to all participants of the issue. Like the due date, the "day before the due date" is determined by the server's timezone. diff --git a/doc/user/project/issues/img/due_dates_issues_index_page.png b/doc/user/project/issues/img/due_dates_issues_index_page.png Binary files differdeleted file mode 100644 index 94679436b32..00000000000 --- a/doc/user/project/issues/img/due_dates_issues_index_page.png +++ /dev/null diff --git a/doc/user/project/issues/index.md b/doc/user/project/issues/index.md index 05e7eb3021a..74311eefd83 100644 --- a/doc/user/project/issues/index.md +++ b/doc/user/project/issues/index.md @@ -22,8 +22,8 @@ their implementation between: They can also be used for a variety of other purposes, customized to your needs and workflow. -Issues are always associated with a specific project, but if you have multiple projects in a group, -you can also view all the issues collectively at the group level. +Issues are always associated with a specific project. If you have multiple projects in a group, +you can view all of the issues collectively at the group level. **Common use cases include:** @@ -91,9 +91,13 @@ must be set. ## Viewing and managing issues -While you can view and manage the full details of an issue on the [issue page](#issue-page), -you can also work with multiple issues at a time using the [Issues List](#issues-list), -[Issue Boards](#issue-boards), Issue references, and [Epics](#epics). **(PREMIUM)** +While you can view and manage details of an issue on the [issue page](#issue-page), +you can also work with multiple issues at a time using: + +- [Issues List](#issues-list). +- [Issue Boards](#issue-boards). +- Issue references. +- [Epics](#epics) **(PREMIUM)**. Key actions for issues include: @@ -117,14 +121,17 @@ and modify them if you have the necessary [permissions](../../permissions.md). Assignees in the sidebar are updated in real time. This feature is **disabled by default**. To enable, you need to enable [ActionCable in-app mode](https://docs.gitlab.com/omnibus/settings/actioncable.html). -### Issues list +### Issues List + +![Project Issues List view](img/project_issues_list_view.png) + +On the Issues List, you can: -![Project issues list view](img/project_issues_list_view.png) +- View all issues in a project when opening the Issues List from a project context. +- View all issues in a groups's projects when opening the Issues List from a group context. -On the Issues List, you can view all issues in the current project, or from multiple -projects when opening the Issues List from the higher-level group context. Filter the -issue list with a [search query](../../search/index.md#filtering-issue-and-merge-request-lists), -including specific metadata, such as label(s), assignees(s), status, and more. From this +You can filter the Issues List with a [search query](../../search/index.md#filtering-issue-and-merge-request-lists), +including specific metadata, such as labels, assignees, status, and more. From this view, you can also make certain changes [in bulk](../bulk_editing.md) to the displayed issues. For more information, see the [Issue Data and Actions](issue_data_and_actions.md) page @@ -140,21 +147,21 @@ You can sort a list of issues in several ways, for example by issue creation dat labels or their assignees**(PREMIUM)**. They offer the flexibility to manage issues using highly customizable workflows. -You can reorder issues within a column. If you drag an issue card to another column, its -associated label or assignee will change to match that of the new column. The entire +You can reorder issues in the column. If you drag an issue card to another column, its +associated label or assignee is changed to match that of the new column. The entire board can also be filtered to only include issues from a certain milestone or an overarching label. ### Design Management With [Design Management](design_management.md), you can upload design -assets to issues and view them all together to easily share and -collaborate with your team. +assets to issues and view them all together for sharing and +collaboration with your team. ### Epics **(PREMIUM)** [Epics](../../group/epics/index.md) let you manage your portfolio of projects more -efficiently and with less effort by tracking groups of issues that share a theme, across +efficiently and with less effort. Epics track groups of issues that share a theme, across projects and milestones. ### Related issues @@ -179,10 +186,10 @@ message in the Activity stream about the reference, with a link to the other iss To prevent duplication of issues for the same topic, GitLab searches for similar issues when new issues are being created. -When typing in the title in the **New Issue** page, GitLab searches titles and descriptions -across all issues the user has access to in the current project. Up to five similar issues, -sorted by most recently updated, are displayed below the title box. Note that this feature -requires [GraphQL](../../../api/graphql/index.md) to be enabled. +As you type in the title field of the **New Issue** page, GitLab searches titles and descriptions +across all issues to in the current project. Only issues you have access to are returned. +Up to five similar issues, sorted by most recently updated, are displayed below the title box. +[GraphQL](../../../api/graphql/index.md) must be enabled to use this feature. ![Similar issues](img/similar_issues.png) @@ -193,8 +200,8 @@ requires [GraphQL](../../../api/graphql/index.md) to be enabled. > - Issue health status visible in issue lists [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/45141) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.6. > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/213567) in GitLab 13.7. -To help you track the status of your issues, you can assign a status to each issue to flag work -that's progressing as planned or needs attention to keep on schedule: +To help you track issue statuses, you can assign a status to each issue. +This marks issues as progressing as planned or needs attention to keep on schedule: - **On track** (green) - **Needs attention** (amber) diff --git a/doc/user/project/issues/issue_data_and_actions.md b/doc/user/project/issues/issue_data_and_actions.md index 2520a562f1e..4c8630581f5 100644 --- a/doc/user/project/issues/issue_data_and_actions.md +++ b/doc/user/project/issues/issue_data_and_actions.md @@ -35,6 +35,7 @@ The numbers in the image correspond to the following features: - **12.** [Participants](#participants) - **13.** [Notifications](#notifications) - **14.** [Reference](#reference) +- [Issue email](#email) - **15.** [Edit](#edit) - **16.** [Description](#description) - **17.** [Mentions](#mentions) @@ -174,6 +175,13 @@ for the issue. Notifications are automatically enabled after you participate in `foo/bar#xxx`, where `foo` is the `username` or `groupname`, `bar` is the `project-name`, and `xxx` is the issue number. +### Email + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18816) in GitLab 13.8. + +Guest users can see a button in the right sidebar to copy the email address for the issue. +Sending an email to this address creates a comment containing the email body. + ### Edit Clicking this icon opens the issue for editing. All the fields which diff --git a/doc/user/project/issues/managing_issues.md b/doc/user/project/issues/managing_issues.md index 03060ca720c..ef860df054e 100644 --- a/doc/user/project/issues/managing_issues.md +++ b/doc/user/project/issues/managing_issues.md @@ -19,16 +19,16 @@ Key actions for issues include: ## Create a new issue -When you create a new issue, you'll be prompted to fill in the [data and fields of the issue](issue_data_and_actions.md), +When you create a new issue, you are prompted to fill in the [data and fields of the issue](issue_data_and_actions.md), as illustrated below. If you know the values you want to assign to an issue, you can use the -[Quick actions](../quick_actions.md) feature to input values, instead of selecting them from lists. +[Quick actions](../quick_actions.md) feature to input values. While creating an issue, you can associate it to an existing epic from current group by selecting it using **Epic** dropdown. ### Accessing the New Issue form -There are many ways to get to the New Issue form from within a project: +There are many ways to get to the New Issue form from a project's page: - Navigate to your **Project's Dashboard** > **Issues** > **New Issue**: @@ -75,9 +75,8 @@ using the dropdown button at the top-right of the page. ![Select project to create issue](img/select_project_from_group_level_issue_tracker.png) -We'll keep track of the project you selected most recently, and use it as the default -for your next visit. This should save you a lot of time and clicks, if you mostly -create issues for the same project. +The project you selected most recently becomes the default for your next visit. +This should save you a lot of time and clicks, if you mostly create issues for the same project. ![Create issue from group-level issue tracker](img/create_issue_from_group_level_issue_tracker.png) @@ -90,22 +89,22 @@ the appropriate project and followed up from there. ### New issue via email A link to **Email a new issue to this project** is displayed at the bottom of a project's -**Issues List** page, if your GitLab instance has [incoming email](../../../administration/incoming_email.md) -configured. +**Issues List** page. The link is shown only if your GitLab instance has [incoming email](../../../administration/incoming_email.md) +configured and there is at least one issue in the issue list. ![Bottom of a project issues page](img/new_issue_from_email.png) When you click this link, an email address is generated and displayed, which should be used by **you only**, to create issues in this project. You can save this address as a -contact in your email client for easy access. +contact in your email client for quick access. WARNING: This is a private email address, generated just for you. **Keep it to yourself**, as anyone who knows it can create issues or merge requests as if they -were you. If the address is compromised, or you'd like it to be regenerated for -any reason, click **Email a new issue to this project** again and click the reset link. +were you. If the address is compromised, or you want to regenerate it, +click **Email a new issue to this project**, followed by **reset it**. -Sending an email to this address will create a new issue in your name for +Sending an email to this address creates a new issue associated with your account for this project, where: - The email subject becomes the issue title. @@ -118,15 +117,15 @@ older format is still supported, allowing existing aliases or contacts to contin ### New issue via URL with prefilled fields -You can link directly to the new issue page for a given project, with prefilled -field values using query string parameters in a URL. This is useful for embedding -a URL in an external HTML page, and also certain scenarios where you want the user to -create an issue with certain fields prefilled. +To link directly to the new issue page with prefilled fields, use query +string parameters in a URL. You can embed a URL in an external +HTML page, or create issues with certain +fields prefilled. The title, description, description template, and confidential fields can be prefilled using this method. You cannot pre-fill both the description and description template -fields in the same URL (since a description template also populates the description -field). +fields in the same URL because a description template also populates the description +field. | Field | URL Parameter Name | Notes | |----------------------|-----------------------|-------------------------------------------------------| @@ -147,9 +146,9 @@ Follow these examples to form your new issue URL with prefilled fields. ## Moving Issues -Moving an issue will copy it to a new location (project), and close it in the old project, -but it will not be deleted. There will also be a system note added to both issues -indicating where it came from and went to. +Moving an issue copies it to the target project, and closes it in the originating project. +The original issue is not deleted. A system note, which indicates +where it came from and went to, is added to both issues. The "Move issue" button is at the bottom of the right-sidebar when viewing the issue. @@ -157,7 +156,9 @@ The "Move issue" button is at the bottom of the right-sidebar when viewing the i ### Moving Issues in Bulk -If you have advanced technical skills you can also bulk move all the issues from one project to another in the rails console. The below script will move all the issues from one project to another that are not in status **closed**. +If you have advanced technical skills you can also bulk move all the issues from +one project to another in the rails console. The below script moves all issues +that are not in status **closed** from one project to another. To access rails console run `sudo gitlab-rails console` on the GitLab server and run the below script. Please be sure to change `project`, `admin_user`, and `target_project` to your values. @@ -193,23 +194,18 @@ from its list and dropping it into the **Closed** list. ### Closing issues automatically -NOTE: -For performance reasons, automatic issue closing is disabled for the very first -push from an existing repository. - -When a commit or merge request resolves one or more issues, it is possible to have -these issues closed automatically when the commit or merge request reaches the project's -default branch. +When a commit or merge request resolves issues, the issues +can be closed automatically when the commit reaches the project's default branch. If a commit message or merge request description contains text matching a [defined pattern](#default-closing-pattern), -all issues referenced in the matched text will be closed. This happens when the commit +all issues referenced in the matched text are closed. This happens when the commit is pushed to a project's [**default** branch](../repository/branches/index.md#default-branch), or when a commit or merge request is merged into it. For example, if `Closes #4, #6, Related to #5` is included in a Merge Request -description, issues `#4` and `#6` will close automatically when the MR is merged, but not `#5`. +description, issues `#4` and `#6` are closed automatically when the MR is merged, but not `#5`. Using `Related to` flags `#5` as a [related issue](related_issues.md), -but it will not close automatically. +but is not closed automatically. ![merge request closing issue when merged](img/merge_request_closes_issue.png) @@ -219,9 +215,12 @@ If the issue is in a different repository than the MR, add the full URL for the Closes #4, #6, and https://gitlab.com/<username>/<projectname>/issues/<xxx> ``` +For performance reasons, automatic issue closing is disabled for the very first +push from an existing repository. + #### Default closing pattern -When not specified, the default issue closing pattern as shown below will be used: +When not specified, this default issue closing pattern is used: ```shell \b((?:[Cc]los(?:e[sd]?|ing)|\b[Ff]ix(?:e[sd]|ing)?|\b[Rr]esolv(?:e[sd]?|ing)|\b[Ii]mplement(?:s|ed|ing)?)(:?) +(?:(?:issues? +)?%{issue_ref}(?:(?: *,? +and +| *,? *)?)|([A-Z][A-Z0-9_]+-\d+))+) @@ -251,8 +250,8 @@ This commit is also related to #17 and fixes #18, #19 and https://gitlab.example.com/group/otherproject/issues/23. ``` -will close `#18`, `#19`, `#20`, and `#21` in the project this commit is pushed to, -as well as `#22` and `#23` in `group/otherproject`. `#17` won't be closed as it does +closes `#18`, `#19`, `#20`, and `#21` in the project this commit is pushed to, +as well as `#22` and `#23` in `group/otherproject`. `#17` is not closed as it does not match the pattern. It works with multi-line commit messages as well as one-liners when used from the command line with `git commit -m`. @@ -261,14 +260,14 @@ when used from the command line with `git commit -m`. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/19754) in GitLab 12.7. The automatic issue closing feature can be disabled on a per-project basis -within the [project's repository settings](../settings/index.md). Referenced -issues will still be displayed as such but won't be closed automatically. +in the [project's repository settings](../settings/index.md). Referenced +issues are still displayed, but are not closed automatically. ![disable issue auto close - settings](img/disable_issue_auto_close.png) This only applies to issues affected by new merge requests or commits. Already closed issues remain as-is. Disabling automatic issue closing only affects merge -requests *within* the project and won't prevent other projects from closing it +requests *in* the project and does not prevent other projects from closing it via cross-project issues. #### Customizing the issue closing pattern **(CORE ONLY)** diff --git a/doc/user/project/labels.md b/doc/user/project/labels.md index 2f8603e1db0..22dfd3a8719 100644 --- a/doc/user/project/labels.md +++ b/doc/user/project/labels.md @@ -57,7 +57,7 @@ and edit labels. ### Project labels -> Showing all inherited labels [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241990) in 13.5. +> Showing all inherited labels [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/241990) in GitLab 13.5. To view the project labels list, navigate to the project and click **Issues > Labels**. The list includes all labels that are defined at the project level, as well as all @@ -228,7 +228,7 @@ to label notifications for the project only, or the whole group. > - Priority sorting is based on the highest priority label only. [This discussion](https://gitlab.com/gitlab-org/gitlab/-/issues/14523) considers changing this. Labels can have relative priorities, which are used in the **Label priority** and -**Priority** sort orders of the epic, issue, and merge request list pages. Prioritization +**Priority** sort orders of issues and merge request list pages. Prioritization for both group and project labels happens at the project level, and cannot be done from the group label list. @@ -241,7 +241,7 @@ means higher priority. ![Drag to change label priority](img/labels_drag_priority_v12_1.gif) -On the epic, merge request, and issue list pages (for both groups and projects) you +On the merge request and issue list pages (for both groups and projects) you can sort by `Label priority` or `Priority`. If you sort by `Label priority`, GitLab uses this sort comparison order: diff --git a/doc/user/project/members/img/access_requests_management.png b/doc/user/project/members/img/access_requests_management.png Binary files differdeleted file mode 100644 index 9a1c9621e41..00000000000 --- a/doc/user/project/members/img/access_requests_management.png +++ /dev/null diff --git a/doc/user/project/members/img/access_requests_management_13_8.png b/doc/user/project/members/img/access_requests_management_13_8.png Binary files differnew file mode 100644 index 00000000000..950ef4dec01 --- /dev/null +++ b/doc/user/project/members/img/access_requests_management_13_8.png diff --git a/doc/user/project/members/img/add_user_email_accept.png b/doc/user/project/members/img/add_user_email_accept.png Binary files differdeleted file mode 100644 index cbee9e08c70..00000000000 --- a/doc/user/project/members/img/add_user_email_accept.png +++ /dev/null diff --git a/doc/user/project/members/img/add_user_email_accept_13_8.png b/doc/user/project/members/img/add_user_email_accept_13_8.png Binary files differnew file mode 100644 index 00000000000..ed980036af5 --- /dev/null +++ b/doc/user/project/members/img/add_user_email_accept_13_8.png diff --git a/doc/user/project/members/img/add_user_email_ready.png b/doc/user/project/members/img/add_user_email_ready.png Binary files differdeleted file mode 100644 index 0066eb3427b..00000000000 --- a/doc/user/project/members/img/add_user_email_ready.png +++ /dev/null diff --git a/doc/user/project/members/img/add_user_email_ready_13_8.png b/doc/user/project/members/img/add_user_email_ready_13_8.png Binary files differnew file mode 100644 index 00000000000..a610b46a176 --- /dev/null +++ b/doc/user/project/members/img/add_user_email_ready_13_8.png diff --git a/doc/user/project/members/img/add_user_email_search.png b/doc/user/project/members/img/add_user_email_search.png Binary files differdeleted file mode 100644 index 66bcd6aad80..00000000000 --- a/doc/user/project/members/img/add_user_email_search.png +++ /dev/null diff --git a/doc/user/project/members/img/add_user_email_search_13_8.png b/doc/user/project/members/img/add_user_email_search_13_8.png Binary files differnew file mode 100644 index 00000000000..934cf19bd3d --- /dev/null +++ b/doc/user/project/members/img/add_user_email_search_13_8.png diff --git a/doc/user/project/members/img/add_user_give_permissions.png b/doc/user/project/members/img/add_user_give_permissions.png Binary files differdeleted file mode 100644 index 376a3eefccc..00000000000 --- a/doc/user/project/members/img/add_user_give_permissions.png +++ /dev/null diff --git a/doc/user/project/members/img/add_user_give_permissions_13_8.png b/doc/user/project/members/img/add_user_give_permissions_13_8.png Binary files differnew file mode 100644 index 00000000000..1916d056a52 --- /dev/null +++ b/doc/user/project/members/img/add_user_give_permissions_13_8.png diff --git a/doc/user/project/members/img/add_user_import_members_from_another_project.png b/doc/user/project/members/img/add_user_import_members_from_another_project.png Binary files differdeleted file mode 100644 index cb3b70bd4b5..00000000000 --- a/doc/user/project/members/img/add_user_import_members_from_another_project.png +++ /dev/null diff --git a/doc/user/project/members/img/add_user_import_members_from_another_project_13_8.png b/doc/user/project/members/img/add_user_import_members_from_another_project_13_8.png Binary files differnew file mode 100644 index 00000000000..a6dddec3fb7 --- /dev/null +++ b/doc/user/project/members/img/add_user_import_members_from_another_project_13_8.png diff --git a/doc/user/project/members/img/add_user_imported_members.png b/doc/user/project/members/img/add_user_imported_members.png Binary files differdeleted file mode 100644 index 51fd7688890..00000000000 --- a/doc/user/project/members/img/add_user_imported_members.png +++ /dev/null diff --git a/doc/user/project/members/img/add_user_imported_members_13_8.png b/doc/user/project/members/img/add_user_imported_members_13_8.png Binary files differnew file mode 100644 index 00000000000..725e447604f --- /dev/null +++ b/doc/user/project/members/img/add_user_imported_members_13_8.png diff --git a/doc/user/project/members/img/add_user_list_members.png b/doc/user/project/members/img/add_user_list_members.png Binary files differdeleted file mode 100644 index e0fa404288d..00000000000 --- a/doc/user/project/members/img/add_user_list_members.png +++ /dev/null diff --git a/doc/user/project/members/img/add_user_list_members_13_8.png b/doc/user/project/members/img/add_user_list_members_13_8.png Binary files differnew file mode 100644 index 00000000000..b8c0160c6d8 --- /dev/null +++ b/doc/user/project/members/img/add_user_list_members_13_8.png diff --git a/doc/user/project/members/img/add_user_search_people.png b/doc/user/project/members/img/add_user_search_people.png Binary files differdeleted file mode 100644 index 41767a9167c..00000000000 --- a/doc/user/project/members/img/add_user_search_people.png +++ /dev/null diff --git a/doc/user/project/members/img/add_user_search_people_13_8.png b/doc/user/project/members/img/add_user_search_people_13_8.png Binary files differnew file mode 100644 index 00000000000..e9aa58512ab --- /dev/null +++ b/doc/user/project/members/img/add_user_search_people_13_8.png diff --git a/doc/user/project/members/img/other_group_sees_shared_project_v13_6.png b/doc/user/project/members/img/other_group_sees_shared_project_v13_6.png Binary files differdeleted file mode 100644 index e6e3f8f043b..00000000000 --- a/doc/user/project/members/img/other_group_sees_shared_project_v13_6.png +++ /dev/null diff --git a/doc/user/project/members/img/other_group_sees_shared_project_v13_8.png b/doc/user/project/members/img/other_group_sees_shared_project_v13_8.png Binary files differnew file mode 100644 index 00000000000..aa2aaf071e1 --- /dev/null +++ b/doc/user/project/members/img/other_group_sees_shared_project_v13_8.png diff --git a/doc/user/project/members/img/project_groups_tab_13_8.png b/doc/user/project/members/img/project_groups_tab_13_8.png Binary files differnew file mode 100644 index 00000000000..5d7948f0761 --- /dev/null +++ b/doc/user/project/members/img/project_groups_tab_13_8.png diff --git a/doc/user/project/members/img/project_members.png b/doc/user/project/members/img/project_members.png Binary files differdeleted file mode 100644 index 218f5a24d2e..00000000000 --- a/doc/user/project/members/img/project_members.png +++ /dev/null diff --git a/doc/user/project/members/img/project_members_13_8.png b/doc/user/project/members/img/project_members_13_8.png Binary files differnew file mode 100644 index 00000000000..9120d471b3b --- /dev/null +++ b/doc/user/project/members/img/project_members_13_8.png diff --git a/doc/user/project/members/img/share_project_with_groups_tab_v13_6.png b/doc/user/project/members/img/share_project_with_groups_tab_v13_6.png Binary files differdeleted file mode 100644 index 7d83659ef7a..00000000000 --- a/doc/user/project/members/img/share_project_with_groups_tab_v13_6.png +++ /dev/null diff --git a/doc/user/project/members/img/share_project_with_groups_tab_v13_8.png b/doc/user/project/members/img/share_project_with_groups_tab_v13_8.png Binary files differnew file mode 100644 index 00000000000..6cbbb386396 --- /dev/null +++ b/doc/user/project/members/img/share_project_with_groups_tab_v13_8.png diff --git a/doc/user/project/members/img/share_project_with_groups_v13_6.png b/doc/user/project/members/img/share_project_with_groups_v13_6.png Binary files differdeleted file mode 100644 index 121e77671a3..00000000000 --- a/doc/user/project/members/img/share_project_with_groups_v13_6.png +++ /dev/null diff --git a/doc/user/project/members/index.md b/doc/user/project/members/index.md index 85cb139c45b..cccb998fc31 100644 --- a/doc/user/project/members/index.md +++ b/doc/user/project/members/index.md @@ -21,7 +21,7 @@ project's **Members**. When your project belongs to the group, group members inherit the membership and permission level for the project from the group. -![Project members page](img/project_members.png) +![Project members page](img/project_members_13_8.png) From the image above, we can deduce the following things: @@ -46,17 +46,17 @@ using the dropdown on the right side: Right next to **People**, start typing the name or username of the user you want to add. -![Search for people](img/add_user_search_people.png) +![Search for people](img/add_user_search_people_13_8.png) Select the user and the [permission level](../../permissions.md) that you'd like to give the user. Note that you can select more than one user. -![Give user permissions](img/add_user_give_permissions.png) +![Give user permissions](img/add_user_give_permissions_13_8.png) Once done, select **Add users to project** and they are immediately added to your project with the permissions you gave them above. -![List members](img/add_user_list_members.png) +![List members](img/add_user_list_members_13_8.png) From there on, you can either remove an existing user or change their access level to the project. @@ -68,14 +68,14 @@ You can import another project's users in your own project by hitting the In the dropdown menu, you can see only the projects you are Maintainer on. -![Import members from another project](img/add_user_import_members_from_another_project.png) +![Import members from another project](img/add_user_import_members_from_another_project_13_8.png) Select the one you want and hit **Import project members**. A flash message displays, notifying you that the import was successful, and the new members are now in the project's members list. Notice that the permissions that they had on the project you imported from are retained. -![Members list of new members](img/add_user_imported_members.png) +![Members list of new members](img/add_user_imported_members_13_8.png) ## Invite people using their e-mail address @@ -83,18 +83,18 @@ If a user you want to give access to doesn't have an account on your GitLab instance, you can invite them just by typing their e-mail address in the user search field. -![Invite user by mail](img/add_user_email_search.png) +![Invite user by mail](img/add_user_email_search_13_8.png) As you can imagine, you can mix inviting multiple people and adding existing GitLab users to the project. -![Invite user by mail ready to submit](img/add_user_email_ready.png) +![Invite user by mail ready to submit](img/add_user_email_ready_13_8.png) Once done, hit **Add users to project** and watch that there is a new member with the e-mail address we used above. From there on, you can resend the invitation, change their access level, or even delete them. -![Invite user members list](img/add_user_email_accept.png) +![Invite user members list](img/add_user_email_accept_13_8.png) While unaccepted, the system automatically sends reminder emails on the second, fifth, and tenth day after the invitation was initially sent. @@ -130,7 +130,7 @@ NOTE: If a project does not have any maintainers, the notification is sent to the most recently active owners of the project's group. -![Manage access requests](img/access_requests_management.png) +![Manage access requests](img/access_requests_management_13_8.png) If you change your mind before your request is approved, just click the **Withdraw Access Request** button. diff --git a/doc/user/project/members/share_project_with_groups.md b/doc/user/project/members/share_project_with_groups.md index edfe8ae3b5b..d17717fb29c 100644 --- a/doc/user/project/members/share_project_with_groups.md +++ b/doc/user/project/members/share_project_with_groups.md @@ -26,19 +26,20 @@ To share 'Project Acme' with the 'Engineering' group: 1. For 'Project Acme' use the left navigation menu to go to **Members**. - ![share project with groups](img/share_project_with_groups_tab_v13_6.png) + ![share project with groups](img/share_project_with_groups_tab_v13_8.png) 1. Select the **Invite group** tab. 1. Add the 'Engineering' group with the maximum access level of your choice. 1. Optionally, select an expiring date. 1. Click **Invite**. +1. After sharing 'Project Acme' with 'Engineering': + - The group is listed in the **Groups** tab. - ![share project with groups tab](img/share_project_with_groups_tab_v13_6.png) + !['Engineering' group is listed in Groups tab](img/project_groups_tab_13_8.png) -1. After sharing 'Project Acme' with 'Engineering', the project is listed - on the group dashboard + - The project is listed on the group dashboard. - !['Project Acme' is listed as a shared project for 'Engineering'](img/other_group_sees_shared_project_v13_6.png) + !['Project Acme' is listed as a shared project for 'Engineering'](img/other_group_sees_shared_project_v13_8.png) Note that you can only share a project with: diff --git a/doc/user/project/merge_requests/allow_collaboration.md b/doc/user/project/merge_requests/allow_collaboration.md index 8eabef982c8..8adaae3b2ef 100644 --- a/doc/user/project/merge_requests/allow_collaboration.md +++ b/doc/user/project/merge_requests/allow_collaboration.md @@ -23,10 +23,10 @@ of the merge request. ## Enabling commit edits from upstream members -The feature can only be enabled by users who already have push access to the -source project and only lasts while the merge request is open. Once enabled, -upstream members will also be able to retry the pipelines and jobs of the -merge request: +From [GitLab 13.7 onwards](https://gitlab.com/gitlab-org/gitlab/-/issues/23308), +this setting is enabled by default. It can be changed by users with Developer +permissions to the source project. Once enabled, upstream members will also be +able to retry the pipelines and jobs of the merge request: 1. While creating or editing a merge request, select the checkbox **Allow commits from members who can merge to the target branch**. diff --git a/doc/user/project/merge_requests/browser_performance_testing.md b/doc/user/project/merge_requests/browser_performance_testing.md index 04114968c80..6fa2340c7a4 100644 --- a/doc/user/project/merge_requests/browser_performance_testing.md +++ b/doc/user/project/merge_requests/browser_performance_testing.md @@ -60,7 +60,7 @@ on your code by using GitLab CI/CD and [sitespeed.io](https://www.sitespeed.io) using Docker-in-Docker. 1. First, set up GitLab Runner with a - [Docker-in-Docker build](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor). + [Docker-in-Docker build](../../../ci/docker/using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker). 1. Configure the default Browser Performance Testing CI job as follows in your `.gitlab-ci.yml` file: ```yaml diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md index 5a98338a81b..ca15ec154fc 100644 --- a/doc/user/project/merge_requests/code_quality.md +++ b/doc/user/project/merge_requests/code_quality.md @@ -72,10 +72,10 @@ It requires GitLab 11.11 or later, and GitLab Runner 11.5 or later. If you are u GitLab 11.4 or earlier, you can view the deprecated job definitions in the [documentation archive](https://docs.gitlab.com/12.10/ee/user/project/merge_requests/code_quality.html#previous-job-definitions). -First, you need GitLab Runner configured: +- Using shared runners, the job should be configured For the [Docker-in-Docker workflow](../../../ci/docker/using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker). +- Using private runners, there is an [alternative configuration](#set-up-a-private-runner-for-code-quality-without-docker-in-docker) recommended for running CodeQuality analysis more efficiently. -- For the [Docker-in-Docker workflow](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor). -- With enough disk space to handle generated Code Quality files. For example on the [GitLab project](https://gitlab.com/gitlab-org/gitlab) the files are approximately 7 GB. +In either configuration, the runner mmust have enough disk space to handle generated Code Quality files. For example on the [GitLab project](https://gitlab.com/gitlab-org/gitlab) the files are approximately 7 GB. Once you set up GitLab Runner, include the Code Quality template in your CI configuration: @@ -140,6 +140,99 @@ definition they could execute privileged Docker commands on the runner host. Having proper access control policies mitigates this attack vector by allowing access only to trusted actors. +### Set up a private runner for code quality without Docker-in-Docker + +It's possible to configure your own runners and avoid Docker-in-Docker. You can use a +configuration that may greatly speed up job execution without requiring your runners +to operate in privileged mode. + +This alternative configuration uses socket binding to share the Runner's Docker daemon +with the job environment. Be aware that this configuration [has significant considerations](../../../ci/docker/using_docker_build.md#use-docker-socket-binding) +to be consider, but may be preferable depending on your use case. + +1. Register a new runner: + + ```shell + $ gitlab-runner register --executor "docker" \ + --docker-image="docker:stable" \ + --url "https://gitlab.com/" \ + --description "cq-sans-dind" \ + --tag-list "cq-sans-dind" \ + --locked="false" \ + --access-level="not_protected" \ + --docker-volumes "/cache"\ + --docker-volumes "/var/run/docker.sock:/var/run/docker.sock" \ + --registration-token="<project_token>" \ + --non-interactive + ``` + +1. **Optional, but recommended:** Set the builds directory to `/tmp/builds`, + so job artifacts are periodically purged from the runner host. If you skip + this step, you must clean up the default builds directory (`/builds`) yourself. + You can do this by adding the following two flags to `gitlab-runner register` + in the previous step. + + ```shell + --builds-dir /tmp/builds + --docker-volumes /tmp/builds:/tmp/builds + ``` + + The resulting configuration: + + ```toml + [[runners]] + name = "cq-sans-dind" + url = "https://gitlab.com/" + token = "<project_token>" + executor = "docker" + builds_dir = "/tmp/builds" + [runners.docker] + tls_verify = false + image = "docker:stable" + privileged = false + disable_entrypoint_overwrite = false + oom_kill_disable = false + disable_cache = false + volumes = ["/cache", "/var/run/docker.sock:/var/run/docker.sock", "/tmp/builds:/tmp/builds"] + shm_size = 0 + [runners.cache] + [runners.cache.s3] + [runners.cache.gcs] + ``` + +1. Apply two overrides to the `code_quality` job created by the template: + + ```yaml + include: + - template: Code-Quality.gitlab-ci.yml + + code_quality: + services: # Shut off Docker-in-Docker + tags: + - cq-sans-dind # Set this job to only run on our new specialized runner + ``` + +The end result is that: + +- Privileged mode is not used. +- Docker-in-Docker is not used. +- Docker images, including all CodeClimate images, are cached, and not re-fetched for subsequent jobs. + +With this configuration, the run time for a second pipeline is much shorter. For example +this [small change](https://gitlab.com/drewcimino/test-code-quality-template/-/merge_requests/4/diffs?commit_id=1e705607aef7236c1b20bb6f637965f3f3e53a46) +to an [open merge request](https://gitlab.com/drewcimino/test-code-quality-template/-/merge_requests/4/pipelines) +running Code Quality analysis ran significantly faster the second time: + +![Code Quality sequential runs without DinD](img/code_quality_host_bound_sequential.png) + +This configuration is not possible on `gitlab.com` shared runners. Shared runners +are configured with `privileged=true`, and they do not expose `docker.sock` into +the job container. As a result, socket binding cannot be used to make `docker` available +in the context of the job script. + +[Docker-in-Docker](../../../ci/docker/using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker) +was chosen as an operational decision by the runner team, instead of exposing `docker.sock`. + ### Disabling the code quality job The `code_quality` job doesn't run if the `$CODE_QUALITY_DISABLED` environment diff --git a/doc/user/project/merge_requests/getting_started.md b/doc/user/project/merge_requests/getting_started.md index cb95daa2cab..bc718ae867f 100644 --- a/doc/user/project/merge_requests/getting_started.md +++ b/doc/user/project/merge_requests/getting_started.md @@ -62,7 +62,7 @@ request's page at the top-right side: - Enable the [squash commits when merge request is accepted](squash_and_merge.md) option to combine all the commits into one before merging, thus keep a clean commit history in your repository. - Set the merge request as a [**Draft**](work_in_progress_merge_requests.md) to avoid accidental merges before it is ready. -Once you have created the merge request, you can also: +After you have created the merge request, you can also: - [Discuss](../../discussions/index.md) your implementation with your team in the merge request thread. - [Perform inline code reviews](reviewing_and_managing_merge_requests.md#perform-inline-code-reviews). @@ -70,7 +70,7 @@ Once you have created the merge request, you can also: - Preview continuous integration [pipelines on the merge request widget](reviewing_and_managing_merge_requests.md#pipeline-status-in-merge-requests-widgets). - Preview how your changes look directly on your deployed application with [Review Apps](reviewing_and_managing_merge_requests.md#live-preview-with-review-apps). - [Allow collaboration on merge requests across forks](allow_collaboration.md). -- Perform a [Review](../../discussions/index.md#merge-request-reviews) in order to create multiple comments on a diff and publish them once you're ready. +- Perform a [Review](../../discussions/index.md#merge-request-reviews) to create multiple comments on a diff and publish them when you're ready. - Add [code suggestions](../../discussions/index.md#suggest-changes) to change the content of merge requests directly into merge request threads, and easily apply them to the codebase directly from the UI. - Add a time estimation and the time spent with that merge request with [Time Tracking](../time_tracking.md#time-tracking). @@ -115,9 +115,10 @@ It is also possible to manage multiple assignees: > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/216054) in GitLab 13.5. > - It was [deployed behind a feature flag](../../../user/feature_flags.md), disabled by default. -> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49787) on GitLab 13.7.1. +> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49787) on GitLab 13.7. > - It's enabled on GitLab.com. > - It's recommended for production use. +> - It can be enabled or disabled for a single project. > - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-merge-request-reviewers). **(CORE ONLY)** WARNING: @@ -160,6 +161,53 @@ Feature.disable(:merge_request_reviewers) Feature.disable(:merge_request_reviewers, Project.find(<project id>)) ``` +#### Reviewer approval rules + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/233736) in GitLab 13.8. +> - It was [deployed behind a feature flag](../../../user/feature_flags.md), disabled by default. +> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/51183) in GitLab 13.8. +> - It's enabled on GitLab.com. +> - It's recommended for production use. +> - It can be enabled or disabled for a single project. +> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#enable-or-disable-reviewer-approval-rules). **(CORE ONLY)** + +When editing the **Reviewers** field in a new or existing merge request, this feature +displays the name of the matching [approval rule](merge_request_approvals.md#approval-rules) +below the name of each suggested reviewer. [Code Owners](../code_owners.md) are displayed as `Codeowner` without group detail. We intend to iterate on this feature in future releases. + +This example shows reviewers and approval rules when creating a new merge request: + +![Reviewer approval rules in new/edit form](img/reviewer_approval_rules_form_v13_8.png) + +This example shows reviewers and approval rules in a merge request sidebar: + +![Reviewer approval rules in sidebar](img/reviewer_approval_rules_sidebar_v13_8.png) + +##### Enable or disable Reviewer Approval Rules **(CORE ONLY)** + +Merge Request Reviewers is under development and ready for production use. +It is deployed behind a feature flag that is **enabled by default**. +[GitLab administrators with access to the GitLab Rails console](../../../administration/feature_flags.md) +can opt to disable it. + +To enable it: + +```ruby +# For the instance +Feature.enable(:reviewer_approval_rules) +# For a single project +Feature.enable(:reviewer_approval_rules, Project.find(<project id>)) +``` + +To disable it: + +```ruby +# For the instance +Feature.disable(:reviewer_approval_rules) +# For a single project +Feature.disable(:reviewer_approval_rules, Project.find(<project id>)) +``` + ### Merge requests to close issues If the merge request is being created to resolve an issue, you can @@ -199,5 +247,5 @@ is set for deletion, the merge request widget displays the at once. By doing so, you save pipeline minutes. - Delete feature branches on merge or after merging them to keep your repository clean. - Take one thing at a time and ship the smallest changes possible. By doing so, - you'll have faster reviews and your changes will be less prone to errors. + reviews are faster and your changes are less prone to errors. - Do not use capital letters nor special chars in branch names. diff --git a/doc/user/project/merge_requests/img/code_quality_host_bound_sequential.png b/doc/user/project/merge_requests/img/code_quality_host_bound_sequential.png Binary files differnew file mode 100644 index 00000000000..2b31f3b42ee --- /dev/null +++ b/doc/user/project/merge_requests/img/code_quality_host_bound_sequential.png diff --git a/doc/user/project/merge_requests/img/reviewer_approval_rules_form_v13_8.png b/doc/user/project/merge_requests/img/reviewer_approval_rules_form_v13_8.png Binary files differnew file mode 100644 index 00000000000..c2aa0689d65 --- /dev/null +++ b/doc/user/project/merge_requests/img/reviewer_approval_rules_form_v13_8.png diff --git a/doc/user/project/merge_requests/img/reviewer_approval_rules_sidebar_v13_8.png b/doc/user/project/merge_requests/img/reviewer_approval_rules_sidebar_v13_8.png Binary files differnew file mode 100644 index 00000000000..3828868965b --- /dev/null +++ b/doc/user/project/merge_requests/img/reviewer_approval_rules_sidebar_v13_8.png diff --git a/doc/user/project/merge_requests/load_performance_testing.md b/doc/user/project/merge_requests/load_performance_testing.md index 82b5d67ba2b..9154897d42d 100644 --- a/doc/user/project/merge_requests/load_performance_testing.md +++ b/doc/user/project/merge_requests/load_performance_testing.md @@ -103,7 +103,7 @@ job. An example configuration workflow: 1. Set up GitLab Runner to run Docker containers, like the - [Docker-in-Docker workflow](../../../ci/docker/using_docker_build.md#use-docker-in-docker-workflow-with-docker-executor). + [Docker-in-Docker workflow](../../../ci/docker/using_docker_build.md#use-the-docker-executor-with-the-docker-image-docker-in-docker). 1. Configure the default Load Performance Testing CI job in your `.gitlab-ci.yml` file. You need to include the template and configure it with variables: diff --git a/doc/user/project/merge_requests/squash_and_merge.md b/doc/user/project/merge_requests/squash_and_merge.md index 5c466654b31..93b85ce8669 100644 --- a/doc/user/project/merge_requests/squash_and_merge.md +++ b/doc/user/project/merge_requests/squash_and_merge.md @@ -8,7 +8,7 @@ type: reference, concepts # Squash and merge > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/1024) in [GitLab Starter](https://about.gitlab.com/pricing/) 8.17. -> - [Ported](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18956) to GitLab Core 11.0. +> - [Moved](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18956) from [GitLab Starter](https://about.gitlab.com/pricing/)to GitLab Core in 11.0. With squash and merge you can combine all your merge request's commits into one and retain a clean history. diff --git a/doc/user/project/merge_requests/test_coverage_visualization.md b/doc/user/project/merge_requests/test_coverage_visualization.md index c38b28f7718..3960f916f9b 100644 --- a/doc/user/project/merge_requests/test_coverage_visualization.md +++ b/doc/user/project/merge_requests/test_coverage_visualization.md @@ -33,7 +33,7 @@ This format was originally developed for Java, but most coverage analysis framew for other languages have plugins to add support for it, like: - [simplecov-cobertura](https://rubygems.org/gems/simplecov-cobertura) (Ruby) -- [gocover-cobertura](https://github.com/t-yuki/gocover-cobertura) (Golang) +- [gocover-cobertura](https://github.com/boumenot/gocover-cobertura) (Golang) Other coverage analysis frameworks support the format out of the box, for example: diff --git a/doc/user/project/new_ci_build_permissions_model.md b/doc/user/project/new_ci_build_permissions_model.md index fd7c58f12b9..4910751ece1 100644 --- a/doc/user/project/new_ci_build_permissions_model.md +++ b/doc/user/project/new_ci_build_permissions_model.md @@ -72,10 +72,26 @@ Let's consider the following scenario: ## Job token -A unique job token is generated for each job and provides the user read -access all projects that would be normally accessible to the user creating that -job. The unique job token does not have any write permissions, but there -is a [proposal to add support](https://gitlab.com/groups/gitlab-org/-/epics/3559). +When a pipeline job is about to run, GitLab generates a unique token and injects it as the +[`CI_JOB_TOKEN` predefined variable](../../ci/variables/predefined_variables.md). +This token can authenticate [API requests](../../api/README.md) +from the job script (Runner) that needs to access the project's resources (for example, when +fetching a job artifact). + +Once the token is authenticated, GitLab identifies the user who triggered the job and uses this user +to authorize access to the resource. Therefore, this user must be assigned to +[a role that has the required privileges](../permissions.md). + +The job token has these limitations: + +- Not all APIs allow job tokens for authentication. See [this list](../../api/README.md#gitlab-ci-job-token) + for available endpoints. +- The token is valid only while the pipeline job runs. Once the job finishes, the token can't be + used for authentication. + +Although a job token is handy to quickly access a project's resources without any configuration, it +sometimes gives extra permissions that aren't necessary. There is [a proposal](https://gitlab.com/groups/gitlab-org/-/epics/3559) +to redesign the feature for more strategic control of the access permissions. If you need your CI pipeline to push to the Package Registry, consider using [deploy tokens](deploy_tokens/index.md). diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md index 4aa89ec6f8d..f02697a3cd5 100644 --- a/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md +++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/dns_concepts.md @@ -24,7 +24,7 @@ GitLab Pages site. Note that **how to** add DNS records depends on which server your domain is hosted on. Every control panel has its own place to do it. If you are not an administrator of your domain, and don't have access to your registrar, -you'll need to ask for the technical support of your hosting service +you must ask the technical support of your hosting service to do it for you. To help you out, we've gathered some instructions on how to do that @@ -67,7 +67,7 @@ Example: - `www` => `CNAME` => `example.com` -This way, visitors visiting `www.example.com` will be redirected to +This way, visitors visiting `www.example.com` are redirected to `example.com`. ## MX record diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md index f8173b4c004..8ed0ef82893 100644 --- a/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md +++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/index.md @@ -47,7 +47,8 @@ Click **Create New Domain**. #### 2. Get the verification code -Once you have added a new domain to Pages, the verification code will be prompted to you. Copy the values from GitLab and paste them in your domain's control panel as a TXT record on the next step. +After you add a new domain to Pages, the verification code prompts you. Copy the values from GitLab +and paste them in your domain's control panel as a TXT record on the next step. ![Get the verification code](img/get_domain_verification_code_v12_0.png) @@ -91,7 +92,7 @@ add a DNS apex `CNAME` record instead of an `A` record. The main advantage of doing so is that when GitLab Pages IP on GitLab.com changes for whatever reason, you don't need to update your `A` record. There may be a few exceptions, but **this method is not recommended** -as it most likely won't work if you set an [`MX` record](dns_concepts.md#mx-record) for your root domain. +as it most likely doesn't work if you set an [`MX` record](dns_concepts.md#mx-record) for your root domain. ##### For subdomains @@ -154,12 +155,11 @@ Once you have added all the DNS records: ![Verify your domain](img/retry_domain_verification_v12_0.png) -As soon as your domain becomes active, your website will be available -through your domain name. +As soon as your domain becomes active, your website is available through your domain name. WARNING: Considering GitLab instances with domain verification enabled, -if the domain cannot be verified for 7 days, it will be removed +if the domain can't be verified for 7 days, it's removed from the GitLab project. > **Notes:** @@ -169,9 +169,9 @@ from the GitLab project. to [disabled custom domain verification](../../../../administration/pages/index.md#custom-domain-verification). > - [DNS propagation may take some time (up to 24h)](https://www.inmotionhosting.com/support/domain-names/dns-nameserver-changes/complete-guide-to-dns-records/), although it's usually a matter of minutes to complete. Until it does, verification - will fail and attempts to visit your domain will respond with a 404. + fails, and attempts to visit your domain result in a 404. > - Once your domain has been verified, leave the verification record - in place: your domain will be periodically reverified, and may be + in place. Your domain is periodically reverified, and may be disabled if the record is removed. ##### Troubleshooting Pages domain verification @@ -211,7 +211,7 @@ For a subdomain: You can add more than one alias (custom domains and subdomains) to the same project. An alias can be understood as having many doors leading to the same room. -All the aliases you've set to your site will be listed on **Setting > Pages**. +All the aliases you've set to your site are listed on **Setting > Pages**. From that page, you can view, add, and remove them. ### Redirecting `www.domain.com` to `domain.com` with Cloudflare @@ -294,7 +294,7 @@ Sublime Text, Atom, Dreamweaver, Brackets, etc). To make your website's visitors even more secure, you can choose to force HTTPS for GitLab Pages. By doing so, all attempts to visit your -website via HTTP will be automatically redirected to HTTPS via 301. +website through HTTP are automatically redirected to HTTPS through 301. It works with both the GitLab default domain and with your custom domain (as long as you've set a valid certificate for it). diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md index 3dea35153e4..aa06a15a8c0 100644 --- a/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md +++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/lets_encrypt_integration.md @@ -50,15 +50,15 @@ Once you've met the requirements, enable Let's Encrypt integration: 1. Click **Save changes**. -Once enabled, GitLab will obtain a LE certificate and add it to the -associated Pages domain. It also will be renewed automatically by GitLab. +Once enabled, GitLab obtains a LE certificate and add it to the +associated Pages domain. GitLab also renews it automatically. > **Notes:** > > - Issuing the certificate and updating Pages configuration > **can take up to an hour**. -> - If you already have SSL certificate in domain settings it -> will continue to work until it will be replaced by Let's Encrypt's certificate. +> - If you already have an SSL certificate in domain settings it +> continues to work until replaced by the Let's Encrypt's certificate. ## Troubleshooting diff --git a/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md b/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md index dc73a664324..e8c6305dbab 100644 --- a/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md +++ b/doc/user/project/pages/custom_domains_ssl_tls_certification/ssl_tls_concepts.md @@ -10,10 +10,10 @@ info: To determine the technical writer assigned to the Stage/Group associated w _Read this document for a brief overview of SSL/TLS certificates in the scope of GitLab Pages, for beginners in web development._ -Every GitLab Pages project on GitLab.com will be available under +Every GitLab Pages project on GitLab.com is available under HTTPS for the default Pages domain (`*.gitlab.io`). Once you set up your Pages project with your custom (sub)domain, if you want -it secured by HTTPS, you will have to issue a certificate for that +it secured by HTTPS, you must issue a certificate for that (sub)domain and install it on your project. NOTE: @@ -41,9 +41,6 @@ the connection between the **client** (you, me, your visitors) and the **server** (where you site lives), through a keychain of authentications and validations. -How about taking Josh's advice and protecting our sites too? We will be -well supported, and we'll contribute to a safer internet. - ## Organizations supporting HTTPS There is a huge movement in favor of securing all the web. W3C fully @@ -62,8 +59,8 @@ GitLab Pages accepts certificates provided in the [PEM](https://knowledge.digice for public websites for security reasons and to ensure that browsers trust your site's certificate. There are various kinds of certificates, each one -with a certain security level. A static personal website will -not require the same security level as an online banking web app, +with a certain security level. A static personal website doesn't +require the same security level as an online banking web app, for instance. There are some certificate authorities that diff --git a/doc/user/project/pages/getting_started/pages_ci_cd_template.md b/doc/user/project/pages/getting_started/pages_ci_cd_template.md index 6dd431e02b0..e0d5e8be535 100644 --- a/doc/user/project/pages/getting_started/pages_ci_cd_template.md +++ b/doc/user/project/pages/getting_started/pages_ci_cd_template.md @@ -41,7 +41,7 @@ configuration for the Pages site to generate properly. If everything is configured correctly, the site can take approximately 30 minutes to deploy. -You can watch the pipeline run by going to **CI / CD > Pipelines**. +You can watch the pipeline run by navigating to **CI / CD > Pipelines**. When the pipeline is finished, go to **Settings > Pages** to find the link to your Pages website. diff --git a/doc/user/project/pages/getting_started/pages_forked_sample_project.md b/doc/user/project/pages/getting_started/pages_forked_sample_project.md index 525bbde4671..c7916b7c01e 100644 --- a/doc/user/project/pages/getting_started/pages_forked_sample_project.md +++ b/doc/user/project/pages/getting_started/pages_forked_sample_project.md @@ -17,7 +17,7 @@ configured to generate a Pages site. To fork a sample project and create a Pages website: -1. View the sample projects by going to the [GitLab Pages examples](https://gitlab.com/pages) group. +1. View the sample projects by navigating to the [GitLab Pages examples](https://gitlab.com/pages) group. 1. Click the name of the project you want to [fork](../../../../gitlab-basics/fork-project.md). 1. In the top right, click the **Fork** button, and then choose a namespace to fork to. 1. Go to your project's **CI/CD > Pipelines** and click **Run pipeline**. @@ -50,7 +50,7 @@ You can take some **optional** further steps: If you set the repository path to `gitlab-tests.gitlab.io`, the resulting URL for your Pages website is `https://gitlab-tests.gitlab.io`. - ![Change repo's path](../img/change_path_v12_10.png) + ![Change repository's path](../img/change_path_v12_10.png) - Now go to your SSG's configuration file and change the [base URL](../getting_started_part_one.md#urls-and-baseurls) from `"project-name"` to `""`. The project name setting varies by SSG and may not be in the configuration file. diff --git a/doc/user/project/pages/getting_started/pages_from_scratch.md b/doc/user/project/pages/getting_started/pages_from_scratch.md index 230e88f35f5..3f2df634e3a 100644 --- a/doc/user/project/pages/getting_started/pages_from_scratch.md +++ b/doc/user/project/pages/getting_started/pages_from_scratch.md @@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w # Create a GitLab Pages website from scratch -This tutorial shows you how to create a Pages site from scratch. You will start with +This tutorial shows you how to create a Pages site from scratch. You start with a blank project and create your own CI file, which gives instruction to a [runner](https://docs.gitlab.com/runner/). When your CI/CD [pipeline](../../../../ci/pipelines/index.md) runs, the Pages site is created. @@ -218,7 +218,7 @@ There are three default stages for GitLab CI/CD: build, test, and deploy. If you want to test your script and check the built site before deploying -to production, you can run the test exactly as it will run when you +to production, you can run the test exactly as it runs when you push to `master`. To specify a stage for your job to run in, @@ -376,7 +376,7 @@ test: In this case, you need to exclude the `/vendor` directory from the list of folders Jekyll builds. Otherwise, Jekyll -will try to build the directory contents along with the site. +tries to build the directory contents along with the site. In the root directory, create a file called `_config.yml` and add this content: diff --git a/doc/user/project/pages/getting_started_part_one.md b/doc/user/project/pages/getting_started_part_one.md index f549c4e6e7d..801fe0c7ef0 100644 --- a/doc/user/project/pages/getting_started_part_one.md +++ b/doc/user/project/pages/getting_started_part_one.md @@ -16,7 +16,7 @@ wildcard domain with your sysadmin. This guide is valid for any GitLab instance, replace the Pages wildcard domain on GitLab.com (`*.gitlab.io`) with your own. If you set up a GitLab Pages project on GitLab, -it will automatically be accessible under a +it's automatically accessible under a subdomain of `namespace.example.io`. The [`namespace`](../../group/index.md#namespaces) is defined by your username on GitLab.com, @@ -45,35 +45,35 @@ To understand Pages domains clearly, read the examples below. - You created a project called `blog` under your username `john`, therefore your project URL is `https://gitlab.com/john/blog/`. Once you enable GitLab Pages for this project, and build your site, - it will be available under `https://john.gitlab.io/blog/`. + you can access it at `https://john.gitlab.io/blog/`. - You created a group for all your websites called `websites`, and a project within this group is called `blog`. Your project URL is `https://gitlab.com/websites/blog/`. Once you enable - GitLab Pages for this project, the site will live under + GitLab Pages for this project, the site is available at `https://websites.gitlab.io/blog/`. - You created a group for your engineering department called `engineering`, a subgroup for all your documentation websites called `docs`, and a project within this subgroup is called `workflows`. Your project URL is `https://gitlab.com/engineering/docs/workflows/`. Once you enable - GitLab Pages for this project, the site will live under + GitLab Pages for this project, the site is available at `https://engineering.gitlab.io/docs/workflows`. ### User and Group website examples - Under your username, `john`, you created a project called - `john.gitlab.io`. Your project URL will be `https://gitlab.com/john/john.gitlab.io`. + `john.gitlab.io`. Your project URL is `https://gitlab.com/john/john.gitlab.io`. Once you enable GitLab Pages for your project, your website - will be published under `https://john.gitlab.io`. + is published under `https://john.gitlab.io`. - Under your group `websites`, you created a project called - `websites.gitlab.io`. your project's URL will be `https://gitlab.com/websites/websites.gitlab.io`. + `websites.gitlab.io`. Your project's URL is `https://gitlab.com/websites/websites.gitlab.io`. Once you enable GitLab Pages for your project, - your website will be published under `https://websites.gitlab.io`. + your website is published under `https://websites.gitlab.io`. **General example:** -- On GitLab.com, a project site will always be available under +- On GitLab.com, a project site is always available under `https://namespace.gitlab.io/project-name` -- On GitLab.com, a user or group website will be available under +- On GitLab.com, a user or group website is available under `https://namespace.gitlab.io/` - On your GitLab instance, replace `gitlab.io` above with your Pages server domain. Ask your sysadmin for this information. @@ -87,7 +87,7 @@ Every Static Site Generator (SSG) default configuration expects to find your website under a (sub)domain (`example.com`), not in a subdirectory of that domain (`example.com/subdir`). Therefore, whenever you publish a project website (`namespace.gitlab.io/project-name`), -you'll have to look for this configuration (base URL) on your SSG's +you must look for this configuration (base URL) on your SSG's documentation and set it up to reflect this pattern. For example, for a Jekyll site, the `baseurl` is defined in the Jekyll @@ -99,11 +99,11 @@ baseurl: "/blog" ``` On the contrary, if you deploy your website after forking one of -our [default examples](https://gitlab.com/pages), the `baseurl` will -already be configured this way, as all examples there are project -websites. If you decide to make yours a user or group website, you'll -have to remove this configuration from your project. For the Jekyll -example we've just mentioned, you'd have to change Jekyll's `_config.yml` to: +our [default examples](https://gitlab.com/pages), the `baseurl` is +already configured this way, as all examples there are project +websites. If you decide to make yours a user or group website, you +must remove this configuration from your project. For the Jekyll +example we just mentioned, you must change Jekyll's `_config.yml` to: ```yaml baseurl: "" diff --git a/doc/user/project/pages/index.md b/doc/user/project/pages/index.md index 846d30e898c..c9e28bf15c2 100644 --- a/doc/user/project/pages/index.md +++ b/doc/user/project/pages/index.md @@ -81,10 +81,12 @@ becomes available automatically. To deploy your site, GitLab uses its built-in tool called [GitLab CI/CD](../../../ci/README.md) to build your site and publish it to the GitLab Pages server. The sequence of scripts that GitLab CI/CD runs to accomplish this task is created from a file named -`.gitlab-ci.yml`, which you can [create and modify](getting_started/pages_from_scratch.md) at will. A specific `job` called `pages` in the configuration file will make GitLab aware that you are deploying a GitLab Pages website. +`.gitlab-ci.yml`, which you can [create and modify](getting_started/pages_from_scratch.md). +A specific `job` called `pages` in the configuration file makes GitLab aware that you're deploying a +GitLab Pages website. You can either use the GitLab [default domain for GitLab Pages websites](getting_started_part_one.md#gitlab-pages-default-domain-names), -`*.gitlab.io`, or your own domain (`example.com`). In that case, you'll +`*.gitlab.io`, or your own domain (`example.com`). In that case, you need administrator access to your domain's registrar (or control panel) to set it up with Pages. The following diagrams show the workflows you might follow to get started with Pages. @@ -94,15 +96,15 @@ The following diagrams show the workflows you might follow to get started with P ## Access to your Pages site If you're using GitLab Pages default domain (`.gitlab.io`), -your website will be automatically secure and available under +your website is automatically secure and available under HTTPS. If you're using your own custom domain, you can optionally secure it with SSL/TLS certificates. -If you're using GitLab.com, your website will be publicly available to the internet. +If you're using GitLab.com, your website is publicly available to the internet. To restrict access to your website, enable [GitLab Pages Access Control](pages_access_control.md). If you're using a self-managed instance (Core, Starter, Premium, or Ultimate), -your websites will be published on your own server, according to the +your websites are published on your own server, according to the [Pages settings](../../../administration/pages/index.md) chosen by your sysadmin, who can make them public or internal. diff --git a/doc/user/project/pages/introduction.md b/doc/user/project/pages/introduction.md index 5a284bf57c3..8380f367212 100644 --- a/doc/user/project/pages/introduction.md +++ b/doc/user/project/pages/introduction.md @@ -44,19 +44,19 @@ Visit the [GitLab Pages group](https://gitlab.com/groups/pages) for a complete l You can provide your own 403 and 404 error pages by creating the `403.html` and `404.html` files respectively in the root directory of the `public/` directory -that will be included in the artifacts. Usually this is the root directory of +that are included in the artifacts. Usually this is the root directory of your project, but that may differ depending on your static generator configuration. If the case of `404.html`, there are different scenarios. For example: - If you use project Pages (served under `/projectname/`) and try to access - `/projectname/non/existing_file`, GitLab Pages will try to serve first + `/projectname/non/existing_file`, GitLab Pages tries to serve first `/projectname/404.html`, and then `/404.html`. - If you use user/group Pages (served under `/`) and try to access - `/non/existing_file` GitLab Pages will try to serve `/404.html`. + `/non/existing_file` GitLab Pages tries to serve `/404.html`. - If you use a custom domain and try to access `/non/existing_file`, GitLab - Pages will try to serve only `/404.html`. + Pages tries to serve only `/404.html`. ## Redirects in GitLab Pages @@ -71,8 +71,8 @@ To restrict access to your website, enable [GitLab Pages Access Control](pages_a If you ever feel the need to purge your Pages content, you can do so by going to your project's settings through the gear icon in the top right, and then -navigating to **Pages**. Hit the **Remove pages** button and your Pages website -will be deleted. +navigating to **Pages**. Click the **Remove pages** button to delete your Pages +website. ![Remove pages](img/remove_pages.png) @@ -81,9 +81,9 @@ will be deleted. When using Pages under the general domain of a GitLab instance (`*.example.io`), you _cannot_ use HTTPS with sub-subdomains. That means that if your username or group name contains a dot, for example `foo.bar`, the domain -`https://foo.bar.example.io` will _not_ work. This is a limitation of the -[HTTP Over TLS protocol](https://tools.ietf.org/html/rfc2818#section-3.1). HTTP pages will continue to work provided you -don't redirect HTTP to HTTPS. +`https://foo.bar.example.io` does _not_ work. This is a limitation of the +[HTTP Over TLS protocol](https://tools.ietf.org/html/rfc2818#section-3.1). +HTTP pages continue to work provided you don't redirect HTTP to HTTPS. GitLab Pages [does **not** support group websites for subgroups](../../group/subgroups/index.md#limitations). You can only create the highest-level group website. @@ -130,11 +130,11 @@ See this document for a [step-by-step guide](getting_started/pages_from_scratch. Remember that GitLab Pages are by default branch/tag agnostic and their deployment relies solely on what you specify in `.gitlab-ci.yml`. You can limit the `pages` job with the [`only` parameter](../../../ci/yaml/README.md#onlyexcept-basic), -whenever a new commit is pushed to a branch that will be used specifically for -your pages. +whenever a new commit is pushed to a branch used specifically for your +pages. That way, you can have your project's code in the `master` branch and use an -orphan branch (let's name it `pages`) that will host your static generator site. +orphan branch (let's name it `pages`) to host your static generator site. You can create a new empty branch like this: @@ -142,9 +142,9 @@ You can create a new empty branch like this: git checkout --orphan pages ``` -The first commit made on this new branch will have no parents and it will be -the root of a new history totally disconnected from all the other branches and -commits. Push the source files of your static generator in the `pages` branch. +The first commit made on this new branch has no parents and is the root of a +new history totally disconnected from all the other branches and commits. +Push the source files of your static generator in the `pages` branch. Below is a copy of `.gitlab-ci.yml` where the most significant line is the last one, specifying to execute everything in the `pages` branch: @@ -172,9 +172,9 @@ also includes `.gitlab-ci.yml`. Most modern browsers support downloading files in a compressed format. This speeds up downloads by reducing the size of files. -Before serving an uncompressed file, Pages will check whether the same file -exists with a `.br` or `.gz` extension. If it does, and the browser supports receiving -compressed files, it will serve that version instead of the uncompressed one. +Before serving an uncompressed file, Pages checks if the same file exists with +a `.br` or `.gz` extension. If it does, and the browser supports receiving +compressed files, it serves that version instead of the uncompressed one. To take advantage of this feature, the artifact you upload to the Pages should have this structure: @@ -236,10 +236,10 @@ public/ ``` Pages supports reaching each of these files through several different URLs. In -particular, it will always look for an `index.html` file if the URL only +particular, it always looks for an `index.html` file if the URL only specifies the directory. If the URL references a file that doesn't exist, but -adding `.html` to the URL leads to a file that *does* exist, it will be served -instead. Here are some examples of what will happen given the above Pages site: +adding `.html` to the URL leads to a file that *does* exist, it's served +instead. Here are some examples of what happens given the above Pages site: | URL path | HTTP response | File served | | -------------------- | ------------- | ----------- | @@ -275,7 +275,7 @@ to private, internal or public. ### Do I need to create a user/group website before creating a project website? -No, you don't. You can create your project first and it will be accessed under +No, you don't. You can create your project first and access it under `http(s)://namespace.example.io/projectname`. ## Known issues diff --git a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md index f2b75354bf8..b5932fc8766 100644 --- a/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md +++ b/doc/user/project/pages/lets_encrypt_for_gitlab_pages.md @@ -61,7 +61,7 @@ might be slightly different. Follow the ``` Alternatively, you can register without adding an e-mail account, - but you won't be notified about the certificate expiration's date: + but you aren't notified about the certificate expiration's date: ```shell sudo certbot certonly -a manual -d example.com --register-unsafely-without-email @@ -71,10 +71,10 @@ might be slightly different. Follow the Read through CertBot's documentation on their [command line options](https://certbot.eff.org/docs/using.html#certbot-command-line-options). -1. You'll be prompted with a message to agree with their terms. +1. You're prompted with a message to agree with their terms. Press `A` to agree and `Y` to let they log your IP. - CertBot will then prompt you with the following message: + CertBot then prompts you with the following message: ```shell Create a file containing just this data: @@ -88,7 +88,7 @@ might be slightly different. Follow the Press Enter to Continue ``` -1. **Do not press Enter yet.** Let's Encrypt will need to verify your +1. **Do not press Enter yet.** Let's Encrypt needs to verify your domain ownership before issuing the certificate. To do so, create 3 consecutive directories under your website's root: `/.well-known/acme-challenge/Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP/` @@ -103,11 +103,11 @@ might be slightly different. Follow the `http://example.com/.well-known/acme-challenge/Rxnv6WKo95hsuLVX3osmT6LgmzsJKSaK9htlPToohOP` to allow Let's Encrypt to verify the ownership of your domain, therefore, it needs to be part of the website content under the - repo's [`public`](index.md#how-it-works) folder. + repository's [`public`](index.md#how-it-works) folder. 1. Add, commit, and push the file into your repository in GitLab. Once the pipeline passes, press **Enter** on your terminal to continue issuing your - certificate. CertBot will then prompt you with the following message: + certificate. CertBot then prompts you with the following message: ```shell Waiting for verification... @@ -157,7 +157,7 @@ valid certificates)**. ## Renewal -Let's Encrypt certificates expire every 90 days and you'll have to +Let's Encrypt certificates expire every 90 days and you must renew them periodically. To renew all your certificates at once, run: ```shell diff --git a/doc/user/project/pages/pages_access_control.md b/doc/user/project/pages/pages_access_control.md index 9d17277fe9e..a2a17a4f2ca 100644 --- a/doc/user/project/pages/pages_access_control.md +++ b/doc/user/project/pages/pages_access_control.md @@ -28,20 +28,20 @@ For a demonstration, see [Pages access controls](https://www.youtube.com/watch?v with GitLab Pages, depending on your project's visibility: - If your project is private: - - **Only project members**: Only project members will be able to browse the website. - - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership. + - **Only project members**: Only project members are able to browse the website. + - **Everyone**: Everyone, both logged into and logged out of GitLab, is able to browse the website, no matter their project membership. - If your project is internal: - - **Only project members**: Only project members will be able to browse the website. - - **Everyone with access**: Everyone logged into GitLab will be able to browse the website, no matter their project membership. - - **Everyone**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership. + - **Only project members**: Only project members are able to browse the website. + - **Everyone with access**: Everyone logged into GitLab is able to browse the website, no matter their project membership. + - **Everyone**: Everyone, both logged into and logged out of GitLab, is able to browse the website, no matter their project membership. - If your project is public: - - **Only project members**: Only project members will be able to browse the website. - - **Everyone with access**: Everyone, both logged into and logged out of GitLab, will be able to browse the website, no matter their project membership. + - **Only project members**: Only project members are able to browse the website. + - **Everyone with access**: Everyone, both logged into and logged out of GitLab, is able to browse the website, no matter their project membership. 1. Click **Save changes**. The next time someone tries to access your website and the access control is -enabled, they will be presented with a page to sign into GitLab and verify they +enabled, they're presented with a page to sign into GitLab and verify they can access the website. ## Terminating a Pages session diff --git a/doc/user/project/quick_actions.md b/doc/user/project/quick_actions.md index 9f849051f40..64be3182dab 100644 --- a/doc/user/project/quick_actions.md +++ b/doc/user/project/quick_actions.md @@ -9,8 +9,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w > - Introduced in [GitLab 12.1](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/26672): > once an action is executed, an alert appears when a quick action is successfully applied. -> - In [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/16877) and later, you can use +> - Introduced in [GitLab 13.2](https://gitlab.com/gitlab-org/gitlab/-/issues/16877): you can use > quick actions when updating the description of issues, epics, and merge requests. +> - Introduced in [GitLab 13.8](https://gitlab.com/gitlab-org/gitlab/-/issues/292393): when you enter +> `/` into a description or comment field, all available quick actions are displayed in a scrollable list. +> - The rebase quick action was [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/49800) in GitLab 13.8. Quick actions are textual shortcuts for common actions on issues, epics, merge requests, and commits that are usually done by clicking buttons or dropdowns in the GitLab UI. @@ -31,6 +34,9 @@ The following quick actions are applicable to descriptions, discussions and thre | `/assign @user` | ✓ | ✓ | | Assign one user. | | `/assign @user1 @user2` | ✓ | ✓ | | Assign multiple users. **(STARTER)** | | `/assign me` | ✓ | ✓ | | Assign yourself. | +| `/assign_reviewer @user` | | ✓ | | Assign one user as a reviewer. | +| `/assign_reviewer @user1 @user2` | | ✓ | | Assign multiple users as reviewers. **(STARTER)** | +| `/assign_reviewer me` | | ✓ | | Assign yourself as a reviewer. | | `/award :emoji:` | ✓ | ✓ | ✓ | Toggle emoji award. | | `/child_epic <epic>` | | | ✓ | Add child epic to `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab/-/issues/7330)). **(ULTIMATE)** | | `/clear_weight` | ✓ | | | Clear weight. **(STARTER)** | @@ -56,6 +62,8 @@ The following quick actions are applicable to descriptions, discussions and thre | `/promote` | ✓ | | | Promote issue to epic. **(PREMIUM)** | | `/publish` | ✓ | | | Publish issue to an associated [Status Page](../../operations/incident_management/status_page.md) ([Introduced in GitLab 13.0](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/30906)) **(ULTIMATE)** | | `/reassign @user1 @user2` | ✓ | ✓ | | Replace current assignees with those specified. **(STARTER)** | +| `/rebase` | | ✓ | | Rebase source branch. This will schedule a background task that attempt to rebase the changes in the source branch on the latest commit of the target branch. If `/rebase` is used, `/merge` will be ignored to avoid a race condition where the source branch is merged or deleted before it is rebased. If there are merge conflicts, GitLab will display a message that a rebase cannot be scheduled. Rebase failures will be displayed with the merge request status. | +| `/reassign_reviewer @user1 @user2` | | ✓ | | Replace current reviewers with those specified. **(STARTER)** | | `/relabel ~label1 ~label2` | ✓ | ✓ | ✓ | Replace current labels with those specified. | | `/relate #issue1 #issue2` | ✓ | | | Mark issues as related. **(STARTER)** | | `/remove_child_epic <epic>` | | | ✓ | Remove child epic from `<epic>`. The `<epic>` value should be in the format of `&epic`, `group&epic`, or a URL to an epic ([introduced in GitLab 12.0](https://gitlab.com/gitlab-org/gitlab/-/issues/7330)). **(ULTIMATE)** | @@ -78,7 +86,9 @@ The following quick actions are applicable to descriptions, discussions and thre | `/title <new title>` | ✓ | ✓ | ✓ | Change title. | | `/todo` | ✓ | ✓ | ✓ | Add a to-do item. | | `/unassign @user1 @user2` | ✓ | ✓ | | Remove specific assignees. **(STARTER)** | -| `/unassign` | ✓ | ✓ | | Remove all assignees. | +| `/unassign` | | ✓ | | Remove all assignees. | +| `/unassign_reviewer @user1 @user2` | | ✓ | | Remove specific reviewers. **(STARTER)** | +| `/unassign_reviewer` | | ✓ | | Remove all reviewers. | | `/unlabel ~label1 ~label2` or `/remove_label ~label1 ~label2` | ✓ | ✓ | ✓ | Remove specified labels. | | `/unlabel` or `/remove_label` | ✓ | ✓ | ✓ | Remove all labels. | | `/unlock` | ✓ | ✓ | | Unlock the discussions. | diff --git a/doc/user/project/releases/index.md b/doc/user/project/releases/index.md index 7b412270938..90d7ac0a3c2 100644 --- a/doc/user/project/releases/index.md +++ b/doc/user/project/releases/index.md @@ -200,7 +200,7 @@ If the job that's executing is within a freeze period, GitLab CI/CD creates an e variable named `$CI_DEPLOY_FREEZE`. To prevent the deployment job from executing, create a `rules` entry in your -`gitlab-ci.yaml`, for example: +`gitlab-ci.yml`, for example: ```yaml deploy_to_production: @@ -274,14 +274,11 @@ Release note descriptions are unrelated. Description supports [Markdown](../../m ### Release assets -You can currently add the following types of assets to each release: +You can add the following types of assets to each release: - [Source code](#source-code) - [Links](#links) -GitLab will support more asset types in the future, including objects such -as pre-built packages, compliance/security evidence, or container images. - #### Permanent links to release assets > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/27300) in GitLab 12.9. @@ -336,8 +333,8 @@ The four types of links are "Runbook," "Package," "Image," and "Other." > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/26019) in GitLab 12.6. Each time a release is created, GitLab takes a snapshot of data that's related to it. -This data is saved in a JSON file and called *release evidence*. The feature currently -includes test artifacts and linked milestones (and will include issues) to facilitate +This data is saved in a JSON file and called *release evidence*. The feature +includes test artifacts and linked milestones to facilitate internal processes, like external audits. To access the release evidence, on the Releases page, click the link to the JSON file that's listed diff --git a/doc/user/project/repository/forking_workflow.md b/doc/user/project/repository/forking_workflow.md index 75e1aea632f..f7da3629c23 100644 --- a/doc/user/project/repository/forking_workflow.md +++ b/doc/user/project/repository/forking_workflow.md @@ -34,10 +34,6 @@ Forking a project is, in most cases, a two-step process. The fork is created. The permissions you have in the namespace are the permissions you will have in the fork. WARNING: -In GitLab 12.6 and later, when project owners [reduce a project's visibility](../../../public_access/public_access.md#reducing-visibility), -it **removes the relationship** between a project and all its forks. - -WARNING: When a public project with the repository feature set to "Members only" is forked, the repository will be public in the fork. The owner of the fork will need to manually change the visibility. This is being diff --git a/doc/user/project/repository/index.md b/doc/user/project/repository/index.md index e1d84baec4d..c4f5d330f63 100644 --- a/doc/user/project/repository/index.md +++ b/doc/user/project/repository/index.md @@ -31,7 +31,7 @@ that you [connect with GitLab via SSH](../../../ssh/README.md). ## Files Use a repository to store your files in GitLab. In [GitLab 12.10 and later](https://gitlab.com/gitlab-org/gitlab/-/issues/33806), -you'll see on the repository's file tree an icon next to the file name +you'll see on the repository's file tree an icon next to the filename according to its extension: ![Repository file icons](img/file_ext_icons_repo_v12_10.png) @@ -236,18 +236,24 @@ lock your files to prevent any conflicting changes. You can access your repositories via [repository API](../../../api/repositories.md). -## Clone in Apple Xcode +## Clone a repository -> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45820) in GitLab 11.0 +Learn how to [clone a repository through the command line](../../../gitlab-basics/start-using-git.md#clone-a-repository). + +Alternatively, clone directly into a code editor as documented below. + +### Clone to Apple Xcode + +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/45820) in GitLab 11.0. Projects that contain a `.xcodeproj` or `.xcworkspace` directory can now be cloned -in Xcode using the new **Open in Xcode** button, located next to the Git URL +into Xcode using the new **Open in Xcode** button, located next to the Git URL used for cloning your project. The button is only shown on macOS. ## Download Source Code -> Support for directory download was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/24704) in GitLab 11.11. -> Support for [including Git LFS blobs](../../../topics/git/lfs#lfs-objects-in-project-archives) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) in GitLab 13.5. +> - Support for directory download was [introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/24704) in GitLab 11.11. +> - Support for [including Git LFS blobs](../../../topics/git/lfs#lfs-objects-in-project-archives) was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/15079) in GitLab 13.5. The source code stored in a repository can be downloaded from the UI. By clicking the download icon, a dropdown will open with links to download the following: diff --git a/doc/user/project/repository/repository_mirroring.md b/doc/user/project/repository/repository_mirroring.md index 96694a9e954..4a7f75ba1ac 100644 --- a/doc/user/project/repository/repository_mirroring.md +++ b/doc/user/project/repository/repository_mirroring.md @@ -8,19 +8,16 @@ disqus_identifier: 'https://docs.gitlab.com/ee/workflow/repository_mirroring.htm # Repository mirroring Repository mirroring allows for mirroring of repositories to and from external sources. It can be -used to mirror branches, tags, and commits between repositories. +used to mirror branches, tags, and commits between repositories. It is useful when you want to use +a repository outside of GitLab. A repository mirror at GitLab will be updated automatically. You can also manually trigger an update at most once every 5 minutes on GitLab.com with [the limit set by the administrator on self-managed instances](../../../administration/instance_limits.md#pull-mirroring-interval). -## Overview - -Repository mirroring is useful when you want to use a repository outside of GitLab. - There are two kinds of repository mirroring supported by GitLab: -- Push: for mirroring a GitLab repository to another location. -- Pull: for mirroring a repository from another location to GitLab. **(STARTER)** +- [Push](#pushing-to-a-remote-repository): for mirroring a GitLab repository to another location. **(CORE)** +- [Pull](#pulling-from-a-remote-repository): for mirroring a repository from another location to GitLab. **(STARTER)** When the mirror repository is updated, all new branches, tags, and commits will be visible in the project's activity feed. @@ -31,8 +28,7 @@ immediate update, unless: - The mirror is already being updated. - The [limit for pull mirroring interval seconds](../../../administration/instance_limits.md#pull-mirroring-interval) has not elapsed since its last update. -For security reasons, in [GitLab 12.10 and later](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/27166), -the URL to the original repository is only displayed to users with +For security reasons, the URL to the original repository is only displayed to users with Maintainer or Owner permissions to the mirrored project. ## Use cases @@ -62,7 +58,8 @@ For an existing project, you can set up push mirroring as follows: 1. Navigate to your project's **Settings > Repository** and expand the **Mirroring repositories** section. 1. Enter a repository URL. 1. Select **Push** from the **Mirror direction** dropdown. -1. Select an authentication method from the **Authentication method** dropdown, if necessary. +1. Select an authentication method from the **Authentication method** dropdown. + You can authenticate with either a password or an [SSH key](#ssh-authentication). 1. Check the **Only mirror protected branches** box, if necessary. 1. Check the **Keep divergent refs** box, if desired. 1. Click the **Mirror repository** button to save the configuration. @@ -88,17 +85,7 @@ section. You can also create and modify project push mirrors through the [remote mirrors API](../../../api/remote_mirrors.md). -### Push only protected branches **(CORE)** - -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3350) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3. -> - [Moved to GitLab Core](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/18715) in 10.8. - -You can choose to only push your protected branches from GitLab to your remote repository. - -To use this option, check the **Only mirror protected branches** box when creating a repository -mirror. - -### Keep divergent refs **(CORE)** +### Keep divergent refs > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/208828) in GitLab 13.0. @@ -119,7 +106,7 @@ update. NOTE: After the mirror is created, this option can currently only be modified via the [API](../../../api/remote_mirrors.md). -## Setting up a push mirror from GitLab to GitHub **(CORE)** +### Setting up a push mirror from GitLab to GitHub To set up a mirror from GitLab to GitHub, you need to follow these steps: @@ -132,7 +119,7 @@ The mirrored repository will be listed. For example, `https://*****:*****@github The repository will push soon. To force a push, click the **Update now** (**{retry}**) button. -## Setting up a push mirror from GitLab to AWS CodeCommit +### Setting up a push mirror from GitLab to AWS CodeCommit AWS CodeCommit push mirroring is currently the best way to connect GitLab repositories to AWS CodePipeline, as GitLab is not yet supported as one of their Source Code Management (SCM) providers. @@ -210,7 +197,7 @@ To test mirroring by forcing a push, click the half-circle arrows button (hover If **Last successful update** shows a date, you have configured mirroring correctly. If it is not working correctly a red `error` tag appears and shows the error message as hover text. -## Setting up a push mirror to another GitLab instance with 2FA activated +### Setting up a push mirror to another GitLab instance with 2FA activated 1. On the destination GitLab instance, create a [personal access token](../../profile/personal_access_tokens.md) with `write_repository` scope. 1. On the source GitLab instance: @@ -249,8 +236,8 @@ To configure mirror pulling for an existing project: ![Repository mirroring pull settings screen - lower part](img/repository_mirroring_pull_settings_lower.png) Because GitLab is now set to pull changes from the upstream repository, you should not push commits -directly to the repository on GitLab. Instead, any commits should be pushed to the upstream repository. -Changes pushed to the upstream repository will be pulled into the GitLab repository, either: +directly to the repository on GitLab. Instead, any commits should be pushed to the remote repository. +Changes pushed to the remote repository will be pulled into the GitLab repository, either: - Automatically within a certain period of time. - When a [forced update](#forcing-an-update) is initiated. @@ -275,10 +262,62 @@ Repository mirrors are updated as Sidekiq becomes available to process them. If - Fails (for example, a branch diverged from upstream), it will be attempted again later. Mirrors can fail up to 14 times before they will not be enqueued for update again. -### SSH authentication +### Overwrite diverged branches **(STARTER)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4559) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. + +You can choose to always update your local branches with remote versions, even if they have +diverged from the remote. + +WARNING: +For mirrored branches, enabling this option results in the loss of local changes. + +To use this option, check the **Overwrite diverged branches** box when creating a repository mirror. + +### Trigger pipelines for mirror updates **(STARTER)** + +If this option is enabled, pipelines will be triggered when branches or tags are +updated from the remote repository. Depending on the activity of the remote +repository, this may greatly increase the load on your CI runners. Only enable +this if you know they can handle the load. CI will run using the credentials +assigned when you set up pull mirroring. + +### Hard failure **(STARTER)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3117) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2. + +Once the mirroring process is unsuccessfully retried 14 times in a row, it will get marked as hard +failed. This will become visible in either the: + +- Project's main dashboard. +- Pull mirror settings page. + +When a project is hard failed, it will no longer get picked up for mirroring. +You can resume the project mirroring again by [forcing an update](#forcing-an-update). + +### Trigger an update using the API **(STARTER)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3453) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3. + +Pull mirroring uses polling to detect new branches and commits added upstream, often minutes +afterwards. If you notify GitLab by [API](../../../api/projects.md#start-the-pull-mirroring-process-for-a-project), +updates will be pulled immediately. + +For more information, see [Start the pull mirroring process for a Project](../../../api/projects.md#start-the-pull-mirroring-process-for-a-project). + +## Mirror only protected branches **(STARTER)** + +Based on the mirror direction that you choose, you can opt to mirror only the +[protected branches](../protected_branches.md) from/to your remote repository. +For pull mirroring, non-protected branches are not mirrored and can diverge. + +To use this option, check the **Only mirror protected branches** box when +creating a repository mirror. -> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2551) for Pull mirroring in [GitLab Starter](https://about.gitlab.com/pricing/) 9.5. -> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22982) for Push mirroring in [GitLab Core](https://about.gitlab.com/pricing/) 11.6 +## SSH authentication + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/2551) in [GitLab Starter](https://about.gitlab.com/pricing/) 9.5 for Pull mirroring. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/22982) in [GitLab Core](https://about.gitlab.com/pricing/) 11.6 for Push mirroring. SSH authentication is mutual: @@ -367,50 +406,6 @@ NOTE: The generated keys are stored in the GitLab database, not in the filesystem. Therefore, SSH public key authentication for mirrors cannot be used in a pre-receive hook. -### Overwrite diverged branches **(STARTER)** - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/4559) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.6. - -You can choose to always update your local branches with remote versions, even if they have -diverged from the remote. - -WARNING: -For mirrored branches, enabling this option results in the loss of local changes. - -To use this option, check the **Overwrite diverged branches** box when creating a repository mirror. - -### Only mirror protected branches **(STARTER)** - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3326) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3. - -You can choose to pull mirror only the protected branches from your remote repository to GitLab. -Non-protected branches are not mirrored and can diverge. - -To use this option, check the **Only mirror protected branches** box when creating a repository mirror. - -### Hard failure **(STARTER)** - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3117) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.2. - -Once the mirroring process is unsuccessfully retried 14 times in a row, it will get marked as hard -failed. This will become visible in either the: - -- Project's main dashboard. -- Pull mirror settings page. - -When a project is hard failed, it will no longer get picked up for mirroring. A user can resume the -project mirroring again by [Forcing an update](#forcing-an-update). - -### Trigger update using API **(STARTER)** - -> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/3453) in [GitLab Starter](https://about.gitlab.com/pricing/) 10.3. - -Pull mirroring uses polling to detect new branches and commits added upstream, often minutes -afterwards. If you notify GitLab by [API](../../../api/projects.md#start-the-pull-mirroring-process-for-a-project), -updates will be pulled immediately. - -For more information, see [Start the pull mirroring process for a Project](../../../api/projects.md#start-the-pull-mirroring-process-for-a-project). - ## Forcing an update **(CORE)** While mirrors are scheduled to update automatically, you can always force an update by using the @@ -429,10 +424,7 @@ bidirectional mirroring, you should prepare for the likely conflicts by deciding them and how they will be resolved. Rewriting any mirrored commit on either remote will cause conflicts and mirroring to fail. This can -be prevented by: - -- [Pulling only protected branches](#only-mirror-protected-branches). -- [Pushing only protected branches](#push-only-protected-branches). +be prevented by [mirroring only protected branches](#mirror-only-protected-branches). You should [protect the branches](../protected_branches.md) you wish to mirror on both remotes to prevent conflicts caused by rewriting history. diff --git a/doc/user/project/repository/web_editor.md b/doc/user/project/repository/web_editor.md index 24bfeee5e7f..b9477da3937 100644 --- a/doc/user/project/repository/web_editor.md +++ b/doc/user/project/repository/web_editor.md @@ -19,7 +19,7 @@ From a project's files page, click the '+' button to the right of the branch sel Choose **New file** from the dropdown. ![New file dropdown menu](img/web_editor_new_file_dropdown.png) -Enter a file name in the **Filename** box. Then, add file content in the editor +Enter a filename in the **Filename** box. Then, add file content in the editor area. Add a descriptive commit message and choose a branch. The branch field will default to the branch you were viewing in the file browser. If you enter a new branch name, a checkbox will appear, allowing you to start a new merge diff --git a/doc/user/project/requirements/index.md b/doc/user/project/requirements/index.md index 9d75c4ab071..c99b0d91523 100644 --- a/doc/user/project/requirements/index.md +++ b/doc/user/project/requirements/index.md @@ -34,7 +34,7 @@ Users with Reporter or higher [permissions](../../permissions.md) can create req To create a requirement: -1. From your project page, go to **Requirements**. +1. In a project, go to **Requirements**. 1. Select **New requirement**. 1. Enter a title and description and select **Create requirement**. @@ -200,10 +200,10 @@ requirements_confirmation: > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/246857) in GitLab 13.7. -You can import requirements to a project by uploading a CSV file with the columns -`title` and `description`. +You can import requirements to a project by uploading a [CSV file](https://en.wikipedia.org/wiki/Comma-separated_values) +with the columns `title` and `description`. -The user uploading the CSV file will be set as the author of the imported requirements. +After the import, the user uploading the CSV file is set as the author of the imported requirements. Users with Reporter or higher [permissions](../../permissions.md) can import requirements. @@ -213,20 +213,20 @@ Before you import your file: - Consider importing a test file containing only a few requirements. There is no way to undo a large import without using the GitLab API. -- Ensure your CSV file meets the [file format](#csv-file-format) requirements. +- Ensure your CSV file meets the [file format](#imported-csv-file-format) requirements. To import requirements: -1. Navigate to a project's Requirements page. - - If the project already has existing requirements, click the import icon (**{import}**) at the +1. In a project, go to **Requirements**. + - If the project already has existing requirements, select the import icon (**{import}**) in the top right. - - For a project without any requirements, click **Import CSV** in the middle of the page. -1. Select the file and click **Import requirements**. + - For a project without any requirements, select **Import CSV** in the middle of the page. +1. Select the file and select **Import requirements**. The file is processed in the background and a notification email is sent to you after the import is complete. -### CSV file format +### Imported CSV file format When importing requirements from a CSV file, it must be formatted in a certain way: @@ -257,3 +257,37 @@ Another Title,"A description, with a comma" The limit depends on the configuration value of Max Attachment Size for the GitLab instance. For GitLab.com, it is set to 10 MB. + +## Export requirements to a CSV file + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/290813) in GitLab 13.8. + +You can export GitLab requirements to a +[CSV file](https://en.wikipedia.org/wiki/Comma-separated_values) sent to your default notification +email as an attachment. + +By exporting requirements, you and your team can import them into another tool or share them with +your customers. Exporting requirements can aid collaboration with higher-level systems, as well as +audit and regulatory compliance tasks. + +Users with Reporter or higher [permissions](../../permissions.md) can export requirements. + +To export requirements: + +1. In a project, go to **Requirements**. +1. Select the **Export as CSV** icon (**{export}**) in the top right. A confirmation modal appears. +1. Select **Export requirements**. The exported CSV file is sent to the email address associated with your user. + +### Exported CSV file format + +You can preview the exported CSV file in a spreadsheet editor, such as Microsoft Excel, +OpenOffice Calc, or Google Sheets. + +The exported CSV file contains the following columns: + +- Requirement ID +- Title +- Description +- Author Username +- Latest Test Report State +- Latest Test Report Created At (UTC) diff --git a/doc/user/project/service_desk.md b/doc/user/project/service_desk.md index 4f3ca12c582..76156690fe7 100644 --- a/doc/user/project/service_desk.md +++ b/doc/user/project/service_desk.md @@ -10,32 +10,38 @@ info: To determine the technical writer assigned to the Stage/Group associated w > - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/214839) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.0. > - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215364) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.2. -Service Desk is a module that allows your team to connect directly -with any external party through email right inside of GitLab; no external tools required. -An ongoing conversation right where your software is built ensures that user feedback ends -up directly where it's needed, helping you build the right features to solve your users' -real problems. +Service Desk is a module that allows your team to connect +with any external party through email, without any external tools. +An ongoing conversation in the same place as where your software +is built ensures user feedback ends up where it's needed. -With Service Desk, you can provide efficient email support to your customers, who can now -email you bug reports, feature requests, or general feedback that will all end up in your -GitLab project as new issues. In turn, your team can respond straight from the project. +With Service Desk, you can provide efficient email support to your customers. They can +email you bug reports, feature requests, or general feedback. They all end up in your +GitLab project as new issues. In turn, your team can respond directly from the project. As Service Desk is built right into GitLab itself, the complexity and inefficiencies -of multiple tools and external integrations are eliminated, significantly shortening +of multiple tools and external integrations are eliminated. This significantly shortens the cycle time from feedback to software update. For an overview, check the video demonstration on [GitLab Service Desk](https://about.gitlab.com/blog/2017/05/09/demo-service-desk/). -## Use cases +## How it works + +GitLab Service Desk enables people to create issues in your +GitLab instance without needing their own user account. + +It provides a unique email address for end users to create issues in a project. +Follow-up notes can be sent either through the GitLab interface or by email. End +users only see the thread through email. For instance, let's assume you develop a game for iOS or Android. The codebase is hosted in your GitLab instance, built and deployed with GitLab CI/CD. -Here's how Service Desk will work for you: +Here's how Service Desk works for you: 1. You provide a project-specific email address to your paying customers, who can email you directly - from within the app. + from the application. 1. Each email they send creates an issue in the appropriate project. 1. Your team members navigate to the Service Desk issue tracker, where they can see new support requests and respond inside associated issues. @@ -43,61 +49,54 @@ Here's how Service Desk will work for you: 1. Your team starts working on implementing code to solve your customer's problem. 1. When your team finishes the implementation, whereupon the merge request is merged and the issue is closed automatically. -1. The customer will have been attended successfully via email, without having real access to your +1. The customer's requests are handled through email, without ever having access to your GitLab instance. 1. Your team saved time by not having to leave GitLab (or setup any integrations) to follow up with your customer. -## How it works - -GitLab Service Desk is a simple way to allow people to create issues in your -GitLab instance without needing their own user account. - -It provides a unique email address for end users to create issues in a project, -and replies can be sent either through the GitLab interface or by email. End -users will only see the thread through email. - ## Configuring Service Desk NOTE: Service Desk is enabled on GitLab.com. You can skip step 1 below; you only need to enable it per project. -If you have project maintainer access you have the option to set up Service Desk. -Follow these steps to do so: +If you have project maintainer access you have the option to set up Service Desk. Follow these steps: 1. [Set up incoming email](../../administration/incoming_email.md#set-it-up) for the GitLab instance. - - We recommend using [email sub-addressing](../../administration/incoming_email.md#email-sub-addressing), - but in GitLab 11.7 and later you can also use [catch-all mailboxes](../../administration/incoming_email.md#catch-all-mailbox). + We recommend using [email sub-addressing](../../administration/incoming_email.md#email-sub-addressing), + but in GitLab 11.7 and later you can also use [catch-all mailboxes](../../administration/incoming_email.md#catch-all-mailbox). 1. Navigate to your project's **Settings > General** and locate the **Service Desk** section. 1. Enable the **Activate Service Desk** toggle. This reveals a unique email address to email issues - to the project. These issues will be [confidential](issues/confidential_issues.md), so they will - only be visible to project members. Note that in GitLab 11.7, we updated the generated email + to the project. These issues are [confidential](issues/confidential_issues.md), so they are + only visible to project members. Note that in GitLab 11.7, we updated the generated email address's format. The older format is still supported, however, allowing existing aliases or contacts to continue working. WARNING: - This email address can be used by anyone to create an issue on this project, whether or not they - have access to your GitLab instance. We recommend **putting this behind an alias** so it can be - changed if needed, and **[enabling Akismet](../../integration/akismet.md)** on your GitLab + This email address can be used by anyone to create an issue on this project, regardless + of their access level to your GitLab instance. We recommend **putting this behind an alias** so it can be + changed if needed. We also recommend **[enabling Akismet](../../integration/akismet.md)** on your GitLab instance to add spam checking to this service. Unblocked email spam would result in many spam issues being created. If you have [templates](description_templates.md) in your repository, you can optionally select one from the selector menu to append it to all Service Desk issues. - ![Service Desk enabled](img/service_desk_enabled.png) - -Service Desk is now enabled for this project! You should be able to access it from your project -navigation's **Issues** menu. +Service Desk is now enabled for this project! You should be able to access it from your project's +**Issues** menu. ![Service Desk Navigation Item](img/service_desk_nav_item.png) ### Using customized email templates - > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2460) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2460) in [GitLab Premium](https://about.gitlab.com/pricing/) 12.7. +> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/214839) to [GitLab Starter](https://about.gitlab.com/pricing/) in 13.0. +> - [Moved](https://gitlab.com/gitlab-org/gitlab/-/issues/215364) to [GitLab Core](https://about.gitlab.com/pricing/) in 13.2. + +An email is sent to the author when: -When a user submits a new issue using Service Desk, or when a new note is created on a Service Desk issue, an email is sent to the author. +- A user submits a new issue using Service Desk. +- A new note is created on a Service Desk issue. The body of these email messages can be customized by using templates. To create a new customized template, create a new Markdown (`.md`) file inside the `.gitlab/service_desk_templates/` @@ -106,39 +105,46 @@ directory in your repository. Commit and push to your default branch. #### Thank you email The **Thank you email** is the email sent to a user after they submit an issue. -The file name of the template has to be `thank_you.md`. -You can use `%{ISSUE_ID}` placeholder which will be replaced by an issue IID in the email and -`%{ISSUE_PATH}` placeholder which will be replaced by project path and the issue IID. +The filename of the template has to be `thank_you.md`. +There are a few placeholders you can use which are automatically replaced in the email: + +- `%{ISSUE_ID}`: issue IID +- `%{ISSUE_PATH}`: project path appended with the issue IID + As the Service Desk issues are created as confidential (only project members can see them) the response email does not provide the issue link. #### New note email -The **New note email** is the email sent to a user when the issue they submitted has a new comment. -The file name of the template has to be `new_note.md`. -You can use `%{ISSUE_ID}` placeholder which will be replaced by an issue IID -in the email, `%{ISSUE_PATH}` placeholder which will be replaced by - project path and the issue IID and `%{NOTE_TEXT}` placeholder which will be replaced by the note text. +When a user-submitted issue receives a new comment, GitLab sends a **New note email** +to the user. The filename of this template must be `new_note.md`, and you can +use these placeholders in the email: + +- `%{ISSUE_ID}`: issue IID +- `%{ISSUE_PATH}`: project path appended with the issue IID +- `%{NOTE_TEXT}`: note text ### Using custom email display name > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7529) in GitLab 12.8. -You can customize the email display name. Emails sent from Service Desk will have +You can customize the email display name. Emails sent from Service Desk have this name in the `From` header. The default display name is `GitLab Support Bot`. -### Using custom email address **(CORE ONLY)** +To edit the custom email display name: + +1. In a project, go to **Settings > General > Service Desk**. +1. Enter a new name in **Email display name**. +1. Select **Save Changes**. + +### Using custom email address > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/2201) in [GitLab Premium](https://about.gitlab.com/pricing/) 13.0. -> - It was [deployed behind a feature flag](../feature_flags.md), disabled by default. -> - [Became enabled by default](https://gitlab.com/gitlab-org/gitlab/-/issues/284656) on GitLab 13.7. -> - It's enabled on GitLab.com. -> - It's recommended for production use. -> - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-custom-email-address). **(CORE ONLY)** - -If the `service_desk_email` feature flag is enabled in your configuration, -then it's possible to create Service Desk issues by sending emails to the -custom Service Desk email address, which should have the following format: +> - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/issues/284656) in GitLab 13.8. + +If the `service_desk_email` is configured, then you can create Service Desk +issues by sending emails to the Service Desk email address. The default +address has the following format: `project_contact+%{key}@example.com`. The `%{key}` part is used to find the project where the issue should be created. The @@ -148,53 +154,57 @@ The `%{key}` part is used to find the project where the issue should be created. You can set the project name suffix in your project's Service Desk settings. It can contain only lowercase letters (`a-z`), numbers (`0-9`), or underscores (`_`). -![Setting custom Service Desk email address](img/service_desk_custom_email_address_v13_0.png) +NOTE: +The `service_desk_email` and `incoming_email` configurations should +always use separate mailboxes. This is important, because emails picked from +`service_desk_email` mailbox are processed by a different worker and it would +not recognize `incoming_email` emails. -You can add the following snippets to your configuration. +To configure a custom email address for Service Desk, add the following snippets to your configuration file: -Example for installations from source: +- Example for installations from source: -```yaml -service_desk_email: - enabled: true - address: "project_contact+%{key}@example.com" - user: "project_support@example.com" - password: "[REDACTED]" - host: "imap.gmail.com" - port: 993 - ssl: true - start_tls: false - log_path: "log/mailroom.log" - mailbox: "inbox" - idle_timeout: 60 - expunge_deleted: true -``` + ```yaml + service_desk_email: + enabled: true + address: "project_contact+%{key}@example.com" + user: "project_support@example.com" + password: "[REDACTED]" + host: "imap.gmail.com" + port: 993 + ssl: true + start_tls: false + log_path: "log/mailroom.log" + mailbox: "inbox" + idle_timeout: 60 + expunge_deleted: true + ``` -Example for Omnibus GitLab installations: +- Example for Omnibus GitLab installations: -```ruby -gitlab_rails['service_desk_email_enabled'] = true + ```ruby + gitlab_rails['service_desk_email_enabled'] = true -gitlab_rails['service_desk_email_address'] = "project_contact+%{key}@gmail.com" + gitlab_rails['service_desk_email_address'] = "project_contact+%{key}@gmail.com" -gitlab_rails['service_desk_email_email'] = "project_support@gmail.com" + gitlab_rails['service_desk_email_email'] = "project_support@gmail.com" -gitlab_rails['service_desk_email_password'] = "[REDACTED]" + gitlab_rails['service_desk_email_password'] = "[REDACTED]" -gitlab_rails['service_desk_email_mailbox_name'] = "inbox" + gitlab_rails['service_desk_email_mailbox_name'] = "inbox" -gitlab_rails['service_desk_email_idle_timeout'] = 60 + gitlab_rails['service_desk_email_idle_timeout'] = 60 -gitlab_rails['service_desk_email_log_file'] = "/var/log/gitlab/mailroom/mail_room_json.log" + gitlab_rails['service_desk_email_log_file'] = "/var/log/gitlab/mailroom/mail_room_json.log" -gitlab_rails['service_desk_email_host'] = "imap.gmail.com" + gitlab_rails['service_desk_email_host'] = "imap.gmail.com" -gitlab_rails['service_desk_email_port'] = 993 + gitlab_rails['service_desk_email_port'] = 993 -gitlab_rails['service_desk_email_ssl'] = true + gitlab_rails['service_desk_email_ssl'] = true -gitlab_rails['service_desk_email_start_tls'] = false -``` + gitlab_rails['service_desk_email_start_tls'] = false + ``` In this case, suppose the `mygroup/myproject` project Service Desk settings has the project name suffix set to `support`, and a user sends an email to `project_contact+mygroup-myproject-support@example.com`. @@ -203,27 +213,10 @@ As a result, a new Service Desk issue is created from this email in the `mygroup The configuration options are the same as for configuring [incoming email](../../administration/incoming_email.md#set-it-up). -#### Disable custom email address **(CORE ONLY)** - -Service Desk custom email is under development but ready for production use. -It is deployed behind a feature flag that is **enabled by default**. -[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) -can opt to disable it. - -To enable it: - -```ruby -Feature.enable(:service_desk_custom_address) -``` - -To disable it: - -```ruby -Feature.disable(:service_desk_custom_address) -``` - ## Using Service Desk +There are a few ways Service Desk can be used. + ### As an end user (issue creator) To create a Service Desk issue, an end user does not need to know anything about @@ -235,29 +228,30 @@ receive an email back confirming receipt: This also gives the end user an option to unsubscribe. If they don't choose to unsubscribe, then any new comments added to the issue -will be sent as emails: +are sent as emails: ![Service Desk reply email](img/service_desk_reply.png) -And any responses they send will be displayed in the issue itself. +Any responses they send via email are displayed in the issue itself. ### As a responder to the issue -For responders to the issue, everything works as usual. They will see a familiar looking -issue tracker, where they can see issues created via customer support requests and -filter and interact with them just like other GitLab issues. +For responders to the issue, everything works just like other GitLab issues. +GitLab displays a familiar-looking issue tracker where responders can see +issues created through customer support requests, and filter or interact with them. ![Service Desk Issue tracker](img/service_desk_issue_tracker.png) -Messages from the end user will show as coming from the special Support Bot user, but apart from that, -you can read and write comments as you normally do: +Messages from the end user are shown as coming from the special +[Support Bot user](../../subscriptions/self_managed/index.md#billable-users). +You can read and write comments as you normally do in GitLab: ![Service Desk issue thread](img/service_desk_thread.png) Note that: - The project's visibility (private, internal, public) does not affect Service Desk. -- The path to the project, including its group or namespace, will be shown on emails. +- The path to the project, including its group or namespace, are shown in emails. ### Support Bot user diff --git a/doc/user/project/settings/import_export.md b/doc/user/project/settings/import_export.md index 53233cc347e..27727890383 100644 --- a/doc/user/project/settings/import_export.md +++ b/doc/user/project/settings/import_export.md @@ -179,7 +179,7 @@ If use of the `Internal` visibility level all imported projects are given the visibility of `Private`. NOTE: -The maximum import file size can be set by the Administrator, default is 50MB. +The maximum import file size can be set by the Administrator, default is `0` (unlimited). As an administrator, you can modify the maximum import file size. To do so, use the `max_import_size` option in the [Application settings API](../../../api/settings.md#change-application-settings) or the [Admin Area UI](../../admin_area/settings/account_and_limit_settings.md). ### Project import status diff --git a/doc/user/project/settings/index.md b/doc/user/project/settings/index.md index 41f404de4f2..26ef5e2260a 100644 --- a/doc/user/project/settings/index.md +++ b/doc/user/project/settings/index.md @@ -52,10 +52,6 @@ If you set **Project Visibility** to public, you can limit access to some featur to **Only Project Members**. In addition, you can select the option to [Allow users to request access](../members/index.md#project-membership-and-requesting-access). -WARNING: -If you [reduce a project's visibility level](../../../public_access/public_access.md#reducing-visibility), -that action unlinks all forks of that project. - Use the switches to enable or disable the following features: | Option | More access limit options | Description | diff --git a/doc/user/project/settings/project_access_tokens.md b/doc/user/project/settings/project_access_tokens.md index 494f0b725e3..39de9ab9ca2 100644 --- a/doc/user/project/settings/project_access_tokens.md +++ b/doc/user/project/settings/project_access_tokens.md @@ -38,8 +38,10 @@ For examples of how you can use a project access token to authenticate with the ## Project bot users -For each project access token created, a bot user will also be created and added to the project with -["Maintainer" level permissions](../../permissions.md#project-members-permissions). +Project bot users are [GitLab-created service accounts](../../../subscriptions/self_managed/index.md#billable-users) and do not count as licensed seats. + +For each project access token created, a bot user is created and added to the project with +[Maintainer level permissions](../../permissions.md#project-members-permissions). For the bot: @@ -49,15 +51,15 @@ For the bot: API calls made with a project access token are associated with the corresponding bot user. -These users will appear in **Members** but can not be modified. -Furthermore, the bot user can not be added to any other project. +These bot users are included in a project's **Members** list but cannot be modified. Also, a bot +user cannot be added to any other project. - The username is set to `project_{project_id}_bot` for the first access token, such as `project_123_bot`. - The username is set to `project_{project_id}_bot{bot_count}` for further access tokens, such as `project_123_bot1`. -When the project access token is [revoked](#revoking-a-project-access-token) the bot user is then deleted and all records are moved to a system-wide user with the username "Ghost User". For more information, see [Associated Records](../../profile/account/delete_account.md#associated-records). - -Project bot users are [GitLab-created service accounts](../../../subscriptions/self_managed/index.md#billable-users) and do not count as licensed seats. +When the project access token is [revoked](#revoking-a-project-access-token) the bot user is deleted +and all records are moved to a system-wide user with the username "Ghost User". For more +information, see [Associated Records](../../profile/account/delete_account.md#associated-records). ## Revoking a project access token @@ -72,7 +74,7 @@ the following table. | Scope | Description | | ------------------ | ----------- | -| `api` | Grants complete read/write access to the scoped project API, including the Package Registry](../../packages/package_registry/index.md). | +| `api` | Grants complete read/write access to the scoped project API, including the [Package Registry](../../packages/package_registry/index.md). | | `read_api` | Grants read access to the scoped project API, including the [Package Registry](../../packages/package_registry/index.md). | | `read_registry` | Allows read-access (pull) to [container registry](../../packages/container_registry/index.md) images if a project is private and authorization is required. | | `write_registry` | Allows write-access (push) to [container registry](../../packages/container_registry/index.md). | diff --git a/doc/user/project/web_ide/index.md b/doc/user/project/web_ide/index.md index 29b24028e48..af8e78afb28 100644 --- a/doc/user/project/web_ide/index.md +++ b/doc/user/project/web_ide/index.md @@ -33,8 +33,8 @@ start seeing results. ## Command palette You can see all available commands for manipulating editor content by pressing -the <kbd>F1</kbd> key when the editor is in focus. After that, -you'll see a complete list of available commands for +the <kbd>F1</kbd> key when the editor is in focus. After that, the editor displays +a complete list of available commands for manipulating editor content. The editor supports commands for multi-cursor editing, code block folding, commenting, searching and replacing, navigating editor warnings and suggestions, and more. @@ -47,7 +47,7 @@ the command without having to select it in the command palette. ## Syntax highlighting -As expected from an IDE, syntax highlighting for many languages within +As expected from an IDE, syntax highlighting for many languages in the Web IDE makes your direct editing even easier. The Web IDE currently provides: @@ -78,7 +78,7 @@ All the themes GitLab supports for syntax highlighting are added to the Web IDE' You can pick a theme from your [profile preferences](../../profile/preferences.md). The themes are available only in the Web IDE file editor, except for the [dark theme](https://gitlab.com/gitlab-org/gitlab/-/issues/209808) and -the [solarized dark theme](https://gitlab.com/gitlab-org/gitlab/-/issues/219228), +the [Solarized dark theme](https://gitlab.com/gitlab-org/gitlab/-/issues/219228), which apply to the entire Web IDE screen. | Solarized Light Theme | Solarized Dark Theme | Dark Theme | @@ -144,12 +144,13 @@ schemas: Each schema entry supports two properties: -- `uri`: please provide an absolute URL for the schema definition file here. The schema from this URL -is loaded when a matching file is open. -- `match`: a list of matching paths or glob expressions. If a schema matches a particular path pattern, -it will be applied to that file. Please enclose the pattern in quotes if it begins with an asterisk (`*`), -it's be applied to that file. If a pattern begins with an asterisk (`*`), enclose it in quotation -marks. Otherwise, the configuration file is not valid YAML. +- `uri`: please provide an absolute URL for the schema definition file here. + The schema from this URL is loaded when a matching file is open. +- `match`: a list of matching paths or glob expressions. If a schema matches a + particular path pattern, it is applied to that file. Please enclose the pattern + in quotes if it begins with an asterisk (`*`), it's be applied to that file. + If a pattern begins with an asterisk (`*`), enclose it in quotation marks. + Otherwise, the configuration file is not valid YAML. ## Configure the Web IDE @@ -180,7 +181,7 @@ The Web IDE currently supports the following `.editorconfig` settings: After making your changes, click the **Commit** button on the bottom-left to review the list of changed files. -Once you have finalized your changes, you can add a commit message, commit the +After you have finalized your changes, you can add a commit message, commit the changes and directly create a merge request. In case you don't have write access to the selected branch, you see a warning, but can still create a new branch and start a merge request. @@ -268,7 +269,7 @@ GitLab.com ![Administrator Live Preview setting](img/admin_live_preview_v13_0.png) -Once you have done that, you can preview projects with a `package.json` file and +After you have done that, you can preview projects with a `package.json` file and a `main` entry point inside the Web IDE. An example `package.json` is shown below. @@ -325,7 +326,7 @@ In order to enable the Web IDE terminals you need to create the file file is fairly similar to the [CI configuration file](../../../ci/yaml/README.md) syntax but with some restrictions: -- No global blocks can be defined (i.e., `before_script` or `after_script`) +- No global blocks (such as `before_script` or `after_script`) can be defined. - Only one job named `terminal` can be added to this file. - Only the keywords `image`, `services`, `tags`, `before_script`, `script`, and `variables` are allowed to be used to configure the job. @@ -350,7 +351,7 @@ terminal: NODE_ENV: "test" ``` -Once the terminal has started, the console is displayed and we could access +After the terminal has started, the console is displayed and we could access the project repository files. **Important**. The terminal job is branch dependent. This means that the @@ -364,7 +365,7 @@ If there is no configuration file in a branch, an error message is shown. If Interactive Terminals are available for the current user, the **Terminal** button is visible in the right sidebar of the Web IDE. Click this button to open or close the terminal tab. -Once open, the tab shows the **Start Web Terminal** button. This button may +After opening, the tab shows the **Start Web Terminal** button. This button may be disabled if the environment is not configured correctly. If so, a status message describes the issue. Here are some reasons why **Start Web Terminal** may be disabled: @@ -378,7 +379,7 @@ can be closed and reopened and the state of the terminal is not affected. When the terminal is started and is successfully connected to the runner, then the runner's shell prompt appears in the terminal. From here, you can enter -commands executed within the runner's environment. This is similar +commands executed in the runner's environment. This is similar to running commands in a local terminal or through SSH. While the terminal is running, it can be stopped by clicking **Stop Terminal**. @@ -426,7 +427,7 @@ terminal: [predefined environment variable](../../../ci/variables/predefined_variables.md) for GitLab Runners. This is where your project's repository resides. -Once you have configured the web terminal for file syncing, then when the web +After you have configured the web terminal for file syncing, then when the web terminal is started, a **Terminal** status is visible in the status bar. ![Web IDE Client Side Evaluation](img/terminal_status.png) @@ -434,7 +435,7 @@ terminal is started, a **Terminal** status is visible in the status bar. Changes made to your files via the Web IDE sync to the running terminal when: -- <kbd>Ctrl</kbd> + <kbd>S</kbd> (or <kbd>Cmd</kbd> + <kbd>S</kbd> on Mac) +- <kbd>Control</kbd> + <kbd>S</kbd> (or <kbd>Command</kbd> + <kbd>S</kbd> on Mac) is pressed while editing a file. - Anything outside the file editor is clicked after editing a file. - A file or folder is created, deleted, or renamed. @@ -446,7 +447,7 @@ The Web IDE has a few limitations: - Interactive Terminals is in a beta phase and continues to be improved in upcoming releases. In the meantime, please note that the user is limited to having only one active terminal at a time. -- LFS files can be rendered and displayed but they cannot be updated and committed using the Web IDE. If an LFS file is modified and pushed to the repository, the LFS pointer in the repository will be overwritten with the modified LFS file content. +- LFS files can be rendered and displayed but they cannot be updated and committed using the Web IDE. If an LFS file is modified and pushed to the repository, the LFS pointer in the repository is overwritten with the modified LFS file content. ### Troubleshooting diff --git a/doc/user/project/wiki/index.md b/doc/user/project/wiki/index.md index 7802f2ba95e..779179a6665 100644 --- a/doc/user/project/wiki/index.md +++ b/doc/user/project/wiki/index.md @@ -204,13 +204,11 @@ otherwise they will not display when pushed to GitLab: ## Customizing sidebar -On the project's Wiki page, there is a right side navigation that renders the full Wiki pages list by default, with hierarchy. +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/23109) in GitLab 13.8, the sidebar can be customized by clicking the **Edit sidebar** button. -To customize the sidebar, you can create a file named `_sidebar` to fully replace the default navigation. +To customize the Wiki's navigation sidebar, you need Developer permissions to the project. -WARNING: -Unless you link the `_sidebar` file from your custom nav, to edit it you'll have to access it directly -from the browser's address bar by typing: `https://gitlab.com/<namespace>/<project_name>/-/wikis/_sidebar` (for self-managed GitLab instances, replace `gitlab.com` with your instance's URL). +On the top-right, click **Edit sidebar** and make your changes. This creates a wiki page named `_sidebar` which fully replaces the default sidebar navigation. Example for `_sidebar` (using Markdown format): diff --git a/doc/user/search/advanced_search_syntax.md b/doc/user/search/advanced_search_syntax.md index fe2371947b4..e3501be8e8e 100644 --- a/doc/user/search/advanced_search_syntax.md +++ b/doc/user/search/advanced_search_syntax.md @@ -52,14 +52,17 @@ The Advanced Search Syntax also supports the use of filters. The available filte - blob: Filters by Git `object ID`. Exact match only. To use them, add them to your keyword in the format `<filter_name>:<value>` without -any spaces between the colon (`:`) and the value. A keyword or an asterisk (`*`) is required for filter searches and has to be added in front of the filter separated by a space. +any spaces between the colon (`:`) and the value. When no keyword is provided, an asterisk (`*`) will be used as the keyword. Examples: - Finding a file with any content named `search_results.rb`: [`* filename:search_results.rb`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=*+filename%3Asearch_results.rb&group_id=9970&project_id=278964) -- Finding a file named `found_blob_spec.rb` with the text `CHANGELOG` inside of it: [`CHANGELOG filename:found_blob_spec.rb](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=CHANGELOG+filename%3Afound_blob_spec.rb&group_id=9970&project_id=278964) +- The leading asterisk (`*`) can be ignored in the case above: [`filename:search_results.rb`](https://gitlab.com/search?group_id=9970&project_id=278964&scope=blobs&search=filename%3Asearch_results.rb) +- Finding a file named `found_blob_spec.rb` with the text `CHANGELOG` inside of it: [`CHANGELOG filename:found_blob_spec.rb`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=CHANGELOG+filename%3Afound_blob_spec.rb&group_id=9970&project_id=278964) - Finding the text `EpicLinks` inside files with the `.rb` extension: [`EpicLinks extension:rb`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=EpicLinks+extension%3Arb&group_id=9970&project_id=278964) +- Finding any file with the `.yaml` extension: [`extension:yaml`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=extension%3Ayaml&group_id=9970&project_id=278964) - Finding the text `Sidekiq` in a file, when that file is in a path that includes `elastic`: [`Sidekiq path:elastic`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=Sidekiq+path%3Aelastic&group_id=9970&project_id=278964) +- Finding any file in a path that includes `elasticsearch`: [`path:elasticsearch`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=path%3Aelasticsearch&group_id=9970&project_id=278964) - Finding the files represented by the Git object ID `998707b421c89bd9a3063333f9f728ef3e43d101`: [`* blob:998707b421c89bd9a3063333f9f728ef3e43d101`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=false&scope=blobs&repository_ref=&search=*+blob%3A998707b421c89bd9a3063333f9f728ef3e43d101&group_id=9970) - Syntax filters can be combined for complex filtering. Finding any file starting with `search` containing `eventHub` and with the `.js` extension: [`eventHub filename:search* extension:js`](https://gitlab.com/search?utf8=%E2%9C%93&snippets=&scope=blobs&repository_ref=&search=eventHub+filename%3Asearch*+extension%3Ajs&group_id=9970&project_id=278964) diff --git a/doc/user/search/img/project_search_general_settings_v13_8.png b/doc/user/search/img/project_search_general_settings_v13_8.png Binary files differnew file mode 100644 index 00000000000..08395e0d4f9 --- /dev/null +++ b/doc/user/search/img/project_search_general_settings_v13_8.png diff --git a/doc/user/search/index.md b/doc/user/search/index.md index 8c3d941192c..d229c27b608 100644 --- a/doc/user/search/index.md +++ b/doc/user/search/index.md @@ -18,7 +18,7 @@ The number displayed on their right represents the number of issues and merge re ![issues and MRs dashboard links](img/dashboard_links.png) -When you click **Issues**, you'll see the opened issues assigned to you straight away: +When you click **Issues**, the opened issues assigned to you are shown straight away: ![Issues assigned to you](img/issues_assigned_to_you.png) @@ -29,14 +29,18 @@ You can also filter the results using the search and filter field, as described ### Issues and MRs assigned to you or created by you -You'll also find shortcuts to issues and merge requests created by you or assigned to you +GitLab shows shortcuts to issues and merge requests created by you or assigned to you on the search field on the top-right of your screen: ![shortcut to your issues and merge requests](img/issues_mrs_shortcut.png) ### Filtering issue and merge request lists -Follow these steps to filter the **Issues** and **Merge Requests** list pages within projects and +> - Filtering by Epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.9. +> - Filtering by child Epics was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0. +> - Filtering by Iterations was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6. + +Follow these steps to filter the **Issues** and **Merge Requests** list pages in projects and groups: 1. Click in the field **Search or filter results...**. @@ -44,15 +48,12 @@ groups: - Author - Assignee - [Milestone](../project/milestones/index.md) - - [Iteration](../group/iterations/index.md) ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/118742) in [GitLab Starter](https://about.gitlab.com/pricing/) 13.6) + - [Iteration](../group/iterations/index.md) - Release - [Label](../project/labels.md) - My-reaction - Confidential - - Epic ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/195704) in GitLab 12.9), - including [child epic](../group/epics/index.md#multi-level-child-epics) - ([introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/9029) in - [GitLab Ultimate](https://about.gitlab.com/pricing/) 13.0) + - [Epic and child Epic](../group/epics/index.md) (available only for the group the Epic was created, not for [higher group levels](https://gitlab.com/gitlab-org/gitlab/-/issues/233729)). - Search for this text 1. Select or type the operator to use for filtering the attribute. The following operators are available: @@ -73,7 +74,7 @@ Some filter fields like milestone and assignee, allow you to filter by **None** ![filter by none any](img/issues_filter_none_any.png) -Selecting **None** returns results that have an empty value for that field. E.g.: no milestone, no assignee. +Selecting **None** returns results that have an empty value for that field. For example: no milestone, no assignee. Selecting **Any** does the opposite. It returns results that have a non-empty value for that field. @@ -82,11 +83,11 @@ Selecting **Any** does the opposite. It returns results that have a non-empty va You can filter issues and merge requests by specific terms included in titles or descriptions. - Syntax - - Searches look for all the words in a query, in any order. E.g.: searching - issues for `display bug` will return all issues matching both those words, in any order. + - Searches look for all the words in a query, in any order. For example: searching + issues for `display bug` returns all issues matching both those words, in any order. - To find the exact term, use double quotes: `"display bug"` - Limitation - - For performance reasons, terms shorter than 3 chars are ignored. E.g.: searching + - For performance reasons, terms shorter than 3 chars are ignored. For example: searching issues for `included in titles` is same as `included titles` - Search is limited to 4096 characters and 64 terms per query. @@ -118,6 +119,13 @@ the dropdown) **Approved-By** and select the user. ![Filter MRs by approved by](img/filter_approved_by_merge_requests_v13_0.png) +### Filtering merge requests by reviewer **(CORE)** + +> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/47605) in GitLab 13.7. + +To filter review requested merge requests for a specific individual, you can type (or select from +the dropdown) **Reviewer** and select the user. + ### Filtering merge requests by environment or deployment date **(CORE)** > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44041) in GitLab 13.6. @@ -149,7 +157,7 @@ relevant users or other attributes. For performance optimization, there is a requirement of a minimum of three characters to begin your search. For example, if you want to search for -issues that have the assignee "Simone Presley", you'll need to type at +issues that have the assignee "Simone Presley", you must type at least "Sim" before autocomplete gives any relevant results. ## Search history @@ -162,11 +170,11 @@ You can view recent searches by clicking on the little arrow-clock icon, which i Individual filters can be removed by clicking on the filter's (x) button or backspacing. The entire search filter can be cleared by clicking on the search box's (x) button or via <kbd>⌘</kbd> (Mac) + <kbd>⌫</kbd>. -To delete filter tokens one at a time, the <kbd>⌥</kbd> (Mac) / <kbd>Ctrl</kbd> + <kbd>⌫</kbd> keyboard combination can be used. +To delete filter tokens one at a time, the <kbd>⌥</kbd> (Mac) / <kbd>Control</kbd> + <kbd>⌫</kbd> keyboard combination can be used. ## Filtering with multiple filters of the same type -Some filters can be added multiple times. These include but are not limited to assignees and labels. When you filter with these multiple filters of the same type, the AND logic is applied. For example, if you were filtering `assignee:@sam assignee:@sarah`, your results will only include entries whereby the assignees are assigned to both Sam and Sarah are returned. +Some filters can be added multiple times. These include but are not limited to assignees and labels. When you filter with these multiple filters of the same type, the AND logic is applied. For example, if you were filtering `assignee:@sam assignee:@sarah`, your results include only entries whereby the assignees are assigned to both Sam and Sarah are returned. ![multiple assignees filtering](img/multiple_assignees.png) @@ -182,7 +190,7 @@ author, type, and action. Also, you can sort them by You can search through your projects from the left menu, by clicking the menu bar, then **Projects**. On the field **Filter by name**, type the project or group name you want to find, and GitLab -will filter them for you as you type. +filters them for you as you type. You can also look for the projects you [starred](../project/index.md#star-a-project) (**Starred projects**), and **Explore** all public and internal projects available in GitLab.com, from which you can filter by visibility, @@ -199,7 +207,7 @@ Similarly to [projects search](#projects), you can search through your groups fr the left menu, by clicking the menu bar, then **Groups**. On the field **Filter by name**, type the group name you want to find, and GitLab -will filter them for you as you type. +filters them for you as you type. You can also **Explore** all public and internal groups available in GitLab.com, and sort them by **Last created**, **Oldest created**, **Last updated**, or **Oldest updated**. @@ -211,15 +219,15 @@ You can also filter them by name (issue title), from the field **Filter by name* When you want to search for issues to add to lists present in your Issue Board, click the button **Add issues** on the top-right of your screen, opening a modal window from which -you'll be able to, besides filtering them by **Name**, **Author**, **Assignee**, **Milestone**, +you can, besides filtering them by **Name**, **Author**, **Assignee**, **Milestone**, and **Labels**, select multiple issues to add to a list of your choice: ![search and select issues to add to board](img/search_issues_board.png) ## Shortcut -You'll find a shortcut on the search field on the top-right of the project's dashboard to -quickly access issues and merge requests created or assigned to you within that project: +GitLab shows a shortcut on the search field on the top-right of the project's dashboard to +quickly access issues and merge requests created or assigned to you in that project: ![search per project - shortcut](img/project_search.png) @@ -234,12 +242,12 @@ You can also type in this search bar to see autocomplete suggestions for: - Recently viewed issues (try and type some word from the title of a recently viewed issue) - Recently viewed merge requests (try and type some word from the title of a recently viewed merge request) - Recently viewed epics (try and type some word from the title of a recently viewed epic) -- [GitLab Flavored Markdown](../markdown.md#special-gitlab-references) (GFM) for issues within a project (try and type a GFM reference for an issue) +- [GitLab Flavored Markdown](../markdown.md#special-gitlab-references) (GFM) for issues in a project (try and type a GFM reference for an issue) ## Basic search The Basic search in GitLab is a global search service that allows you to search -across the entire GitLab instance, within a group, or a single project. Basic search is +across the entire GitLab instance, in a group, or in a single project. Basic search is backed by the database and allows searching in: - Projects @@ -254,12 +262,12 @@ backed by the database and allows searching in: - Wiki (Project only) To start a search, type into the search bar on the top-right of the screen. You can always search -in all GitLab and may also see the options to search within a group or project if you are in the +in all GitLab and may also see the options to search in a group or project if you are in the group or project dashboard. ![basic search](img/basic_search.png) -Once the results are returned, you can modify the search, select a different type of data to +After the results are returned, you can modify the search, select a different type of data to search, or choose a specific group or project. ![basic_search_results](img/basic_search_results.png) @@ -274,11 +282,11 @@ the search field on the top-right of your screen while the project page is open. ### SHA search -You can quickly access a commit from within the project dashboard by entering the SHA -into the search field on the top right of the screen. If a single result is found, you will be +You can quickly access a commit from the project dashboard by entering the SHA +into the search field on the top right of the screen. If a single result is found, you are redirected to the commit result and given the option to return to the search results page. -![project sha search redirect](img/project_search_sha_redirect.png) +![project SHA search redirect](img/project_search_sha_redirect.png) ## Advanced Search **(STARTER)** @@ -292,3 +300,39 @@ GitLab instance. Use advanced queries for more targeted search results. [Learn how to use the Advanced Search Syntax.](advanced_search_syntax.md) + +## Search project settings + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/292941) in GitLab 13.8. +> - It's [deployed behind a feature flag](../feature_flags.md), disabled by default. +> - It's disabled on GitLab.com. +> - It's not recommended for production use. +> - To use it in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-search-project-settings). **(CORE ONLY)** + +WARNING: +This feature might not be available to you. Check the **version history** note above for details. + +You can search inside the project’s settings sections by entering a search +term in the search box located at the top of the page. The search results +appear highlighted in the sections that match the search term. + +![Search project settings](img/project_search_general_settings_v13_8.png) + +### Enable or disable Search project settings **(CORE ONLY)** + +Search project settings is under development and not ready for production use. It is +deployed behind a feature flag that is **disabled by default**. +[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md) +can enable it. + +To enable it: + +```ruby +Feature.enable(:search_settings_in_page) +``` + +To disable it: + +```ruby +Feature.disable(:search_settings_in_page) +``` diff --git a/doc/user/snippets.md b/doc/user/snippets.md index 33aa0bd253b..af499221da6 100644 --- a/doc/user/snippets.md +++ b/doc/user/snippets.md @@ -53,7 +53,7 @@ From there, add the **Title**, **Description**, and a **File** name with the appropriate extension (for example, `example.rb`, `index.html`). WARNING: -Make sure to add the file name to get code highlighting and to avoid this +Make sure to add the filename to get code highlighting and to avoid this [copy-pasting bug](https://gitlab.com/gitlab-org/gitlab/-/issues/22870). ## Versioned Snippets @@ -69,10 +69,10 @@ new commit to the master branch is recorded. Commit messages are automatically generated. The snippet's repository has only one branch (master) by default, deleting it or creating other branches is not supported. -Existing snippets will be automatically migrated in 13.0. Their current -content will be saved as the initial commit to the snippets' repository. +Existing snippets are automatically migrated in 13.0. Their current +content is saved as the initial commit to the snippets' repository. -### File names +### Filenames Snippets support syntax highlighting based on the filename and extension provided for them. While it is possible to submit a snippet @@ -86,10 +86,10 @@ number increases incrementally when more snippets without an attributed filename are added. When upgrading from an earlier version of GitLab to 13.0, existing snippets -without a supported filename will be renamed to a compatible format. For -example, if the snippet's filename is `http://a-weird-filename.me` it will -be changed to `http-a-weird-filename-me` to be included in the snippet's -repository. As snippets are stored by ID, changing their filenames will not break +without a supported filename are renamed to a compatible format. For +example, if the snippet's filename is `http://a-weird-filename.me` it is +changed to `http-a-weird-filename-me` to be included in the snippet's +repository. As snippets are stored by ID, changing their filenames breaks direct or embedded links to the snippet. ### Multiple files by Snippet @@ -105,8 +105,8 @@ to a certain context. For example: - A snippet with a `docker-compose.yml` file and its associated `.env` file. - A `gulpfile.js` file coupled with a `package.json` file, which together can be used to bootstrap a project and manage its dependencies. -Snippets support between 1 and 10 files. They can be managed via Git (since they're [versioned](#versioned-snippets) -by a Git repository), through the [Snippets API](../api/snippets.md), or within the GitLab UI. +Snippets support between 1 and 10 files. They can be managed via Git (because they're [versioned](#versioned-snippets) +by a Git repository), through the [Snippets API](../api/snippets.md), or in the GitLab UI. ![Multi-file Snippet](img/gitlab_snippet_v13_5.png) @@ -122,7 +122,7 @@ To delete a file from your snippet through the GitLab UI: 1. Go to your snippet in the GitLab UI. 1. Click **Edit** in the top right. -1. Select **Delete file** alongside the file name of each file +1. Select **Delete file** alongside the filename of each file you wish to delete. 1. Click **Save changes**. @@ -139,7 +139,7 @@ master branch. ### Reduce snippets repository size -Since versioned Snippets are considered as part of the [namespace storage size](../user/admin_area/settings/account_and_limit_settings.md), +Because versioned Snippets are considered as part of the [namespace storage size](../user/admin_area/settings/account_and_limit_settings.md), it's recommended to keep snippets' repositories as compact as possible. For more information about tools to compact repositories, @@ -151,7 +151,7 @@ see the documentation on [reducing repository size](../user/project/repository/r - Creating or deleting branches is not supported. Only a default *master* branch is used. - Git tags are not supported in snippet repositories. - Snippets' repositories are limited to 10 files. Attempting to push more -than 10 files will result in an error. +than 10 files results in an error. - Revisions are not *yet* visible to the user on the GitLab UI, but it's planned to be added in future iterations. See the [revisions tab issue](https://gitlab.com/gitlab-org/gitlab/-/issues/39271) for updates. @@ -187,9 +187,9 @@ facilitating the collaboration among users. You can download the raw content of a snippet. -By default snippets will be downloaded with Linux-style line endings (`LF`). If +By default snippets are downloaded with Linux-style line endings (`LF`). If you want to preserve the original line endings you need to add a parameter `line_ending=raw` -(e.g., `https://gitlab.com/snippets/SNIPPET_ID/raw?line_ending=raw`). In case a +(For example: `https://gitlab.com/snippets/SNIPPET_ID/raw?line_ending=raw`). In case a snippet was created using the GitLab web interface the original line ending is Windows-like (`CRLF`). ## Embedded snippets @@ -207,7 +207,7 @@ To embed a snippet, first make sure that: - In **Project > Settings > Permissions**, the snippets permissions are set to **Everyone with access** -Once the above conditions are met, the "Embed" section will appear in your +After the above conditions are met, the "Embed" section appears in your snippet where you can simply click on the "Copy" button. This copies a one-line script that you can add to any website or blog post. @@ -221,6 +221,6 @@ Here's how an embedded snippet looks like: <script src="https://gitlab.com/gitlab-org/gitlab-foss/snippets/1717978.js"></script> -Embedded snippets are displayed with a header that shows the file name if it's defined, +Embedded snippets are displayed with a header that shows the filename if it's defined, the snippet size, a link to GitLab, and the actual snippet content. Actions in the header allow users to see the snippet in raw format and download it. diff --git a/doc/user/todos.md b/doc/user/todos.md index 7d5a66a1632..27a849719c5 100644 --- a/doc/user/todos.md +++ b/doc/user/todos.md @@ -72,7 +72,7 @@ prevent data loss, in the case where a user's access is accidentally revoked. > [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/merge_requests/7926) in GitLab 9.0. -If you're mentioned at the start of a line, the to-do item you receive is +If you're mentioned at the start of a line, the to-do item you receive is listed as *directly addressed*. For example, in the following comment: ```markdown diff --git a/doc/user/usage_quotas.md b/doc/user/usage_quotas.md index 5f637c8d5cb..8662efc03a7 100644 --- a/doc/user/usage_quotas.md +++ b/doc/user/usage_quotas.md @@ -22,7 +22,6 @@ To help manage storage, a namespace's owner can view: - Total storage used in the namespace - Total storage used per project -- Breakdown of storage use per project, by storage type. To view storage usage, from the namespace's page go to **Settings > Usage Quotas** and select the **Storage** tab. The Usage Quotas statistics are updated every 90 minutes. |