Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot
2023-03-29 15:10:35 +00:00
parent 1a8b381312
commit 6407b5a4c1
53 changed files with 1116 additions and 503 deletions

View File

@ -1 +1 @@
82da6c9eb6897bf3bbb7a791ba13a184f5679d24
d41dacd832cc71860f8e069647b539880263392c

View File

@ -14,6 +14,7 @@ import semverPrerelease from 'semver/functions/prerelease';
import TimeAgoTooltip from '~/vue_shared/components/time_ago_tooltip.vue';
import timeagoMixin from '~/vue_shared/mixins/timeago';
import { helpPagePath } from '~/helpers/help_page_helper';
import { getIdFromGraphQLId } from '~/graphql_shared/utils';
import { AGENT_STATUSES, I18N_AGENT_TABLE } from '../constants';
import { getAgentConfigPath } from '../clusters_util';
import DeleteAgentButton from './delete_agent_button.vue';
@ -83,6 +84,11 @@ export default {
label: this.$options.i18n.versionLabel,
tdClass,
},
{
key: 'agentID',
label: this.$options.i18n.agentIdLabel,
tdClass,
},
{
key: 'configuration',
label: this.$options.i18n.configurationLabel,
@ -119,6 +125,9 @@ export default {
getPopoverTestId(item) {
return `popover-${item.name}`;
},
getAgentId(item) {
return getIdFromGraphQLId(item.id);
},
getAgentConfigPath,
getAgentVersions(agent) {
const agentConnections = agent.connections?.nodes || [];
@ -276,6 +285,12 @@ export default {
</gl-popover>
</template>
<template #cell(agentID)="{ item }">
<span data-testid="cluster-agent-id">
{{ getAgentId(item) }}
</span>
</template>
<template #cell(configuration)="{ item }">
<span data-testid="cluster-agent-configuration-link">
<gl-link v-if="item.configFolder" :href="item.configFolder.webPath">

View File

@ -1,5 +1,5 @@
<script>
import { GlButtonGroup, GlButton, GlTooltipDirective } from '@gitlab/ui';
import { GlButtonGroup, GlButton, GlTooltipDirective, GlFormCheckbox } from '@gitlab/ui';
import SafeHtml from '~/vue_shared/directives/safe_html';
import CommitPipelineStatus from '~/projects/tree/components/commit_pipeline_status_component.vue';
@ -30,6 +30,7 @@ export default {
CommitPipelineStatus,
GlButtonGroup,
GlButton,
GlFormCheckbox,
},
directives: {
GlTooltip: GlTooltipDirective,
@ -117,12 +118,11 @@ export default {
</div>
<div>
<div class="d-flex float-left align-items-center align-self-start">
<input
<gl-form-checkbox
v-if="isSelectable"
class="gl-mr-3"
type="checkbox"
:checked="checked"
@change="$emit('handleCheckboxChange', $event.target.checked)"
class="gl-mt-3"
@change="$emit('handleCheckboxChange', !checked)"
/>
<user-avatar-link
:link-href="authorUrl"

View File

@ -50,6 +50,7 @@ export default {
i18n: {
...DIFF_FILE_HEADER,
compareButtonLabel: __('Compare submodule commit revisions'),
fileModeTooltip: __('File permissions'),
},
props: {
discussionPath: {
@ -342,7 +343,13 @@ export default {
data-track-property="diff_copy_file"
/>
<small v-if="isModeChanged" ref="fileMode" class="mr-1">
<small
v-if="isModeChanged"
ref="fileMode"
v-gl-tooltip.hover
class="mr-1"
:title="$options.i18n.fileModeTooltip"
>
{{ diffFile.a_mode }} {{ diffFile.b_mode }}
</small>

View File

@ -2,7 +2,6 @@
stage: Plan
group: Knowledge
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
description: 'Learn how to administer GitLab Pages.'
---
# GitLab Pages administration **(FREE SELF)**
@ -818,7 +817,7 @@ From [GitLab 13.3 to GitLab 13.12](#domain-source-configuration-before-140) GitL
Starting from [GitLab 14.0](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5993) GitLab Pages uses API
by default and fails to start if it can't connect to it.
For common issues, see the [troubleshooting section](#failed-to-connect-to-the-internal-gitlab-api).
For common issues, see [troubleshooting](troubleshooting.md#failed-to-connect-to-the-internal-gitlab-api).
For more details see this [blog post](https://about.gitlab.com/blog/2020/08/03/how-gitlab-pages-uses-the-gitlab-api-to-serve-content/).
@ -895,7 +894,7 @@ configuration is tried to be resolved automatically before reporting an error.
> [Introduced](https://gitlab.com/gitlab-org/omnibus-gitlab/-/issues/5577) in GitLab 13.6.
[Read more about using object storage with GitLab](../object_storage.md).
For more information, see [object storage](../object_storage.md).
### Object storage settings
@ -1100,8 +1099,8 @@ In GitLab 14.0 a number of breaking changes were introduced which may require so
The steps below describe the best way to migrate without causing any downtime for your GitLab instance.
A GitLab instance running on a single server typically upgrades to 14.0 smoothly, and there should be minimal issues after the upgrade is complete.
Regardless, we recommend everyone follow the migration steps to ensure a successful upgrade.
If at any point you run into issues, consult the [troubleshooting section](#troubleshooting).
Regardless, you should follow the migration steps to ensure a successful upgrade.
For common issues, see [troubleshooting](troubleshooting.md).
If your current GitLab version is lower than 13.12, then you must first update to 13.12.
Updating directly to 14.0 is [not supported](../../update/index.md#upgrade-paths)
@ -1184,313 +1183,3 @@ Rate limits are enforced using the following:
```
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
<!-- ## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
one might have when setting this up, or when something is changed, or on upgrading, it's
important to describe those, too. Think of things that may go wrong and include them in
the section below.
This is important to minimize requests for support, and to avoid doc comments with
questions that you know someone might ask.
Each scenario can be a third-level heading, for example `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
## Troubleshooting
### How to see GitLab Pages logs
You can see Pages daemon logs by running:
```shell
sudo gitlab-ctl tail gitlab-pages
```
You can also find the log file in `/var/log/gitlab/gitlab-pages/current`.
### `unsupported protocol scheme \"\""`
If you see the following error:
```plaintext
{"error":"failed to connect to internal Pages API: Get \"/api/v4/internal/pages/status\": unsupported protocol scheme \"\"","level":"warning","msg":"attempted to connect to the API","time":"2021-06-23T20:03:30Z"}
```
It means you didn't set the HTTP(S) protocol scheme in the Pages server settings.
To fix it:
1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
gitlab_pages['gitlab_server'] = "https://<your_pages_domain_name>"
gitlab_pages['internal_gitlab_server'] = "https://<your_pages_domain_name>"
```
1. Reconfigure GitLab:
```shell
sudo gitlab-ctl reconfigure
```
### 502 error when connecting to GitLab Pages proxy when server does not listen over IPv6
In some cases, NGINX might default to using IPv6 to connect to the GitLab Pages
service even when the server does not listen over IPv6. You can identify when
this is happening if you see something similar to the log entry below in the
`gitlab_pages_error.log`:
```plaintext
2020/02/24 16:32:05 [error] 112654#0: *4982804 connect() failed (111: Connection refused) while connecting to upstream, client: 123.123.123.123, server: ~^(?<group>.*)\.pages\.example\.com$, request: "GET /-/group/project/-/jobs/1234/artifacts/artifact.txt HTTP/1.1", upstream: "http://[::1]:8090//-/group/project/-/jobs/1234/artifacts/artifact.txt", host: "group.example.com"
```
To resolve this, set an explicit IP and port for the GitLab Pages `listen_proxy` setting
to define the explicit address that the GitLab Pages daemon should listen on:
```ruby
gitlab_pages['listen_proxy'] = '127.0.0.1:8090'
```
### Intermittent 502 errors or after a few days
If you run Pages on a system that uses `systemd` and
[`tmpfiles.d`](https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html),
you may encounter intermittent 502 errors trying to serve Pages with an error similar to:
```plaintext
dial tcp: lookup gitlab.example.com on [::1]:53: dial udp [::1]:53: connect: no route to host"
```
GitLab Pages creates a [bind mount](https://man7.org/linux/man-pages/man8/mount.8.html)
inside `/tmp/gitlab-pages-*` that includes files like `/etc/hosts`.
However, `systemd` may clean the `/tmp/` directory on a regular basis so the DNS
configuration may be lost.
To stop `systemd` from cleaning the Pages related content:
1. Tell `tmpfiles.d` to not remove the Pages `/tmp` directory:
```shell
echo 'x /tmp/gitlab-pages-*' >> /etc/tmpfiles.d/gitlab-pages-jail.conf
```
1. Restart GitLab Pages:
```shell
sudo gitlab-ctl restart gitlab-pages
```
### Unable to access GitLab Pages
If you can't access your GitLab Pages (such as receiving `502 Bad Gateway` errors, or a login loop)
and in your Pages log shows this error:
```plaintext
"error":"retrieval context done: context deadline exceeded","host":"root.docs-cit.otenet.gr","level":"error","msg":"could not fetch domain information from a source"
```
1. Add the following to `/etc/gitlab/gitlab.rb`:
```ruby
gitlab_pages['internal_gitlab_server'] = 'http://localhost:8080'
```
1. Restart GitLab Pages:
```shell
sudo gitlab-ctl restart gitlab-pages
```
### Failed to connect to the internal GitLab API
If you see the following error:
```plaintext
ERRO[0010] Failed to connect to the internal GitLab API after 0.50s error="failed to connect to internal Pages API: HTTP status: 401"
```
If you are [Running GitLab Pages on a separate server](#running-gitlab-pages-on-a-separate-server)
you must copy the `/etc/gitlab/gitlab-secrets.json` file
from the **GitLab server** to the **Pages server** after upgrading to GitLab 13.3,
as described in that section.
Other reasons may include network connectivity issues between your
**GitLab server** and your **Pages server** such as firewall configurations or closed ports.
For example, if there is a connection timeout:
```plaintext
error="failed to connect to internal Pages API: Get \"https://gitlab.example.com:3000/api/v4/internal/pages/status\": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)"
```
### Pages cannot communicate with an instance of the GitLab API
If you use the default value for `domain_config_source=auto` and run multiple instances of GitLab
Pages, you may see intermittent 502 error responses while serving Pages content. You may also see
the following warning in the Pages logs:
```plaintext
WARN[0010] Pages cannot communicate with an instance of the GitLab API. Please sync your gitlab-secrets.json file https://gitlab.com/gitlab-org/gitlab-pages/-/issues/535#workaround. error="pages endpoint unauthorized"
```
This can happen if your `gitlab-secrets.json` file is out of date between GitLab Rails and GitLab
Pages. Follow steps 8-10 of [Running GitLab Pages on a separate server](#running-gitlab-pages-on-a-separate-server),
in all of your GitLab Pages instances.
### Intermittent 502 errors when using an AWS Network Load Balancer and GitLab Pages
Connections will time out when using a Network Load Balancer with client IP preservation enabled and [the request is looped back to the source server](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-troubleshooting.html#loopback-timeout).
This can happen to GitLab instances with multiple servers
running both the core GitLab application and GitLab Pages. This can also happen when a single
container is running both the core GitLab application and GitLab Pages.
AWS [recommends using an IP target type](https://aws.amazon.com/premiumsupport/knowledge-center/target-connection-fails-load-balancer/)
to resolve this issue.
Turning off [client IP preservation](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html#client-ip-preservation)
may resolve this issue when the core GitLab application and GitLab Pages run on the same host or
container.
### 500 error with `securecookie: failed to generate random iv` and `Failed to save the session`
This problem most likely results from an [out-dated operating system](../package_information/supported_os.md#os-versions-that-are-no-longer-supported).
The [Pages daemon uses the `securecookie` library](https://gitlab.com/search?group_id=9970&project_id=734943&repository_ref=master&scope=blobs&search=securecookie&snippets=false) to get random strings via [`crypto/rand` in Go](https://pkg.go.dev/crypto/rand#pkg-variables).
This requires the `getrandom` system call or `/dev/urandom` to be available on the host OS.
Upgrading to an [officially supported operating system](https://about.gitlab.com/install/) is recommended.
### The requested scope is invalid, malformed, or unknown
This problem comes from the permissions of the GitLab Pages OAuth application. To fix it:
1. On the top bar, select **Main menu > Admin**.
1. On the left sidebar, select **Applications > GitLab Pages**.
1. Edit the application.
1. Under **Scopes**, ensure that the `api` scope is selected.
1. Save your changes.
When running a [separate Pages server](#running-gitlab-pages-on-a-separate-server),
this setting needs to be configured on the main GitLab server.
### Workaround in case no wildcard DNS entry can be set
If the wildcard DNS [prerequisite](#prerequisites) can't be met, you can still use GitLab Pages in a limited fashion:
1. [Move](../../user/project/settings/index.md#transfer-a-project-to-another-namespace)
all projects you need to use Pages with into a single group namespace, for example `pages`.
1. Configure a [DNS entry](#dns-configuration) without the `*.`-wildcard, for example `pages.example.io`.
1. Configure `pages_external_url http://example.io/` in your `gitlab.rb` file.
Omit the group namespace here, because it automatically is prepended by GitLab.
### Pages daemon fails with permission denied errors
If `/tmp` is mounted with `noexec`, the Pages daemon fails to start with an error like:
```plaintext
{"error":"fork/exec /gitlab-pages: permission denied","level":"fatal","msg":"could not create pages daemon","time":"2021-02-02T21:54:34Z"}
```
In this case, change `TMPDIR` to a location that is not mounted with `noexec`. Add the following to
`/etc/gitlab/gitlab.rb`:
```ruby
gitlab_pages['env'] = {'TMPDIR' => '<new_tmp_path>'}
```
Once added, reconfigure with `sudo gitlab-ctl reconfigure` and restart GitLab with
`sudo gitlab-ctl restart`.
### `The redirect URI included is not valid.` when using Pages Access Control
You may see this error if `pages_external_url` was updated at some point of time. Verify the following:
1. The **Callback URL**/Redirect URI in the GitLab Pages [System OAuth application](../../integration/oauth_provider.md#create-an-instance-wide-application)
is using the protocol (HTTP or HTTPS) that `pages_external_url` is configured to use.
1. The domain and path components of `Redirect URI` are valid: they should look like `projects.<pages_external_url>/auth`.
### 500 error `cannot serve from disk`
If you get a 500 response from Pages and encounter an error similar to:
```plaintext
ERRO[0145] cannot serve from disk error="gitlab: disk access is disabled via enable-disk=false" project_id=27 source_path="file:///shared/pages/@hashed/67/06/670671cd97404156226e507973f2ab8330d3022ca96e0c93bdbdb320c41adcaf/pages_deployments/14/artifacts.zip" source_type=zip
```
It means that GitLab Rails is telling GitLab Pages to serve content from a location on disk,
however, GitLab Pages was configured to disable disk access.
To enable disk access:
1. Enable disk access for GitLab Pages in `/etc/gitlab/gitlab.rb`:
```ruby
gitlab_pages['enable_disk'] = true
```
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
### `httprange: new resource 403`
If you see an error similar to:
```plaintext
{"error":"httprange: new resource 403: \"403 Forbidden\"","host":"root.pages.example.com","level":"error","msg":"vfs.Root","path":"/pages1/","time":"2021-06-10T08:45:19Z"}
```
And you run pages on the separate server syncing files via NFS, it may mean that
the shared pages directory is mounted on a different path on the main GitLab server and the
GitLab Pages server.
In that case, it's highly recommended you to configure
[object storage and migrate any existing pages data to it](#using-object-storage).
Alternatively, you can mount the GitLab Pages shared directory to the same path on
both servers.
### GitLab Pages doesn't work after upgrading to GitLab 14.0 or above
GitLab 14.0 introduces a number of changes to GitLab Pages which may require manual intervention.
1. Firstly [follow the migration guide](#prepare-gitlab-pages-for-140).
1. Try to upgrade to GitLab 14.3 or above. Some of the issues were fixed in GitLab 14.1, 14.2 and 14.3.
1. If it doesn't work, see [GitLab Pages logs](#how-to-see-gitlab-pages-logs), and if you see any errors there then search them on this page.
WARNING:
In GitLab 14.0-14.2 you can temporarily enable legacy storage and configuration mechanisms.
To do that:
1. Describe the issue you're seeing in the [migration feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/331699).
1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
gitlab_pages['use_legacy_storage'] = true
```
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
### GitLab Pages deploy job fails with error "is not a recognized provider"
If the **pages** job succeeds but the **deploy** job gives the error "is not a recognized provider":
![Pages Deploy Failure](img/pages_deploy_failure_v14_8.png)
The error message `is not a recognized provider` could be coming from the `fog` gem that GitLab uses to connect to cloud providers for object storage.
To fix that:
1. Check your `gitlab.rb` file. If you have `gitlab_rails['pages_object_store_enabled']` enabled, but no bucket details have been configured, either:
- Configure object storage for your Pages deployments, following the [S3-compatible connection settings](#s3-compatible-connection-settings) guide.
- Store your deployments locally, by commenting out that line.
1. Save the changes you made to your `gitlab.rb` file, then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
### 404 error `The page you're looking for could not be found`
If you get a `404 Page Not Found` response from GitLab Pages:
1. Check `.gitlab-ci.yml` contains the job `pages:`.
1. Check the current project's pipeline to confirm the job `pages:deploy` is being run.
Without the `pages:deploy` job, the updates to your GitLab Pages site are never published.

View File

@ -0,0 +1,304 @@
---
stage: Plan
group: Knowledge
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Troubleshooting GitLab Pages administration **(FREE SELF)**
This page contains a list of issues you might encounter when administering GitLab Pages.
## How to see GitLab Pages logs
You can see Pages daemon logs by running:
```shell
sudo gitlab-ctl tail gitlab-pages
```
You can also find the log file in `/var/log/gitlab/gitlab-pages/current`.
## `unsupported protocol scheme \"\""`
If you see the following error:
```plaintext
{"error":"failed to connect to internal Pages API: Get \"/api/v4/internal/pages/status\": unsupported protocol scheme \"\"","level":"warning","msg":"attempted to connect to the API","time":"2021-06-23T20:03:30Z"}
```
It means you didn't set the HTTP(S) protocol scheme in the Pages server settings.
To fix it:
1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
gitlab_pages['gitlab_server'] = "https://<your_pages_domain_name>"
gitlab_pages['internal_gitlab_server'] = "https://<your_pages_domain_name>"
```
1. Reconfigure GitLab:
```shell
sudo gitlab-ctl reconfigure
```
## 502 error when connecting to GitLab Pages proxy when server does not listen over IPv6
In some cases, NGINX might default to using IPv6 to connect to the GitLab Pages
service even when the server does not listen over IPv6. You can identify when
this is happening if you see something similar to the log entry below in the
`gitlab_pages_error.log`:
```plaintext
2020/02/24 16:32:05 [error] 112654#0: *4982804 connect() failed (111: Connection refused) while connecting to upstream, client: 123.123.123.123, server: ~^(?<group>.*)\.pages\.example\.com$, request: "GET /-/group/project/-/jobs/1234/artifacts/artifact.txt HTTP/1.1", upstream: "http://[::1]:8090//-/group/project/-/jobs/1234/artifacts/artifact.txt", host: "group.example.com"
```
To resolve this, set an explicit IP and port for the GitLab Pages `listen_proxy` setting
to define the explicit address that the GitLab Pages daemon should listen on:
```ruby
gitlab_pages['listen_proxy'] = '127.0.0.1:8090'
```
## Intermittent 502 errors or after a few days
If you run Pages on a system that uses `systemd` and
[`tmpfiles.d`](https://www.freedesktop.org/software/systemd/man/tmpfiles.d.html),
you may encounter intermittent 502 errors trying to serve Pages with an error similar to:
```plaintext
dial tcp: lookup gitlab.example.com on [::1]:53: dial udp [::1]:53: connect: no route to host"
```
GitLab Pages creates a [bind mount](https://man7.org/linux/man-pages/man8/mount.8.html)
inside `/tmp/gitlab-pages-*` that includes files like `/etc/hosts`.
However, `systemd` may clean the `/tmp/` directory on a regular basis so the DNS
configuration may be lost.
To stop `systemd` from cleaning the Pages related content:
1. Tell `tmpfiles.d` to not remove the Pages `/tmp` directory:
```shell
echo 'x /tmp/gitlab-pages-*' >> /etc/tmpfiles.d/gitlab-pages-jail.conf
```
1. Restart GitLab Pages:
```shell
sudo gitlab-ctl restart gitlab-pages
```
## Unable to access GitLab Pages
If you can't access your GitLab Pages (such as receiving `502 Bad Gateway` errors, or a login loop)
and in your Pages log shows this error:
```plaintext
"error":"retrieval context done: context deadline exceeded","host":"root.docs-cit.otenet.gr","level":"error","msg":"could not fetch domain information from a source"
```
1. Add the following to `/etc/gitlab/gitlab.rb`:
```ruby
gitlab_pages['internal_gitlab_server'] = 'http://localhost:8080'
```
1. Restart GitLab Pages:
```shell
sudo gitlab-ctl restart gitlab-pages
```
## Failed to connect to the internal GitLab API
If you see the following error:
```plaintext
ERRO[0010] Failed to connect to the internal GitLab API after 0.50s error="failed to connect to internal Pages API: HTTP status: 401"
```
If you are [Running GitLab Pages on a separate server](index.md#running-gitlab-pages-on-a-separate-server)
you must copy the `/etc/gitlab/gitlab-secrets.json` file
from the **GitLab server** to the **Pages server** after upgrading to GitLab 13.3,
as described in that section.
Other reasons may include network connectivity issues between your
**GitLab server** and your **Pages server** such as firewall configurations or closed ports.
For example, if there is a connection timeout:
```plaintext
error="failed to connect to internal Pages API: Get \"https://gitlab.example.com:3000/api/v4/internal/pages/status\": net/http: request canceled while waiting for connection (Client.Timeout exceeded while awaiting headers)"
```
## Pages cannot communicate with an instance of the GitLab API
If you use the default value for `domain_config_source=auto` and run multiple instances of GitLab
Pages, you may see intermittent 502 error responses while serving Pages content. You may also see
the following warning in the Pages logs:
```plaintext
WARN[0010] Pages cannot communicate with an instance of the GitLab API. Please sync your gitlab-secrets.json file https://gitlab.com/gitlab-org/gitlab-pages/-/issues/535#workaround. error="pages endpoint unauthorized"
```
This can happen if your `gitlab-secrets.json` file is out of date between GitLab Rails and GitLab
Pages. Follow steps 8-10 of [Running GitLab Pages on a separate server](index.md#running-gitlab-pages-on-a-separate-server),
in all of your GitLab Pages instances.
## Intermittent 502 errors when using an AWS Network Load Balancer and GitLab Pages
Connections will time out when using a Network Load Balancer with client IP preservation enabled and [the request is looped back to the source server](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-troubleshooting.html#loopback-timeout).
This can happen to GitLab instances with multiple servers
running both the core GitLab application and GitLab Pages. This can also happen when a single
container is running both the core GitLab application and GitLab Pages.
AWS [recommends using an IP target type](https://aws.amazon.com/premiumsupport/knowledge-center/target-connection-fails-load-balancer/)
to resolve this issue.
Turning off [client IP preservation](https://docs.aws.amazon.com/elasticloadbalancing/latest/network/load-balancer-target-groups.html#client-ip-preservation)
may resolve this issue when the core GitLab application and GitLab Pages run on the same host or
container.
## 500 error with `securecookie: failed to generate random iv` and `Failed to save the session`
This problem most likely results from an [out-dated operating system](../package_information/supported_os.md#os-versions-that-are-no-longer-supported).
The [Pages daemon uses the `securecookie` library](https://gitlab.com/search?group_id=9970&project_id=734943&repository_ref=master&scope=blobs&search=securecookie&snippets=false) to get random strings via [`crypto/rand` in Go](https://pkg.go.dev/crypto/rand#pkg-variables).
This requires the `getrandom` system call or `/dev/urandom` to be available on the host OS.
Upgrading to an [officially supported operating system](https://about.gitlab.com/install/) is recommended.
## The requested scope is invalid, malformed, or unknown
This problem comes from the permissions of the GitLab Pages OAuth application. To fix it:
1. On the top bar, select **Main menu > Admin**.
1. On the left sidebar, select **Applications > GitLab Pages**.
1. Edit the application.
1. Under **Scopes**, ensure that the `api` scope is selected.
1. Save your changes.
When running a [separate Pages server](index.md#running-gitlab-pages-on-a-separate-server),
this setting needs to be configured on the main GitLab server.
## Workaround in case no wildcard DNS entry can be set
If the wildcard DNS [prerequisite](index.md#prerequisites) can't be met, you can still use GitLab Pages in a limited fashion:
1. [Move](../../user/project/settings/index.md#transfer-a-project-to-another-namespace)
all projects you need to use Pages with into a single group namespace, for example `pages`.
1. Configure a [DNS entry](index.md#dns-configuration) without the `*.`-wildcard, for example `pages.example.io`.
1. Configure `pages_external_url http://example.io/` in your `gitlab.rb` file.
Omit the group namespace here, because it automatically is prepended by GitLab.
## Pages daemon fails with permission denied errors
If `/tmp` is mounted with `noexec`, the Pages daemon fails to start with an error like:
```plaintext
{"error":"fork/exec /gitlab-pages: permission denied","level":"fatal","msg":"could not create pages daemon","time":"2021-02-02T21:54:34Z"}
```
In this case, change `TMPDIR` to a location that is not mounted with `noexec`. Add the following to
`/etc/gitlab/gitlab.rb`:
```ruby
gitlab_pages['env'] = {'TMPDIR' => '<new_tmp_path>'}
```
Once added, reconfigure with `sudo gitlab-ctl reconfigure` and restart GitLab with
`sudo gitlab-ctl restart`.
## `The redirect URI included is not valid.` when using Pages Access Control
You may see this error if `pages_external_url` was updated at some point of time. Verify the following:
1. The **Callback URL**/Redirect URI in the GitLab Pages [System OAuth application](../../integration/oauth_provider.md#create-an-instance-wide-application)
is using the protocol (HTTP or HTTPS) that `pages_external_url` is configured to use.
1. The domain and path components of `Redirect URI` are valid: they should look like `projects.<pages_external_url>/auth`.
## 500 error `cannot serve from disk`
If you get a 500 response from Pages and encounter an error similar to:
```plaintext
ERRO[0145] cannot serve from disk error="gitlab: disk access is disabled via enable-disk=false" project_id=27 source_path="file:///shared/pages/@hashed/67/06/670671cd97404156226e507973f2ab8330d3022ca96e0c93bdbdb320c41adcaf/pages_deployments/14/artifacts.zip" source_type=zip
```
It means that GitLab Rails is telling GitLab Pages to serve content from a location on disk,
however, GitLab Pages was configured to disable disk access.
To enable disk access:
1. Enable disk access for GitLab Pages in `/etc/gitlab/gitlab.rb`:
```ruby
gitlab_pages['enable_disk'] = true
```
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
## `httprange: new resource 403`
If you see an error similar to:
```plaintext
{"error":"httprange: new resource 403: \"403 Forbidden\"","host":"root.pages.example.com","level":"error","msg":"vfs.Root","path":"/pages1/","time":"2021-06-10T08:45:19Z"}
```
And you run pages on the separate server syncing files via NFS, it may mean that
the shared pages directory is mounted on a different path on the main GitLab server and the
GitLab Pages server.
In that case, it's highly recommended you to configure
[object storage and migrate any existing pages data to it](index.md#using-object-storage).
Alternatively, you can mount the GitLab Pages shared directory to the same path on
both servers.
## GitLab Pages doesn't work after upgrading to GitLab 14.0 or above
GitLab 14.0 introduces a number of changes to GitLab Pages which may require manual intervention.
1. Firstly [follow the migration guide](index.md#prepare-gitlab-pages-for-140).
1. Try to upgrade to GitLab 14.3 or above. Some of the issues were fixed in GitLab 14.1, 14.2 and 14.3.
1. If it doesn't work, see [GitLab Pages logs](#how-to-see-gitlab-pages-logs), and if you see any errors there then search them on this page.
WARNING:
In GitLab 14.0-14.2 you can temporarily enable legacy storage and configuration mechanisms.
To do that:
1. Describe the issue you're seeing in the [migration feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/331699).
1. Edit `/etc/gitlab/gitlab.rb`:
```ruby
gitlab_pages['use_legacy_storage'] = true
```
1. [Reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
## GitLab Pages deploy job fails with error "is not a recognized provider"
If the **pages** job succeeds but the **deploy** job gives the error "is not a recognized provider":
![Pages Deploy Failure](img/pages_deploy_failure_v14_8.png)
The error message `is not a recognized provider` could be coming from the `fog` gem that GitLab uses to connect to cloud providers for object storage.
To fix that:
1. Check your `gitlab.rb` file. If you have `gitlab_rails['pages_object_store_enabled']` enabled, but no bucket details have been configured, either:
- Configure object storage for your Pages deployments, following the [S3-compatible connection settings](index.md#s3-compatible-connection-settings) guide.
- Store your deployments locally, by commenting out that line.
1. Save the changes you made to your `gitlab.rb` file, then [reconfigure GitLab](../restart_gitlab.md#omnibus-gitlab-reconfigure).
## 404 error `The page you're looking for could not be found`
If you get a `404 Page Not Found` response from GitLab Pages:
1. Check `.gitlab-ci.yml` contains the job `pages:`.
1. Check the current project's pipeline to confirm the job `pages:deploy` is being run.
Without the `pages:deploy` job, the updates to your GitLab Pages site are never published.

View File

@ -5341,6 +5341,25 @@ Input type: `SecurityFindingCreateIssueInput`
| <a id="mutationsecurityfindingcreateissueerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationsecurityfindingcreateissueissue"></a>`issue` | [`Issue`](#issue) | Issue created after mutation. |
### `Mutation.securityFindingCreateMergeRequest`
Input type: `SecurityFindingCreateMergeRequestInput`
#### Arguments
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationsecurityfindingcreatemergerequestclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationsecurityfindingcreatemergerequestuuid"></a>`uuid` | [`String!`](#string) | UUID of the security finding to be used to create a merge request. |
#### Fields
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="mutationsecurityfindingcreatemergerequestclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. |
| <a id="mutationsecurityfindingcreatemergerequesterrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. |
| <a id="mutationsecurityfindingcreatemergerequestmergerequest"></a>`mergeRequest` | [`MergeRequest`](#mergerequest) | Merge Request created after mutation. |
### `Mutation.securityFindingDismiss`
Input type: `SecurityFindingDismissInput`

View File

@ -164,12 +164,17 @@ self-managed instances.
A number of technical issues need to be resolved to implement Cells (in no particular order). This section will be expanded.
1. How are users of an organization routed to the correct Cell?
1. How do users authenticate?
1. How are Cells provisioned? - [Design discussion](https://gitlab.com/gitlab-org/gitlab/-/issues/396641)
1. What is a Cells topology? - [Design discussion](https://gitlab.com/gitlab-org/gitlab/-/issues/396641)
1. How are users of an organization routed to the correct Cell? -
1. How do users authenticate with Cells and Organizations? - [Design discussion](https://gitlab.com/gitlab-org/gitlab/-/issues/395736)
1. How are Cells rebalanced?
1. How are Cells provisioned?
1. How can Cells implement disaster recovery capabilities?
## Decision log
- 2022-03-15: Google Cloud as the cloud service. [Reference](https://gitlab.com/gitlab-org/gitlab/-/issues/396641#note_1314932272)
## Cross-section impact
Cells is a fundamental architecture change that impacts other sections and stages. This section summarizes and links to other groups that may be impacted and highlights potential conflicts that need to be resolved. The Tenant Scale group is not responsible for achieving the goals of other groups but we want to ensure that dependencies are resolved.

View File

@ -4,10 +4,15 @@ group: Pipeline Execution
info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/product/ux/technical-writing/#assignments
---
# Accessibility testing **(FREE)**
<!--- start_remove The following content will be removed on remove_date: '2024-05-22' -->
# Accessibility testing (deprecated) **(FREE)**
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/25144) in GitLab 12.8.
WARNING:
This feature was deprecated in GitLab 15.9
and is planned for removal in 17.0. This change is a breaking change.
If your application offers a web interface, you can use
[GitLab CI/CD](../index.md) to determine the accessibility
impact of pending code changes.
@ -74,3 +79,5 @@ The job definition provided by the template does not support Kubernetes.
You cannot pass configurations into Pa11y via CI configuration.
To change the configuration, edit a copy of the template in your CI file.
<!--- end_remove -->

View File

@ -391,6 +391,87 @@ You can read more about components in Vue.js site, [Component System](https://v2
Check this [page](vuex.md) for more details.
### Vue Router
To add [Vue Router](https://router.vuejs.org/) to a page:
1. Add a catch-all route to the Rails route file using a wildcard named `*vueroute`:
```ruby
# example from ee/config/routes/project.rb
resources :iteration_cadences, path: 'cadences(/*vueroute)', action: :index
```
The above example serves the `index` page from `iteration_cadences` controller to any route
matching the start of the `path`, for example `groupname/projectname/-/cadences/123/456/`.
1. Pass the base route (everything before `*vueroute`) to the frontend to use as the `base` parameter to initialize Vue Router:
```haml
.js-my-app{ data: { base_path: project_iteration_cadences_path(project) } }
```
1. Initialize the router:
```javascript
Vue.use(VueRouter);
export function createRouter(basePath) {
return new VueRouter({
routes: createRoutes(),
mode: 'history',
base: basePath,
});
}
```
1. Add a fallback for unrecognised routes with `path: '*'`. Either:
- Add a redirect to the end of your routes array:
```javascript
const routes = [
{
path: '/',
name: 'list-page',
component: ListPage,
},
{
path: '*',
redirect: '/',
},
];
```
- Add a fallback component to the end of your routes array:
```javascript
const routes = [
{
path: '/',
name: 'list-page',
component: ListPage,
},
{
path: '*',
component: NotFound,
},
];
```
1. Optional. To also allow using the path helper for child routes, add `controller` and `action`
parameters to use the parent controller.
```ruby
resources :iteration_cadences, path: 'cadences(/*vueroute)', action: :index do
resources :iterations, only: [:index, :new, :edit, :show], constraints: { id: /\d+/ }, controller: :iteration_cadences, action: :index
end
```
This means routes like `/cadences/123/iterations/456/edit` can be validated on the backend,
for example to check group or project membership.
It also means we can use the `_path` helper, which means we can load the page in feature specs
without manually building the `*vueroute` part of the path..
### Mixing Vue and jQuery
- Mixing Vue and jQuery is not recommended.

View File

@ -72,22 +72,6 @@ To avoid external dependencies like Gitpod and a Jira Cloud instance, use the [J
1. Go to `http://localhost:9292`.
1. Paste the token and select **Install GitLab.com Jira Cloud app**.
### Troubleshooting
If the app install failed, you might need to delete `jira_connect_installations` from your database.
1. Open the [database console](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md#access-postgresql).
1. Run `TRUNCATE TABLE jira_connect_installations CASCADE;`.
#### Not authorized to access the file
If you use Gitpod and you get an error about Jira not being able to access the descriptor file, you might need to make the GDK port public by following these steps:
1. Open your GitLab workspace in Gitpod.
1. When the GDK is running, select **Ports** in the bottom-right corner.
1. On the left sidebar, select the port the GDK is listening to (typically `3000`).
1. If the port is marked as private, select the lock icon to make it public.
## Test the GitLab OAuth authentication flow
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/81126) in GitLab 14.9 [with a flag](../../administration/feature_flags.md) named `jira_connect_oauth`. Disabled by default.
@ -123,3 +107,21 @@ The following steps describe setting up an environment to test the GitLab OAuth
1. Scroll down and expand the GitLab for Jira App section.
1. Go to [gitpod.io/variables](https://gitpod.io/variables).
1. Paste the Application ID into the **Jira Connect Application ID** field and select **Save changes**.
## Troubleshooting
### App installation fails
If the app installation fails, you might need to delete `jira_connect_installations` from your database.
1. Open the [database console](https://gitlab.com/gitlab-org/gitlab-development-kit/-/blob/main/doc/howto/postgresql.md#access-postgresql).
1. Run `TRUNCATE TABLE jira_connect_installations CASCADE;`.
### Not authorized to access the file
If you use Gitpod and you get an error about Jira not being able to access the descriptor file, you might need to make the GDK port public by following these steps:
1. Open your GitLab workspace in Gitpod.
1. When the GDK is running, select **Ports** in the bottom-right corner.
1. On the left sidebar, select the port the GDK is listening to (typically `3000`).
1. If the port is marked as private, select the lock icon to make it public.

View File

@ -294,7 +294,7 @@ To fix this issue:
### Error `Failed to connect to the internal GitLab API` on a separate GitLab Pages server
See [GitLab Pages troubleshooting](../../administration/pages/index.md#failed-to-connect-to-the-internal-gitlab-api).
See [GitLab Pages administration troubleshooting](../../administration/pages/troubleshooting.md#failed-to-connect-to-the-internal-gitlab-api).
### Error `An error occurred during the signature verification` when running `apt-get update`

View File

@ -11,10 +11,11 @@ info: To determine the technical writer assigned to the Stage/Group associated w
> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/23427) from cycle analytics to value stream analytics in GitLab 12.8.
Value stream analytics provides metrics about each stage of your software development process.
For more information, see [How value stream analytics measures stages](../group/value_stream_analytics/index.md#how-value-stream-analytics-measures-stages).
A **value stream** is the entire work process that delivers value to customers. For example,
the [DevOps lifecycle](https://about.gitlab.com/stages-devops-lifecycle/) is a value stream that starts
with the Manage stage and ends with the Protect stage.
with the Plan stage and ends with the Govern stage.
Use value stream analytics to identify:
@ -113,7 +114,7 @@ To view the lead time for changes for merge requests in your project:
The **Lead Time for Changes** metrics display below the **Filter results** text box.
## View number of successful deployments **(FREE)**
## View number of successful deployments
Prerequisites:
@ -161,60 +162,6 @@ Access permissions for value stream analytics depend on the project type.
| Internal | Any authenticated user can access. |
| Private | Any member Guest and above can access. |
## How value stream analytics measures each stage
Value stream analytics uses start and end events to measure the time that an issue or merge request
spends in each stage.
For example, a stage might start when a user adds a label to an issue, and ends when they add another label.
Items aren't included in the stage time calculation if they have not reached the end event.
| Stage | Measurement method |
|---------|----------------------|
| Issue | The median time between creating an issue and taking action to solve it, by either labeling it or adding it to a milestone. The label is tracked only if it already includes an [issue board list](../project/issue_board.md) that has been created for the label. |
| Plan | The median time between the action you took for the previous stage, and when you push the first commit to the branch. The first branch commit triggers the transition from **Plan** to **Code**, and at least one of the commits in the branch must include the related issue number (such as `#42`). If the issue number is not included in a commit, that data is not included in the measurement time of the stage. |
| Code | The median time between pushing a first commit (previous stage) and creating a merge request. The process is tracked with the [issue closing pattern](../project/issues/managing_issues.md#closing-issues-automatically) in the description of the merge request. For example, if the issue is closed with `Closes #xxx`, `xxx` is the issue number for the merge request. If there is no closing pattern, the start time is set to the create time of the first commit. |
| Test | The time from start to finish for all pipelines. Measures the median time to run the entire pipeline for that project. Related to the time required by GitLab CI/CD to run every job for the commits pushed to that merge request, as defined in the previous stage. |
| Review | The median time taken to review merge requests with a closing issue pattern, from creation to merge. |
| Staging | The median time between merging the merge request (with a closing issue pattern) to the first deployment to a [production environment](../../ci/environments/index.md#deployment-tier-of-environments). Data is not collected without a production environment. |
## Example workflow
This example shows a workflow through all seven stages in one day. In this
example, milestones have been created and CI for testing and setting environments is configured.
- 09:00: Create issue. **Issue** stage starts.
- 11:00: Add issue to a milestone, start work on the issue, and create a branch locally.
**Issue** stage stops and **Plan** stage starts.
- 12:00: Make the first commit.
- 12:30: Make the second commit to the branch that mentions the issue number. **Plan** stage stops and **Code** stage starts.
- 14:00: Push branch and create a merge request that contains the [issue closing pattern](../project/issues/managing_issues.md#closing-issues-automatically). **Code** stage stops and **Test** and **Review** stages start.
- The CI takes 5 minutes to run scripts defined in [`.gitlab-ci.yml`](../../ci/yaml/index.md).
**Test** stage stops.
- Review merge request.
- 19:00: Merge the merge request. **Review** stage stops and **Staging** stage starts.
- 19:30: Deployment to the `production` environment starts and finishes. **Staging** stops.
Value stream analytics records the following times for each stage:
- **Issue**: 09:00 to 11:00: 2 hrs
- **Plan**: 11:00 to 12:30: 1.5 hr
- **Code**: 12:30 to 14:00: 1.5 hrs
- **Test**: 5 minutes
- **Review**: 14:00 to 19:00: 5 hrs
- **Staging**: 19:00 to 19:30: 30 minutes
Keep in mind the following observations related to this example:
- Although this example specifies the issue number in a later commit, the process
still collects analytics data for the issue.
- The time required in the **Test** stage is included in the **Review** process,
as every merge request should be tested.
- This example illustrates only one cycle of multiple stages. The value
stream analytics dashboard shows the calculated median elapsed time for these issues.
- Value stream analytics identifies production environments based on the
[deployment tier of environments](../../ci/environments/index.md#deployment-tier-of-environments).
## Troubleshooting
### 100% CPU utilization by Sidekiq `cronjob:analytics_cycle_analytics`

View File

@ -21,7 +21,7 @@ The Usage Quotas page (**Settings > Usage Quotas > Storage**) displays storage u
This page includes the Container Registry usage, which is only available on GitLab.com.
Measuring usage is only possible on the new version of the GitLab Container Registry backed by a
metadata database. Support for improvements is proposed in epic [5523](https://gitlab.com/groups/gitlab-org/-/epics/5523).
You cannot use the Container Registry in self-managed instances, but epic [5521](https://gitlab.com/groups/gitlab-org/-/epics/5521) proposes to change this behavior.
On self-managed instances, you cannot use the Container Registry with a metadata database. For the plan to change this behavior, see [epic 5521](https://gitlab.com/groups/gitlab-org/-/epics/5521).
Image layers stored in the Container Registry are deduplicated at the root namespace level.

View File

@ -196,38 +196,6 @@ from the GitLab project.
in place. Your domain is periodically reverified, and may be
disabled if the record is removed.
##### Troubleshoot domain verification
To manually verify that you have properly configured the domain verification
`TXT` DNS entry, you can run the following command in your terminal:
```shell
dig _gitlab-pages-verification-code.<YOUR-PAGES-DOMAIN> TXT
```
Expect the output:
```plaintext
;; ANSWER SECTION:
_gitlab-pages-verification-code.<YOUR-PAGES-DOMAIN>. 300 IN TXT "gitlab-pages-verification-code=<YOUR-VERIFICATION-CODE>"
```
In some cases it can help to add the verification code with the same domain name as you are trying to register.
For a root domain:
| From | DNS Record | To |
| ------------------------------------------------- | ---------- | ---------------------- |
| `example.com` | `TXT` | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` |
| `_gitlab-pages-verification-code.example.com` | `TXT` | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` |
For a subdomain:
| From | DNS Record | To |
| ------------------------------------------------- | ---------- | ---------------------- |
| `www.example.com` | `TXT` | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` |
| `_gitlab-pages-verification-code.www.example.com` | `TXT` | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` |
### Add more domain aliases
You can add more than one alias (custom domains and subdomains) to the same project.
@ -351,14 +319,36 @@ To enable this setting:
If you use Cloudflare CDN in front of GitLab Pages, make sure to set the SSL connection setting to
`full` instead of `flexible`. For more details, see the [Cloudflare CDN directions](https://developers.cloudflare.com/ssl/origin-configuration/ssl-modes#h_4e0d1a7c-eb71-4204-9e22-9d3ef9ef7fef).
<!-- ## Troubleshooting
## Troubleshooting
Include any troubleshooting steps that you can foresee. If you know beforehand what issues
one might have when setting this up, or when something is changed, or on upgrading, it's
important to describe those, too. Think of things that may go wrong and include them here.
This is important to minimize requests for support, and to avoid doc comments with
questions that you know someone might ask.
### Domain verification
Each scenario can be a third-level heading, for example, `### Getting error message X`.
If you have none to add when creating a doc, leave this section in place
but commented out to help encourage others to add to it in the future. -->
To manually verify that you have properly configured the domain verification
`TXT` DNS entry, you can run the following command in your terminal:
```shell
dig _gitlab-pages-verification-code.<YOUR-PAGES-DOMAIN> TXT
```
Expect the output:
```plaintext
;; ANSWER SECTION:
_gitlab-pages-verification-code.<YOUR-PAGES-DOMAIN>. 300 IN TXT "gitlab-pages-verification-code=<YOUR-VERIFICATION-CODE>"
```
In some cases it can help to add the verification code with the same domain name as you are trying to register.
For a root domain:
| From | DNS Record | To |
| ------------------------------------------------- | ---------- | ---------------------- |
| `example.com` | `TXT` | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` |
| `_gitlab-pages-verification-code.example.com` | `TXT` | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` |
For a subdomain:
| From | DNS Record | To |
| ------------------------------------------------- | ---------- | ---------------------- |
| `www.example.com` | `TXT` | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` |
| `_gitlab-pages-verification-code.www.example.com` | `TXT` | `gitlab-pages-verification-code=00112233445566778899aabbccddeeff` |

View File

@ -154,7 +154,3 @@ Alternatively, you can pass the parameters from a URL and connect directly to th
```
1. Go to that URL and enter the [token you fetched](#fetch-a-token).
## Related topics
- [Web IDE Beta](../web_ide_beta/index.md)

View File

@ -101,6 +101,18 @@ To create a tag from the GitLab UI:
To prevent users from removing a tag with `git push`, create a [push rule](../push_rules.md).
## Trigger pipelines from a tag
GitLab CI/CD provides a [`CI_COMMIT_TAG` variable](../../../../ci/variables/predefined_variables.md)
to identify tags. Use this variable in job rules and workflow rules to test if the pipeline
was triggered by a tag.
In your `.gitlab-ci.yml` file for the CI/CD pipeline configuration of your project,
you can trigger based on a new tag:
- At the job level, with the [`only` keyword](../../../../ci/yaml/index.md#only--except).
- At the pipeline level, with the [workflow rules keywords](../../../../ci/yaml/workflow.md).
## Related topics
- [Tagging](https://git-scm.com/book/en/v2/Git-Basics-Tagging) Git reference page.

View File

@ -450,7 +450,7 @@ when:
- You select any area outside the file editor after editing a file.
- A file or folder is created, deleted, or renamed.
### Known issues
## Known issues
The Web IDE has a few limitations:
@ -458,7 +458,9 @@ The Web IDE has a few limitations:
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 is overwritten with the modified LFS file content.
### Troubleshooting
## Troubleshooting
### Web terminals
- If the terminal's text is gray and unresponsive, then the terminal has stopped
and it can no longer be used. A stopped terminal can be restarted by selecting
@ -466,7 +468,3 @@ The Web IDE has a few limitations:
- If the terminal displays **Connection Failure**, then the terminal could not
connect to the runner. Try to stop and restart the terminal. If the
problem persists, double check your runner configuration.
## Related topics
- [Web IDE Beta](../web_ide_beta/index.md)

View File

@ -128,8 +128,3 @@ The [Web Terminal](../web_ide/index.md#interactive-web-terminals-for-the-web-ide
and [Live Preview](../web_ide/index.md#live-preview-removed) are not available in the Web IDE Beta.
These features might become available at a later date.
## Related topics
- [Remote Development](../remote_development/index.md)
- [Web IDE](../web_ide/index.md)

View File

@ -50,7 +50,7 @@ module Sidebars
if menu_item.super_sidebar_before
menus[idx].insert_item_before(menu_item.super_sidebar_before, menu_item)
else
menus[idx].add_item(menu_item)
menus[idx].replace_placeholder(menu_item)
end
end
end

View File

@ -117,6 +117,15 @@ module Sidebars
insert_element_after(@items, after_item, new_item)
end
def replace_placeholder(item)
idx = @items.index { |e| e.item_id == item.item_id && e.is_a?(::Sidebars::NilMenuItem) }
if idx.nil?
add_item(item)
else
replace_element(@items, item.item_id, item)
end
end
override :container_html_options
def container_html_options
super.tap do |html_options|

View File

@ -41,9 +41,9 @@ module Sidebars
'chart'
end
override :pick_into_super_sidebar?
def pick_into_super_sidebar?
true
override :serialize_as_menu_item_args
def serialize_as_menu_item_args
nil
end
private
@ -57,8 +57,9 @@ module Sidebars
end
::Sidebars::MenuItem.new(
title: _('CI/CD'),
title: context.is_super_sidebar ? _('CI/CD analytics') : _('CI/CD'),
link: charts_project_pipelines_path(context.project),
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::AnalyzeMenu,
active_routes: { path: 'pipelines#charts' },
item_id: :ci_cd_analytics
)
@ -70,8 +71,9 @@ module Sidebars
end
::Sidebars::MenuItem.new(
title: _('Repository'),
title: context.is_super_sidebar ? _('Repository analytics') : _('Repository'),
link: charts_project_graph_path(context.project, context.current_ref),
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::AnalyzeMenu,
container_html_options: { class: 'shortcuts-repository-charts' },
active_routes: { path: 'graphs#charts' },
item_id: :repository_analytics
@ -85,8 +87,9 @@ module Sidebars
end
::Sidebars::MenuItem.new(
title: _('Value stream'),
title: context.is_super_sidebar ? _('Value stream analytics') : _('Value stream'),
link: project_cycle_analytics_path(context.project),
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::AnalyzeMenu,
container_html_options: { class: 'shortcuts-project-cycle-analytics' },
active_routes: { path: 'cycle_analytics#show' },
item_id: :cycle_analytics

View File

@ -44,17 +44,18 @@ module Sidebars
'doc-text'
end
override :pick_into_super_sidebar?
def pick_into_super_sidebar?
true
override :serialize_as_menu_item_args
def serialize_as_menu_item_args
nil
end
private
def files_menu_item
::Sidebars::MenuItem.new(
title: _('Files'),
title: context.is_super_sidebar ? _('Repository') : _('Files'),
link: project_tree_path(context.project, context.current_ref),
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::CodeMenu,
active_routes: { controller: %w[tree blob blame edit_tree new_tree find_file] },
item_id: :files
)
@ -66,6 +67,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Commits'),
link: link,
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::CodeMenu,
active_routes: { controller: %w(commit commits) },
item_id: :commits,
container_html_options: { id: 'js-onboarding-commits-link' }
@ -76,6 +78,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Branches'),
link: project_branches_path(context.project),
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::CodeMenu,
active_routes: { controller: :branches },
item_id: :branches,
container_html_options: { id: 'js-onboarding-branches-link' }
@ -86,6 +89,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Tags'),
link: project_tags_path(context.project),
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::CodeMenu,
item_id: :tags,
active_routes: { controller: :tags }
)
@ -99,6 +103,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Contributor statistics'),
link: link,
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::AnalyzeMenu,
active_routes: { path: 'graphs#show' },
item_id: :contributors
)
@ -108,8 +113,9 @@ module Sidebars
link = project_network_path(context.project, context.current_ref, ref_type: ref_type_from_context(context))
::Sidebars::MenuItem.new(
title: _('Graph'),
title: context.is_super_sidebar ? _('Repository graph') : _('Graph'),
link: link,
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::CodeMenu,
active_routes: { controller: :network },
item_id: :graphs
)
@ -118,6 +124,7 @@ module Sidebars
def compare_menu_item
::Sidebars::MenuItem.new(
title: _('Compare revisions'),
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::CodeMenu,
link: project_compare_index_path(context.project, from: context.project.repository.root_ref, to: context.current_ref),
active_routes: { controller: :compare },
item_id: :compare

View File

@ -25,9 +25,9 @@ module Sidebars
'shield'
end
override :pick_into_super_sidebar?
def pick_into_super_sidebar?
true
override :serialize_as_menu_item_args
def serialize_as_menu_item_args
nil
end
private
@ -40,6 +40,7 @@ module Sidebars
::Sidebars::MenuItem.new(
title: _('Security configuration'),
link: project_security_configuration_path(context.project),
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::SecureMenu,
active_routes: { path: configuration_menu_item_paths },
item_id: :configuration
)

View File

@ -39,8 +39,7 @@ module Sidebars
override :serialize_as_menu_item_args
def serialize_as_menu_item_args
super.deep_merge({
super_sidebar_parent: ::Sidebars::Projects::Menus::RepositoryMenu,
super_sidebar_before: :contributors,
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::CodeMenu,
item_id: :project_snippets
})
end

View File

@ -0,0 +1,34 @@
# frozen_string_literal: true
module Sidebars
module Projects
module SuperSidebarMenus
class AnalyzeMenu < ::Sidebars::Menu
override :title
def title
s_('Navigation|Analyze')
end
override :sprite_icon
def sprite_icon
'chart'
end
override :configure_menu_items
def configure_menu_items
[
:dashboards_analytics,
:cycle_analytics,
:contributors,
:ci_cd_analytics,
:repository_analytics,
:code_review,
:merge_requests,
:issues,
:insights
].each { |id| add_item(::Sidebars::NilMenuItem.new(item_id: id)) }
end
end
end
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Sidebars
module Projects
module SuperSidebarMenus
class BuildMenu < ::Sidebars::Menu
override :title
def title
s_('Navigation|Build')
end
override :sprite_icon
def sprite_icon
'rocket'
end
end
end
end
end

View File

@ -0,0 +1,33 @@
# frozen_string_literal: true
module Sidebars
module Projects
module SuperSidebarMenus
class CodeMenu < ::Sidebars::Menu
override :title
def title
s_('Navigation|Code')
end
override :sprite_icon
def sprite_icon
'code'
end
override :configure_menu_items
def configure_menu_items
[
:files,
:branches,
:commits,
:tags,
:graphs,
:compare,
:project_snippets,
:file_locks
].each { |id| add_item(::Sidebars::NilMenuItem.new(item_id: id)) }
end
end
end
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Sidebars
module Projects
module SuperSidebarMenus
class ManageMenu < ::Sidebars::Menu
override :title
def title
s_('Navigation|Manage')
end
override :sprite_icon
def sprite_icon
'users'
end
end
end
end
end

View File

@ -0,0 +1,19 @@
# frozen_string_literal: true
module Sidebars
module Projects
module SuperSidebarMenus
class MonitorMenu < ::Sidebars::Menu
override :title
def title
s_('Navigation|Monitor')
end
override :sprite_icon
def sprite_icon
'monitor'
end
end
end
end
end

View File

@ -6,7 +6,7 @@ module Sidebars
class OperationsMenu < ::Sidebars::Menu
override :title
def title
_('Operations')
s_('Navigation|Operate')
end
override :sprite_icon

View File

@ -6,7 +6,7 @@ module Sidebars
class PlanMenu < ::Sidebars::Menu
override :title
def title
_('Plan')
s_('Navigation|Plan')
end
override :sprite_icon

View File

@ -0,0 +1,34 @@
# frozen_string_literal: true
module Sidebars
module Projects
module SuperSidebarMenus
class SecureMenu < ::Sidebars::Menu
override :title
def title
s_('Navigation|Secure')
end
override :sprite_icon
def sprite_icon
'shield'
end
override :configure_menu_items
def configure_menu_items
[
:discover_project_security,
:audit_events,
:dashboard,
:vulnerability_report,
:on_demand_scans,
:scan_policies,
:dependency_list,
:license_compliance,
:configuration
].each { |id| add_item(::Sidebars::NilMenuItem.new(item_id: id)) }
end
end
end
end
end

View File

@ -13,15 +13,19 @@ module Sidebars
@menus = []
add_menu(Sidebars::StaticMenu.new(context))
add_menu(Sidebars::Projects::SuperSidebarMenus::ManageMenu.new(context))
add_menu(Sidebars::Projects::SuperSidebarMenus::PlanMenu.new(context))
add_menu(Sidebars::Projects::SuperSidebarMenus::CodeMenu.new(context))
add_menu(Sidebars::Projects::SuperSidebarMenus::BuildMenu.new(context))
add_menu(Sidebars::Projects::SuperSidebarMenus::SecureMenu.new(context))
add_menu(Sidebars::Projects::SuperSidebarMenus::OperationsMenu.new(context))
add_menu(Sidebars::Projects::SuperSidebarMenus::MonitorMenu.new(context))
add_menu(Sidebars::Projects::SuperSidebarMenus::AnalyzeMenu.new(context))
# Pick old menus, will be obsolete once everything is in their own
# super sidebar menu
pick_from_old_menus(old_menus)
insert_menu_before(
Sidebars::Projects::Menus::MonitorMenu,
Sidebars::Projects::SuperSidebarMenus::OperationsMenu.new(context)
)
insert_menu_before(
Sidebars::Projects::Menus::SettingsMenu,
Sidebars::UncategorizedMenu.new(context)

View File

@ -5002,6 +5002,9 @@ msgstr ""
msgid "Application ID"
msgstr ""
msgid "Application analytics"
msgstr ""
msgid "Application limits saved successfully"
msgstr ""
@ -7967,6 +7970,9 @@ msgstr ""
msgid "CI/CD Settings"
msgstr ""
msgid "CI/CD analytics"
msgstr ""
msgid "CI/CD configuration"
msgstr ""
@ -10341,6 +10347,9 @@ msgstr ""
msgid "Code review"
msgstr ""
msgid "Code review analytics"
msgstr ""
msgid "Code snippet"
msgstr ""
@ -18036,6 +18045,9 @@ msgstr ""
msgid "File name"
msgstr ""
msgid "File permissions"
msgstr ""
msgid "File renamed with no changes."
msgstr ""
@ -23997,6 +24009,9 @@ msgstr ""
msgid "Issue already promoted to epic."
msgstr ""
msgid "Issue analytics"
msgstr ""
msgid "Issue board"
msgstr ""
@ -28513,6 +28528,15 @@ msgstr ""
msgid "Navigation|Admin"
msgstr ""
msgid "Navigation|Analyze"
msgstr ""
msgid "Navigation|Build"
msgstr ""
msgid "Navigation|Code"
msgstr ""
msgid "Navigation|Context navigation"
msgstr ""
@ -28531,12 +28555,24 @@ msgstr ""
msgid "Navigation|Groups you visit often will appear here."
msgstr ""
msgid "Navigation|Manage"
msgstr ""
msgid "Navigation|Monitor"
msgstr ""
msgid "Navigation|No group matches found"
msgstr ""
msgid "Navigation|No project matches found"
msgstr ""
msgid "Navigation|Operate"
msgstr ""
msgid "Navigation|Plan"
msgstr ""
msgid "Navigation|Projects"
msgstr ""
@ -28549,6 +28585,9 @@ msgstr ""
msgid "Navigation|Search for projects or groups"
msgstr ""
msgid "Navigation|Secure"
msgstr ""
msgid "Navigation|Switch to..."
msgstr ""
@ -36945,6 +36984,9 @@ msgstr ""
msgid "Repository already read-only"
msgstr ""
msgid "Repository analytics"
msgstr ""
msgid "Repository by URL"
msgstr ""
@ -36969,6 +37011,9 @@ msgstr ""
msgid "Repository files count over the limit"
msgstr ""
msgid "Repository graph"
msgstr ""
msgid "Repository has an invalid default branch name."
msgstr ""
@ -47752,6 +47797,9 @@ msgstr ""
msgid "Value stream"
msgstr ""
msgid "Value stream analytics"
msgstr ""
msgid "ValueStreamAnalyticsStage|We don't have enough data to show this stage."
msgstr ""

View File

@ -0,0 +1,45 @@
# frozen_string_literal: true
require 'rubocop/cop/rspec/base'
module RuboCop
module Cop
module RSpec
# Ensures that shared examples don't have feature category.
#
# @example
#
# # bad
# RSpec.shared_examples 'an external link with rel attribute', feature_category: :team_planning do
# end
#
# # good
# RSpec.shared_examples 'an external link with rel attribute' do
# end
#
# it 'adds rel="nofollow" to external links', feature_category: :team_planning do
# end
class FeatureCategoryOnSharedExamples < RuboCop::Cop::RSpec::Base
MSG = 'Shared examples should not have feature category set'
# @!method feature_category_value(node)
def_node_matcher :feature_category_value, <<~PATTERN
(block
(send #rspec? {#SharedGroups.all} ...
$(hash <(pair (sym :feature_category) _) ...>)
)
...
)
PATTERN
def on_block(node)
value_node = feature_category_value(node)
return unless value_node
add_offense(value_node, message: MSG)
end
end
end
end
end

View File

@ -36,6 +36,7 @@ describe('AgentTable', () => {
const findStatusIcon = (at) => findStatusText(at).findComponent(GlIcon);
const findLastContactText = (at) => wrapper.findAllByTestId('cluster-agent-last-contact').at(at);
const findVersionText = (at) => wrapper.findAllByTestId('cluster-agent-version').at(at);
const findAgentId = (at) => wrapper.findAllByTestId('cluster-agent-id').at(at);
const findConfiguration = (at) =>
wrapper.findAllByTestId('cluster-agent-configuration-link').at(at);
const findDeleteAgentButton = () => wrapper.findAllComponents(DeleteAgentButton);
@ -65,6 +66,17 @@ describe('AgentTable', () => {
expect(findAgentLink(lineNumber).attributes('href')).toBe(link);
});
it.each`
agentGraphQLId | agentId | lineNumber
${'gid://gitlab/Clusters::Agent/1'} | ${'1'} | ${0}
${'gid://gitlab/Clusters::Agent/2'} | ${'2'} | ${1}
`(
'displays agent id as "$agentId" for "$agentGraphQLId" at line $lineNumber',
({ agentId, lineNumber }) => {
expect(findAgentId(lineNumber).text()).toBe(agentId);
},
);
it.each`
status | iconName | lineNumber
${'Never connected'} | ${'status-neutral'} | ${0}

View File

@ -19,7 +19,7 @@ export const connectedTimeInactive = new Date(connectedTimeNow.getTime() - ACTIV
export const clusterAgents = [
{
name: 'agent-1',
id: 'agent-1-id',
id: 'gid://gitlab/Clusters::Agent/1',
configFolder: {
webPath: '/agent/full/path',
},
@ -30,7 +30,7 @@ export const clusterAgents = [
},
{
name: 'agent-2',
id: 'agent-2-id',
id: 'gid://gitlab/Clusters::Agent/2',
webPath: '/agent-2',
status: 'active',
lastContact: connectedTimeNow.getTime(),
@ -54,7 +54,7 @@ export const clusterAgents = [
},
{
name: 'agent-3',
id: 'agent-3-id',
id: 'gid://gitlab/Clusters::Agent/3',
webPath: '/agent-3',
status: 'inactive',
lastContact: connectedTimeInactive.getTime(),
@ -75,7 +75,7 @@ export const clusterAgents = [
},
{
name: 'agent-4',
id: 'agent-4-id',
id: 'gid://gitlab/Clusters::Agent/4',
webPath: '/agent-4',
status: 'inactive',
lastContact: connectedTimeInactive.getTime(),
@ -99,7 +99,7 @@ export const clusterAgents = [
},
{
name: 'agent-5',
id: 'agent-5-id',
id: 'gid://gitlab/Clusters::Agent/5',
webPath: '/agent-5',
status: 'inactive',
lastContact: connectedTimeInactive.getTime(),
@ -123,7 +123,7 @@ export const clusterAgents = [
},
{
name: 'agent-6',
id: 'agent-6-id',
id: 'gid://gitlab/Clusters::Agent/6',
webPath: '/agent-6',
status: 'inactive',
lastContact: connectedTimeInactive.getTime(),
@ -144,7 +144,7 @@ export const clusterAgents = [
},
{
name: 'agent-7',
id: 'agent-7-id',
id: 'gid://gitlab/Clusters::Agent/7',
webPath: '/agent-7',
status: 'inactive',
lastContact: connectedTimeInactive.getTime(),
@ -165,7 +165,7 @@ export const clusterAgents = [
},
{
name: 'agent-8',
id: 'agent-8-id',
id: 'gid://gitlab/Clusters::Agent/8',
webPath: '/agent-8',
status: 'inactive',
lastContact: connectedTimeInactive.getTime(),
@ -186,7 +186,7 @@ export const clusterAgents = [
},
{
name: 'agent-9',
id: 'agent-9-id',
id: 'gid://gitlab/Clusters::Agent/9',
webPath: '/agent-9',
status: 'inactive',
lastContact: connectedTimeInactive.getTime(),

View File

@ -1,4 +1,5 @@
import { mount } from '@vue/test-utils';
import { GlFormCheckbox } from '@gitlab/ui';
import getDiffWithCommit from 'test_fixtures/merge_request_diffs/with_commit.json';
import { TEST_HOST } from 'helpers/test_constants';
import { trimText } from 'helpers/text_helper';
@ -28,6 +29,7 @@ describe('diffs/components/commit_item', () => {
const getCommitterElement = () => wrapper.find('.committer');
const getCommitActionsElement = () => wrapper.find('.commit-actions');
const getCommitPipelineStatus = () => wrapper.findComponent(CommitPipelineStatus);
const getCommitCheckbox = () => wrapper.findComponent(GlFormCheckbox);
const mountComponent = (propsData) => {
wrapper = mount(Component, {
@ -168,4 +170,24 @@ describe('diffs/components/commit_item', () => {
expect(getCommitPipelineStatus().exists()).toBe(true);
});
});
describe('when commit is selectable', () => {
beforeEach(() => {
mountComponent({
commit: { ...commit },
isSelectable: true,
});
});
it('renders checkbox', () => {
expect(getCommitCheckbox().exists()).toBe(true);
});
it('emits "handleCheckboxChange" event on change', () => {
expect(wrapper.emitted('handleCheckboxChange')).toBeUndefined();
getCommitCheckbox().vm.$emit('change');
expect(wrapper.emitted('handleCheckboxChange')[0]).toEqual([true]);
});
});
});

View File

@ -83,6 +83,16 @@ RSpec.describe Sidebars::Concerns::SuperSidebarPanel, feature_category: :navigat
expect(uncategorized_menu.renderable_items).to eq([])
end
it 'replaces placeholder Menu Items in the defined super_sidebar_parent' do
menu_foo.insert_item_before(:exists, nil_menu_item)
allow(menu_item).to receive(:item_id).and_return(:nil_item)
subject.transform_old_menus(current_menus, menu_bar)
expect(menu_foo.renderable_items).to eq([menu_item, existing_item])
expect(uncategorized_menu.renderable_items).to eq([])
end
it 'adds Menu Items to defined super_sidebar_parent, before super_sidebar_before' do
allow(menu_item).to receive(:super_sidebar_before).and_return(:exists)
subject.transform_old_menus(current_menus, menu_bar)

View File

@ -238,6 +238,47 @@ RSpec.describe Sidebars::Menu, feature_category: :navigation do
end
end
describe '#replace_placeholder' do
let(:item1) { Sidebars::NilMenuItem.new(item_id: :foo1) }
let(:item2) { Sidebars::MenuItem.new(item_id: :foo2, title: 'foo2', link: 'foo2', active_routes: {}) }
let(:item3) { Sidebars::NilMenuItem.new(item_id: :foo3) }
subject { menu.instance_variable_get(:@items) }
before do
menu.add_item(item1)
menu.add_item(item2)
menu.add_item(item3)
end
context 'when a NilMenuItem reference element exists' do
it 'replaces the reference element with the provided item' do
item = Sidebars::MenuItem.new(item_id: :foo1, title: 'target', active_routes: {}, link: 'target')
menu.replace_placeholder(item)
expect(subject).to eq [item, item2, item3]
end
end
context 'when a MenuItem reference element exists' do
it 'does not replace the reference element and adds to the end of the list' do
item = Sidebars::MenuItem.new(item_id: :foo2, title: 'target', active_routes: {}, link: 'target')
menu.replace_placeholder(item)
expect(subject).to eq [item1, item2, item3, item]
end
end
context 'when reference element does not exist' do
it 'adds the element to the end of the list' do
item = Sidebars::MenuItem.new(item_id: :new_element, title: 'target', active_routes: {}, link: 'target')
menu.replace_placeholder(item)
expect(subject).to eq [item1, item2, item3, item]
end
end
end
describe '#remove_element' do
let(:item1) { Sidebars::MenuItem.new(title: 'foo1', link: 'foo1', active_routes: {}, item_id: :foo1) }
let(:item2) { Sidebars::MenuItem.new(title: 'foo2', link: 'foo2', active_routes: {}, item_id: :foo2) }

View File

@ -6,7 +6,11 @@ RSpec.describe Sidebars::Projects::Menus::RepositoryMenu, feature_category: :sou
let_it_be(:project) { create(:project, :repository) }
let(:user) { project.first_owner }
let(:context) { Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: 'master') }
let(:is_super_sidebar) { false }
let(:context) do
Sidebars::Projects::Context.new(current_user: user, container: project, current_ref: 'master',
is_super_sidebar: is_super_sidebar)
end
subject { described_class.new(context) }
@ -36,9 +40,8 @@ RSpec.describe Sidebars::Projects::Menus::RepositoryMenu, feature_category: :sou
end
context 'for menu items' do
shared_examples_for 'repository menu item link for' do |item_id|
shared_examples_for 'repository menu item link for' do
let(:ref) { 'master' }
let(:item_id) { item_id }
subject { described_class.new(context).renderable_items.find { |e| e.item_id == item_id }.link }
using RSpec::Parameterized::TableSyntax
@ -77,10 +80,34 @@ RSpec.describe Sidebars::Projects::Menus::RepositoryMenu, feature_category: :sou
end
end
shared_examples_for 'repository menu item with different super sidebar title' do |title, super_sidebar_title|
subject { described_class.new(context).renderable_items.find { |e| e.item_id == item_id } }
specify do
expect(subject.title).to eq(title)
end
context 'when inside the super sidebar' do
let(:is_super_sidebar) { true }
specify do
expect(subject.title).to eq(super_sidebar_title)
end
end
end
describe 'Files' do
let_it_be(:item_id) { :files }
it_behaves_like 'repository menu item with different super sidebar title',
_('Files'),
_('Repository')
end
describe 'Commits' do
let_it_be(:item_id) { :commits }
it_behaves_like 'repository menu item link for', :commits do
it_behaves_like 'repository menu item link for' do
let(:route) { "/#{project.full_path}/-/commits/#{ref}" }
end
end
@ -103,16 +130,22 @@ RSpec.describe Sidebars::Projects::Menus::RepositoryMenu, feature_category: :sou
project.project_feature.update!(analytics_access_level: ProjectFeature::ENABLED)
end
it_behaves_like 'repository menu item link for', :contributors do
it_behaves_like 'repository menu item link for' do
let(:route) { "/#{project.full_path}/-/graphs/#{ref}" }
end
end
end
describe 'Network' do
it_behaves_like 'repository menu item link for', :graphs do
let_it_be(:item_id) { :graphs }
it_behaves_like 'repository menu item link for' do
let(:route) { "/#{project.full_path}/-/network/#{ref}" }
end
it_behaves_like 'repository menu item with different super sidebar title',
_('Graph'),
_('Repository graph')
end
end
end

View File

@ -13,8 +13,7 @@ RSpec.describe Sidebars::Projects::Menus::SnippetsMenu, feature_category: :navig
let(:menu) { subject }
let(:extra_attrs) do
{
super_sidebar_parent: ::Sidebars::Projects::Menus::RepositoryMenu,
super_sidebar_before: :contributors,
super_sidebar_parent: ::Sidebars::Projects::SuperSidebarMenus::CodeMenu,
item_id: :project_snippets
}
end

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::SuperSidebarMenus::AnalyzeMenu, feature_category: :navigation do
subject { described_class.new({}) }
let(:items) { subject.instance_variable_get(:@items) }
it 'has title and sprite_icon' do
expect(subject.title).to eq(s_("Navigation|Analyze"))
expect(subject.sprite_icon).to eq("chart")
end
it 'defines list of NilMenuItem placeholders' do
expect(items.map(&:class).uniq).to eq([Sidebars::NilMenuItem])
expect(items.map(&:item_id)).to eq([
:dashboards_analytics,
:cycle_analytics,
:contributors,
:ci_cd_analytics,
:repository_analytics,
:code_review,
:merge_requests,
:issues,
:insights
])
end
end

View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::SuperSidebarMenus::BuildMenu, feature_category: :navigation do
subject { described_class.new({}) }
it 'has title and sprite_icon' do
expect(subject.title).to eq(s_("Navigation|Build"))
expect(subject.sprite_icon).to eq("rocket")
end
end

View File

@ -0,0 +1,28 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::SuperSidebarMenus::CodeMenu, feature_category: :navigation do
subject { described_class.new({}) }
let(:items) { subject.instance_variable_get(:@items) }
it 'has title and sprite_icon' do
expect(subject.title).to eq(s_("Navigation|Code"))
expect(subject.sprite_icon).to eq("code")
end
it 'defines list of NilMenuItem placeholders' do
expect(items.map(&:class).uniq).to eq([Sidebars::NilMenuItem])
expect(items.map(&:item_id)).to eq([
:files,
:branches,
:commits,
:tags,
:graphs,
:compare,
:project_snippets,
:file_locks
])
end
end

View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::SuperSidebarMenus::ManageMenu, feature_category: :navigation do
subject { described_class.new({}) }
it 'has title and sprite_icon' do
expect(subject.title).to eq(s_("Navigation|Manage"))
expect(subject.sprite_icon).to eq("users")
end
end

View File

@ -0,0 +1,12 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::SuperSidebarMenus::MonitorMenu, feature_category: :navigation do
subject { described_class.new({}) }
it 'has title and sprite_icon' do
expect(subject.title).to eq(s_("Navigation|Monitor"))
expect(subject.sprite_icon).to eq("monitor")
end
end

View File

@ -6,7 +6,7 @@ RSpec.describe Sidebars::Projects::SuperSidebarMenus::OperationsMenu, feature_ca
subject { described_class.new({}) }
it 'has title and sprite_icon' do
expect(subject.title).to eq(_("Operations"))
expect(subject.title).to eq(s_("Navigation|Operate"))
expect(subject.sprite_icon).to eq("deployments")
end
end

View File

@ -6,7 +6,7 @@ RSpec.describe Sidebars::Projects::SuperSidebarMenus::PlanMenu, feature_category
subject { described_class.new({}) }
it 'has title and sprite_icon' do
expect(subject.title).to eq(_("Plan"))
expect(subject.title).to eq(s_("Navigation|Plan"))
expect(subject.sprite_icon).to eq("planning")
end
end

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Projects::SuperSidebarMenus::SecureMenu, feature_category: :navigation do
subject { described_class.new({}) }
let(:items) { subject.instance_variable_get(:@items) }
it 'has title and sprite_icon' do
expect(subject.title).to eq(s_("Navigation|Secure"))
expect(subject.sprite_icon).to eq("shield")
end
it 'defines list of NilMenuItem placeholders' do
expect(items.map(&:class).uniq).to eq([Sidebars::NilMenuItem])
expect(items.map(&:item_id)).to eq([
:discover_project_security,
:audit_events,
:dashboard,
:vulnerability_report,
:on_demand_scans,
:scan_policies,
:dependency_list,
:license_compliance,
:configuration
])
end
end

View File

@ -26,13 +26,16 @@ RSpec.describe Sidebars::Projects::SuperSidebarPanel, feature_category: :navigat
let(:category_menu) do
[
Sidebars::StaticMenu,
Sidebars::Projects::SuperSidebarMenus::ManageMenu,
Sidebars::Projects::SuperSidebarMenus::PlanMenu,
Sidebars::Projects::Menus::RepositoryMenu,
Sidebars::Projects::Menus::CiCdMenu,
Sidebars::Projects::Menus::SecurityComplianceMenu,
Sidebars::Projects::SuperSidebarMenus::CodeMenu,
Sidebars::Projects::SuperSidebarMenus::BuildMenu,
Sidebars::Projects::SuperSidebarMenus::SecureMenu,
Sidebars::Projects::SuperSidebarMenus::OperationsMenu,
Sidebars::Projects::SuperSidebarMenus::MonitorMenu,
Sidebars::Projects::SuperSidebarMenus::AnalyzeMenu,
Sidebars::Projects::Menus::CiCdMenu,
Sidebars::Projects::Menus::MonitorMenu,
Sidebars::Projects::Menus::AnalyticsMenu,
Sidebars::UncategorizedMenu,
Sidebars::Projects::Menus::SettingsMenu
]

View File

@ -0,0 +1,30 @@
# frozen_string_literal: true
require 'rubocop_spec_helper'
require 'rspec-parameterized'
require_relative '../../../../rubocop/cop/rspec/feature_category_on_shared_examples'
RSpec.describe RuboCop::Cop::RSpec::FeatureCategoryOnSharedExamples, feature_category: :tooling do
it 'flags feature category in shared example' do
expect_offense(<<~RUBY)
RSpec.shared_examples 'foo', feature_category: :shared do
^^^^^^^^^^^^^^^^^^^^^^^^^ Shared examples should not have feature category set
end
shared_examples 'foo', feature_category: :shared do
^^^^^^^^^^^^^^^^^^^^^^^^^ Shared examples should not have feature category set
end
RUBY
end
it 'does not flag if feature category is missing' do
expect_no_offenses(<<~RUBY)
RSpec.shared_examples 'foo' do
end
shared_examples 'foo', some: :tag do
end
RUBY
end
end