Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--GITALY_SERVER_VERSION2
-rw-r--r--app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue2
-rw-r--r--app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue4
-rw-r--r--app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue3
-rw-r--r--app/controllers/omniauth_callbacks_controller.rb4
-rw-r--r--app/models/project.rb1
-rw-r--r--app/views/projects/merge_requests/_merge_request.html.haml8
-rw-r--r--db/migrate/20230328020316_delete_unused_index_on_merge_requests_on_state_id_and_merge_status.rb17
-rw-r--r--db/schema_migrations/202303280203161
-rw-r--r--doc/api/environments.md4
-rw-r--r--doc/ci/environments/img/environment_auto_stop_v13_10.pngbin16265 -> 0 bytes
-rw-r--r--doc/ci/environments/index.md208
-rw-r--r--doc/ci/environments/protected_environments.md2
-rw-r--r--doc/ci/pipelines/index.md2
-rw-r--r--doc/ci/review_apps/index.md2
-rw-r--r--doc/ci/variables/predefined_variables.md1
-rw-r--r--doc/ci/yaml/index.md2
-rw-r--r--doc/development/documentation/styleguide/index.md9
-rw-r--r--doc/development/testing_guide/review_apps.md2
-rw-r--r--doc/topics/autodevops/cloud_deployments/auto_devops_with_eks.md2
-rw-r--r--doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md2
-rw-r--r--doc/user/application_security/secret_detection/post_processing.md21
-rw-r--r--doc/user/profile/account/create_accounts.md20
-rw-r--r--doc/user/profile/achievements.md195
-rw-r--r--doc/user/profile/img/user_profile_achievements_v15_11.pngbin0 -> 74766 bytes
-rw-r--r--locale/gitlab.pot6
-rw-r--r--qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb3
-rw-r--r--spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js15
-rw-r--r--spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js2
-rw-r--r--spec/lib/gitlab/ci/variables/builder_spec.rb2
-rw-r--r--spec/models/ci/build_spec.rb1
-rw-r--r--spec/models/project_spec.rb17
32 files changed, 413 insertions, 147 deletions
diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 6f875b6cfb8..2927a9c0482 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-4a144bdd080a7eeca4399d43add443fd7326b227
+82da6c9eb6897bf3bbb7a791ba13a184f5679d24
diff --git a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
index 40873245beb..c6a8c07da52 100644
--- a/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
+++ b/app/assets/javascripts/vue_merge_request_widget/components/widget/widget.vue
@@ -219,6 +219,8 @@ export default {
this.fetchExpandedContent();
}
}
+
+ this.$emit('toggle', { expanded: !this.isCollapsed });
},
async fetchExpandedContent() {
this.isLoadingExpandedContent = true;
diff --git a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue
index b0fa3e4c27e..b5783265ffa 100644
--- a/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue
+++ b/app/assets/javascripts/vue_shared/components/filtered_search_bar/tokens/base_token.vue
@@ -9,7 +9,7 @@ import {
} from '@gitlab/ui';
import { debounce } from 'lodash';
-import { DEBOUNCE_DELAY, FILTERS_NONE_ANY, OPERATOR_NOT } from '../constants';
+import { DEBOUNCE_DELAY, FILTERS_NONE_ANY, OPERATOR_NOT, OPERATOR_OR } from '../constants';
import {
getRecentlyUsedSuggestions,
setTokenValueToRecentlyUsed,
@@ -100,7 +100,7 @@ export default {
return this.getActiveTokenValue(this.suggestions, this.value.data);
},
availableDefaultSuggestions() {
- if (this.value.operator === OPERATOR_NOT) {
+ if ([OPERATOR_NOT, OPERATOR_OR].includes(this.value.operator)) {
return this.defaultSuggestions.filter(
(suggestion) => !FILTERS_NONE_ANY.includes(suggestion.value),
);
diff --git a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue
index cc8c834fff4..2200bb08863 100644
--- a/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue
+++ b/app/assets/javascripts/vue_shared/issuable/list/components/issuable_item.vue
@@ -286,7 +286,6 @@ export default {
</span>
<slot name="timeframe"></slot>
</span>
- &nbsp;
<p v-if="labels.length" role="group" :aria-label="__('Labels')" class="gl-mt-1 gl-mb-0">
<gl-label
v-for="(label, index) in labels"
@@ -296,7 +295,7 @@ export default {
:description="label.description"
:scoped="scopedLabel(label)"
:target="labelTarget(label)"
- :class="{ 'gl-ml-2': index }"
+ class="gl-mr-2"
size="sm"
/>
</p>
diff --git a/app/controllers/omniauth_callbacks_controller.rb b/app/controllers/omniauth_callbacks_controller.rb
index daed4023d02..b9964e8ca01 100644
--- a/app/controllers/omniauth_callbacks_controller.rb
+++ b/app/controllers/omniauth_callbacks_controller.rb
@@ -183,7 +183,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
persist_accepted_terms_if_required(user) if new_user
store_after_sign_up_path_for_user if intent_to_register?
- sign_in_and_redirect_or_confirm_identity(user, auth_user, new_user)
+ sign_in_and_redirect_or_verify_identity(user, auth_user, new_user)
end
else
fail_login(user)
@@ -315,7 +315,7 @@ class OmniauthCallbacksController < Devise::OmniauthCallbacksController
end
# overridden in EE
- def sign_in_and_redirect_or_confirm_identity(user, _, _)
+ def sign_in_and_redirect_or_verify_identity(user, _, _)
sign_in_and_redirect(user, event: :authentication)
end
end
diff --git a/app/models/project.rb b/app/models/project.rb
index d0c89edf407..2462777400a 100644
--- a/app/models/project.rb
+++ b/app/models/project.rb
@@ -2423,6 +2423,7 @@ class Project < ApplicationRecord
def api_variables
Gitlab::Ci::Variables::Collection.new.tap do |variables|
variables.append(key: 'CI_API_V4_URL', value: API::Helpers::Version.new('v4').root_url)
+ variables.append(key: 'CI_API_GRAPHQL_URL', value: Gitlab::Routing.url_helpers.api_graphql_url)
end
end
diff --git a/app/views/projects/merge_requests/_merge_request.html.haml b/app/views/projects/merge_requests/_merge_request.html.haml
index 7b449134567..85396134db2 100644
--- a/app/views/projects/merge_requests/_merge_request.html.haml
+++ b/app/views/projects/merge_requests/_merge_request.html.haml
@@ -39,9 +39,9 @@
= sprite_icon('branch', size: 12, css_class: 'fork-sprite')
= merge_request.target_branch
- if merge_request.labels.any?
- &nbsp;
- - presented_labels_sorted_by_title(merge_request.labels, merge_request.project).each do |label|
- = link_to_label(label, type: :merge_request, small: true)
+ .gl-mt-1{ role: 'group', 'aria-label': _('Labels') }
+ - presented_labels_sorted_by_title(merge_request.labels, merge_request.project).each do |label|
+ = link_to_label(label, type: :merge_request, small: true)
.issuable-meta
%ul.controls.d-flex.align-items-end
@@ -66,6 +66,6 @@
= render 'shared/issuable_meta_data', issuable: merge_request
- .float-right.issuable-updated-at.d-none.d-sm-inline-block
+ .float-right.issuable-updated-at.d-none.d-sm-inline-block.gl-text-gray-500
%span
= _('updated %{time_ago}').html_safe % { time_ago: time_ago_with_tooltip(merge_request.updated_at, placement: 'bottom', html_class: 'merge_request_updated_ago') }
diff --git a/db/migrate/20230328020316_delete_unused_index_on_merge_requests_on_state_id_and_merge_status.rb b/db/migrate/20230328020316_delete_unused_index_on_merge_requests_on_state_id_and_merge_status.rb
new file mode 100644
index 00000000000..eac1d4e30c1
--- /dev/null
+++ b/db/migrate/20230328020316_delete_unused_index_on_merge_requests_on_state_id_and_merge_status.rb
@@ -0,0 +1,17 @@
+# frozen_string_literal: true
+
+class DeleteUnusedIndexOnMergeRequestsOnStateIdAndMergeStatus < Gitlab::Database::Migration[2.1]
+ # TODO: Index to be destroyed synchronously in https://gitlab.com/gitlab-org/gitlab/-/issues/402491
+
+ def up
+ prepare_async_index_removal :merge_requests, [:state_id, :merge_status],
+ where: "((state_id = 1) AND ((merge_status)::text = 'can_be_merged'::text))",
+ name: 'idx_merge_requests_on_state_id_and_merge_status'
+ end
+
+ def down
+ unprepare_async_index :merge_requests, [:state_id, :merge_status],
+ where: "((state_id = 1) AND ((merge_status)::text = 'can_be_merged'::text))",
+ name: 'idx_merge_requests_on_state_id_and_merge_status'
+ end
+end
diff --git a/db/schema_migrations/20230328020316 b/db/schema_migrations/20230328020316
new file mode 100644
index 00000000000..01eda556b86
--- /dev/null
+++ b/db/schema_migrations/20230328020316
@@ -0,0 +1 @@
+8b5c31f035ede013e589d310fb477a9776b3e3f9554170638bb3b7a299721545 \ No newline at end of file
diff --git a/doc/api/environments.md b/doc/api/environments.md
index 64b64dfbfab..745abdd7ab3 100644
--- a/doc/api/environments.md
+++ b/doc/api/environments.md
@@ -339,7 +339,7 @@ curl --request DELETE --header "PRIVATE-TOKEN: <your_access_token>" "https://git
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/296625) in GitLab 14.2.
It schedules for deletion multiple environments that have already been
-[stopped](../ci/environments/index.md#stop-an-environment) and
+[stopped](../ci/environments/index.md#stopping-an-environment) and
are [in the review app folder](../ci/review_apps/index.md).
The actual deletion is performed after 1 week from the time of execution.
By default, it only deletes environments 30 days or older. You can change this default using the `before` parameter.
@@ -415,7 +415,7 @@ Example response:
## Stop stale environments
-Issue stop request to all environments that were last modified or deployed to before a specified date. Excludes protected environments. Returns `200` if stop request was successful and `400` if the before date is invalid. For details of exactly when the environment is stopped, see [Stop an environment](../ci/environments/index.md#stop-an-environment).
+Issue stop request to all environments that were last modified or deployed to before a specified date. Excludes protected environments. Returns `200` if stop request was successful and `400` if the before date is invalid. For details of exactly when the environment is stopped, see [Stop an environment](../ci/environments/index.md#stopping-an-environment).
```plaintext
POST /projects/:id/environments/stop_stale
diff --git a/doc/ci/environments/img/environment_auto_stop_v13_10.png b/doc/ci/environments/img/environment_auto_stop_v13_10.png
deleted file mode 100644
index 50f268da27f..00000000000
--- a/doc/ci/environments/img/environment_auto_stop_v13_10.png
+++ /dev/null
Binary files differ
diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md
index fe0d71d5f1e..577cbce2943 100644
--- a/doc/ci/environments/index.md
+++ b/doc/ci/environments/index.md
@@ -167,7 +167,7 @@ You cannot rename an environment by using the UI, and the API method was depreca
To achieve the same result as renaming an environment:
-1. [Stop the existing environment](#stop-an-environment-through-the-ui).
+1. [Stop the existing environment](#stop-an-environment-by-using-the-ui).
1. [Delete the existing environment](#delete-an-environment).
1. [Create a new environment](#create-a-static-environment) with the desired name.
@@ -452,28 +452,31 @@ For example:
With GitLab [Route Maps](../review_apps/index.md#route-maps), you can go directly
from source files to public pages in the environment set for Review Apps.
-### Stop an environment
+### Stopping an environment
-When you stop an environment:
+Stopping an environment means its deployments are not accessible on the target server. You must stop
+an environment before it can be deleted.
-- On the **Environments** page, it moves from the list of **Available** environments
- to the list of **Stopped** environments.
-- An [`on_stop` action](../yaml/index.md#environmenton_stop), if defined, is executed.
-
-There are multiple ways to clean up [dynamic environments](#create-a-dynamic-environment):
-
-- If you use [merge request pipelines](../pipelines/merge_request_pipelines.md), GitLab stops an environment [when a merge request is merged or closed](#stop-an-environment-when-a-merge-request-is-merged-or-closed).
-- If you do _NOT_ use [merge request pipelines](../pipelines/merge_request_pipelines.md), GitLab stops an environment [when the associated feature branch is deleted](#stop-an-environment-when-a-branch-is-deleted).
-- If you set [an expiry period to an environment](../yaml/index.md#environmentauto_stop_in), GitLab stops an environment [when it's expired](#stop-an-environment-after-a-certain-time-period).
-
-To stop stale environments, you can [use the API](../../api/environments.md#stop-stale-environments).
+If the environment has an [`on_stop` action](../yaml/index.md#environmenton_stop) defined, it's
+executed to stop the environment.
#### Stop an environment when a branch is deleted
You can configure environments to stop when a branch is deleted.
-The following example shows a `deploy_review` job that calls a `stop_review` job
-to clean up and stop the environment.
+In the following example, a `deploy_review` job calls a `stop_review` job to clean up and stop the
+environment.
+
+- Both jobs must have the same [`rules`](../yaml/index.md#rules)
+ or [`only/except`](../yaml/index.md#only--except) configuration. Otherwise,
+ the `stop_review` job might not be included in all pipelines that include the
+ `deploy_review` job, and you cannot trigger `action: stop` to stop the environment automatically.
+- The job with [`action: stop` might not run](#the-job-with-action-stop-doesnt-run)
+ if it's in a later stage than the job that started the environment.
+- If you can't use [merge request pipelines](../pipelines/merge_request_pipelines.md),
+ set the [`GIT_STRATEGY`](../runners/configure_runners.md#git-strategy) to `none` in the
+ `stop_review` job. Then the [runner](https://docs.gitlab.com/runner/) doesn't
+ try to check out the code after the branch is deleted.
```yaml
deploy_review:
@@ -495,30 +498,13 @@ stop_review:
when: manual
```
-Both jobs must have the same [`rules`](../yaml/index.md#rules)
-or [`only/except`](../yaml/index.md#only--except) configuration. Otherwise,
-the `stop_review` job might not be included in all pipelines that include the
-`deploy_review` job, and you cannot trigger `action: stop` to stop the environment automatically.
-
-The job with [`action: stop` might not run](#the-job-with-action-stop-doesnt-run)
-if it's in a later stage than the job that started the environment.
-
-If you can't use [merge request pipelines](../pipelines/merge_request_pipelines.md),
-set the [`GIT_STRATEGY`](../runners/configure_runners.md#git-strategy) to `none` in the
-`stop_review` job. Then the [runner](https://docs.gitlab.com/runner/) doesn't
-try to check out the code after the branch is deleted.
-
-Read more in the [`.gitlab-ci.yml` reference](../yaml/index.md#environmenton_stop).
-
#### Stop an environment when a merge request is merged or closed
-> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/60885) in GitLab 11.10.
-
-You can configure environments to stop when a merge request is merged or closed.
-This stop trigger is automatically enabled when you use [merge request pipelines](../pipelines/merge_request_pipelines.md).
+When you use the [merge request pipelines](../pipelines/merge_request_pipelines.md) configuration,
+the `stop` trigger is automatically enabled.
-The following example shows a `deploy_review` job that calls a `stop_review` job
-to clean up and stop the environment.
+In the following example, the `deploy_review` job calls a `stop_review` job to clean up and stop
+the environment.
```yaml
deploy_review:
@@ -543,38 +529,35 @@ stop_review:
when: manual
```
-#### Stop an environment when another job is finished
-
-You can set an environment to stop when another job is finished.
-
-In your `.gitlab-ci.yml` file, specify in the [`on_stop`](../yaml/index.md#environmenton_stop)
-keyword the name of the job that stops the environment.
+#### Run a pipeline job when environment is stopped
-The following example shows a `review_app` job that calls a `stop_review_app` job after the first
-job is finished. The `stop_review_app` is triggered based on what is defined under `when`. In this
-case, it is set to `manual`, so it needs a
-[manual action](../jobs/job_control.md#create-a-job-that-must-be-run-manually)
-from the GitLab UI to run.
+You can specify a job to run when an environment is stopped.
-Both jobs must have the same rules or only/except configuration.
-In this example, if the configuration is not identical:
+Prerequisites:
-- The `stop_review_app` job might not be included in all pipelines that include the `review_app` job.
-- It is not possible to trigger the `action: stop` to stop the environment automatically.
+- Both jobs must have the same rules or only/except configuration.
+- The `stop_review_app` job **must** have the following keywords defined:
+ - `when`, defined at either:
+ - [The job level](../yaml/index.md#when).
+ - [In a rules clause](../yaml/index.md#rules). If you use `rules` and `when: manual`, you should
+ also set [`allow_failure: true`](../yaml/index.md#allow_failure) so the pipeline can complete
+ even if the job doesn't run.
+ - `environment:name`
+ - `environment:action`
-Also in the example, `GIT_STRATEGY` is set to `none`. If the
-`stop_review_app` job is [automatically triggered](../environments/index.md#stop-an-environment),
-the runner doesn't try to check out the code after the branch is deleted.
+In your `.gitlab-ci.yml` file, specify in the [`on_stop`](../yaml/index.md#environmenton_stop)
+keyword the name of the job that stops the environment.
-The `stop_review_app` job **must** have the following keywords defined:
+In the following example:
-- `when`, defined at either:
- - [The job level](../yaml/index.md#when).
- - [In a rules clause](../yaml/index.md#rules). If you use `rules` and `when: manual`, you should
- also set [`allow_failure: true`](../yaml/index.md#allow_failure) so the pipeline can complete
- even if the job doesn't run.
-- `environment:name`
-- `environment:action`
+- A `review_app` job calls a `stop_review_app` job after the first job is finished.
+- The `stop_review_app` is triggered based on what is defined under `when`. In this
+ case, it is set to `manual`, so it needs a
+ [manual action](../jobs/job_control.md#create-a-job-that-must-be-run-manually)
+ from the GitLab UI to run.
+- The `GIT_STRATEGY` is set to `none`. If the `stop_review_app` job is
+ [automatically triggered](../environments/index.md#stopping-an-environment),
+ the runner doesn't try to check out the code after the branch is deleted.
```yaml
review_app:
@@ -598,21 +581,23 @@ stop_review_app:
#### Stop an environment after a certain time period
-> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/20956) in GitLab 12.8.
+You can set an environment to stop automatically after a certain time period.
-You can set environments to stop automatically after a certain time period.
+NOTE:
+Due to resource limitations, a background worker for stopping environments runs only once every
+hour. This means that environments may not be stopped after the exact time period specified, but are
+instead stopped when the background worker detects expired environments.
In your `.gitlab-ci.yml` file, specify the [`environment:auto_stop_in`](../yaml/index.md#environmentauto_stop_in)
-keyword. You can specify a human-friendly date as the value, such as `1 hour and 30 minutes` or `1 day`.
+keyword. Specify the time period in natural language, such as `1 hour and 30 minutes` or `1 day`.
After the time period passes, GitLab automatically triggers a job to stop the environment.
-Due to resource limitations, a background worker for stopping environments only runs once
-every hour. This means that environments aren't stopped at the exact timestamp specified, but are
-instead stopped when the hourly cron worker detects expired environments.
+In the following example:
-In the following example, each merge request creates a Review App environment.
-Each push triggers the `review_app` job and an environment named `review/your-branch-name`
-is created or updated. The environment runs until `stop_review_app` is executed:
+- Each commit on a merge request triggers a `review_app` job that deploys the latest change to the
+ environment and resets its expiry period.
+- If the environment is inactive for more than a week, GitLab automatically triggers the
+ `stop_review_app` job to stop the environment.
```yaml
review_app:
@@ -634,13 +619,33 @@ stop_review_app:
when: manual
```
-As long as the merge request is active and keeps getting new commits,
-the Review App doesn't stop. Developers don't need to worry about
-re-initiating Review App.
+##### View an environment's scheduled stop date and time
+
+When a environment has been [scheduled to stop after a specified time period](#stop-an-environment-after-a-certain-time-period),
+you can view its expiration date and time.
+
+To view an environment's expiration date and time:
+
+1. On the top bar, select **Main menu > Projects** and find your project.
+1. On the left sidebar, select **Deployments > Environments**.
+1. Select the name of the environment.
+
+The expiration date and time is displayed in the upper-left corner, next to the environment's name.
+
+##### Override a environment's scheduled stop date and time
+
+When a environment has been [scheduled to stop after a specified time period](#stop-an-environment-after-a-certain-time-period),
+you can override its expiration.
-Because `stop_review_app` is set to `auto_stop_in: 1 week`,
-if a merge request is inactive for more than a week,
-GitLab automatically triggers the `stop_review_app` job to stop the environment.
+To override an environment's expiration:
+
+1. On the top bar, select **Main menu > Projects** and find your project.
+1. On the left sidebar, select **Deployments > Environments**.
+1. Select the deployment name.
+1. in the upper-right corner, select the thumbtack (**{thumbtack}**).
+
+The `auto_stop_in` setting is overridden and the environment remains active until it's stopped
+manually.
#### Stop an environment without running the `on_stop` action
@@ -652,7 +657,7 @@ To stop an environment without running the defined `on_stop` action, execute the
[Stop an environment API](../../api/environments.md#stop-an-environment) with the parameter
`force=true`.
-#### Stop an environment through the UI
+#### Stop an environment by using the UI
NOTE:
To trigger an `on_stop` action and manually stop an environment from the
@@ -671,15 +676,20 @@ To stop an environment in the GitLab UI:
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/22456) in GitLab 14.10 [with a flag](../../administration/feature_flags.md) named `environment_multiple_stop_actions`. Disabled by default.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/358911) in GitLab 15.0. [Feature flag `environment_multiple_stop_actions`](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/86685) removed.
-This feature is useful when you need to perform multiple **parallel** stop actions on an environment.
+To configure multiple **parallel** stop actions on an environment, specify the
+[`on_stop`](../yaml/index.md#environmenton_stop) keyword across multiple
+[deployment jobs](../jobs/index.md#deployment-jobs) for the same `environment`, as defined in the
+`.gitlab-ci.yml` file.
+
+When an environment is stopped, the matching `on_stop` actions from only successful deployment jobs are run in parallel, in no particular order.
-To configure multiple stop actions on an environment, specify the [`on_stop`](../yaml/index.md#environmenton_stop)
-keyword across multiple [deployment jobs](../jobs/index.md#deployment-jobs) for the same `environment`, as defined in the `.gitlab-ci.yml` file.
+In the following example, for the `test` environment there are two deployment jobs:
-When an environment is stopped, the matching `on_stop` actions from *successful deployment jobs* alone are run in parallel in no particular order.
+- `deploy-to-cloud-a`
+- `deploy-to-cloud-b`
-In the following example, for the `test` environment there are two deployment jobs `deploy-to-cloud-a`
-and `deploy-to-cloud-b`.
+When the environment is stopped, the system runs `on_stop` actions `teardown-cloud-a` and
+`teardown-cloud-b` in parallel.
```yaml
deploy-to-cloud-a:
@@ -709,32 +719,6 @@ teardown-cloud-b:
when: manual
```
-When the environment is stopped, the system runs `on_stop` actions
-`teardown-cloud-a` and `teardown-cloud-b` in parallel.
-
-#### View a deployment's scheduled stop time
-
-You can view a deployment's expiration date in the GitLab UI.
-
-1. On the top bar, select **Main menu > Projects** and find your project.
-1. On the left sidebar, select **Deployments > Environments**.
-1. Select the name of the deployment.
-
-In the upper-left corner, next to the environment name, the expiration date is displayed.
-
-#### Override a deployment's scheduled stop time
-
-You can manually override a deployment's expiration date.
-
-1. On the top bar, select **Main menu > Projects** and find your project.
-1. On the left sidebar, select **Deployments > Environments**.
-1. Select the deployment name.
-1. in the upper-right corner, select the thumbtack (**{thumbtack}**).
-
-![Environment auto stop](img/environment_auto_stop_v13_10.png)
-
-The `auto_stop_in` setting is overwritten and the environment remains active until it's stopped manually.
-
### Delete an environment
Delete an environment when you want to remove it and all its deployments.
@@ -742,7 +726,7 @@ Delete an environment when you want to remove it and all its deployments.
Prerequisites:
- You must have at least the Developer role.
-- You must [stop](#stop-an-environment) the environment before it can be deleted.
+- You must [stop](#stopping-an-environment) the environment before it can be deleted.
To delete an environment:
diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md
index 420569ec08b..faeaca1038e 100644
--- a/doc/ci/environments/protected_environments.md
+++ b/doc/ci/environments/protected_environments.md
@@ -124,7 +124,7 @@ access to a protected environment through any of these methods:
If the user also has push or merge access to the branch deployed on production,
they have the following privileges:
-- [Stop an environment](index.md#stop-an-environment).
+- [Stop an environment](index.md#stopping-an-environment).
- [Delete an environment](index.md#delete-an-environment).
- [Create an environment terminal](index.md#web-terminals-deprecated).
diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md
index a912c7f4557..b9c8e9e1e09 100644
--- a/doc/ci/pipelines/index.md
+++ b/doc/ci/pipelines/index.md
@@ -93,7 +93,7 @@ This table lists the refspecs injected for each pipeline type:
The refs `refs/heads/<name>` and `refs/tags/<name>` exist in your
project repository. GitLab generates the special ref `refs/pipelines/<id>` during a
running pipeline job. This ref can be created even after the associated branch or tag has been
-deleted. It's therefore useful in some features such as [automatically stopping an environment](../environments/index.md#stop-an-environment),
+deleted. It's therefore useful in some features such as [automatically stopping an environment](../environments/index.md#stopping-an-environment),
and [merge trains](../pipelines/merge_trains.md)
that might run pipelines after branch deletion.
diff --git a/doc/ci/review_apps/index.md b/doc/ci/review_apps/index.md
index 9e69ab1ccb8..fb0bf7b2ae1 100644
--- a/doc/ci/review_apps/index.md
+++ b/doc/ci/review_apps/index.md
@@ -59,7 +59,7 @@ The process of configuring review apps is as follows:
1. Set up a job in `.gitlab-ci.yml` that uses the [predefined CI/CD variable](../variables/index.md) `${CI_COMMIT_REF_SLUG}`
to create dynamic environments and restrict it to run only on branches.
Alternatively, you can get a YAML template for this job by [enabling review apps](#enable-review-app-button) for your project.
-1. Optionally, set a job that [manually stops](../environments/index.md#stop-an-environment) the review apps.
+1. Optionally, set a job that [manually stops](../environments/index.md#stopping-an-environment) the review apps.
### Enable review app button
diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md
index 45dc1a7fe37..b7b7bed4d2d 100644
--- a/doc/ci/variables/predefined_variables.md
+++ b/doc/ci/variables/predefined_variables.md
@@ -27,6 +27,7 @@ as it can cause the pipeline to behave unexpectedly.
| `CHAT_USER_ID` | 14.4 | all | The chat service's user ID of the user who triggered the [ChatOps](../chatops/index.md) command. |
| `CI` | all | 0.4 | Available for all jobs executed in CI/CD. `true` when available. |
| `CI_API_V4_URL` | 11.7 | all | The GitLab API v4 root URL. |
+| `CI_API_GRAPHQL_URL` | 15.11 | all | The GitLab API GraphQL root URL. |
| `CI_BUILDS_DIR` | all | 11.10 | The top-level directory where builds are executed. |
| `CI_COMMIT_AUTHOR` | 13.11 | all | The author of the commit in `Name <email>` format. |
| `CI_COMMIT_BEFORE_SHA` | 11.2 | all | The previous latest commit present on a branch or tag. Is always `0000000000000000000000000000000000000000` in merge request pipelines and for the first commit in pipelines for branches or tags. |
diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md
index 0bbd3bf37b4..01173f43c2e 100644
--- a/doc/ci/yaml/index.md
+++ b/doc/ci/yaml/index.md
@@ -1734,7 +1734,7 @@ Use the `action` keyword to specify how the job interacts with the environment.
|:----------|:----------------|
| `start` | Default value. Indicates that the job starts the environment. The deployment is created after the job starts. |
| `prepare` | Indicates that the job is only preparing the environment. It does not trigger deployments. [Read more about preparing environments](../environments/index.md#access-an-environment-for-preparation-or-verification-purposes). |
-| `stop` | Indicates that the job stops an environment. [Read more about stopping an environment](../environments/index.md#stop-an-environment). |
+| `stop` | Indicates that the job stops an environment. [Read more about stopping an environment](../environments/index.md#stopping-an-environment). |
| `verify` | Indicates that the job is only verifying the environment. It does not trigger deployments. [Read more about verifying environments](../environments/index.md#access-an-environment-for-preparation-or-verification-purposes). |
| `access` | Indicates that the job is only accessing the environment. It does not trigger deployments. [Read more about accessing environments](../environments/index.md#access-an-environment-for-preparation-or-verification-purposes). |
diff --git a/doc/development/documentation/styleguide/index.md b/doc/development/documentation/styleguide/index.md
index baa46f7bfc2..e66d095a7a4 100644
--- a/doc/development/documentation/styleguide/index.md
+++ b/doc/development/documentation/styleguide/index.md
@@ -718,6 +718,15 @@ This is overridden by the [documentation-specific punctuation rules](#punctuatio
Links help the docs adhere to the
[single source of truth](#documentation-is-the-single-source-of-truth-ssot) principle.
+However, you should avoid putting too many links on any page. Too many links can hinder readability.
+
+- Do not duplicate links on the same page. For example, on **Page A**, do not link to **Page B** multiple times.
+- Avoid multiple links in a single paragraph.
+- Avoid multiple links in a single task.
+- On any one page, try not to use more than 15 links to other pages.
+- Consider using [Related topics](../topic_types/index.md#related-topics) to reduce links that interrupt the flow of a task.
+- Try to avoid anchor links to sections on the same page. Let users rely on the right navigation instead.
+
### Links within the same repository
To link to another page in the same repository,
diff --git a/doc/development/testing_guide/review_apps.md b/doc/development/testing_guide/review_apps.md
index 4e968cea3a0..1e5ee9f3003 100644
--- a/doc/development/testing_guide/review_apps.md
+++ b/doc/development/testing_guide/review_apps.md
@@ -227,7 +227,7 @@ Review apps are automatically stopped 2 days after the last deployment thanks to
the [Environment auto-stop](../../ci/environments/index.md#stop-an-environment-after-a-certain-time-period) feature.
If you need your review app to stay up for a longer time, you can
-[pin its environment](../../ci/environments/index.md#override-a-deployments-scheduled-stop-time) or retry the
+[pin its environment](../../ci/environments/index.md#override-a-environments-scheduled-stop-date-and-time) or retry the
`review-deploy` job to update the "latest deployed at" time.
The `review-cleanup` job that automatically runs in scheduled
diff --git a/doc/topics/autodevops/cloud_deployments/auto_devops_with_eks.md b/doc/topics/autodevops/cloud_deployments/auto_devops_with_eks.md
index f322ebd0c9c..32a47bb790b 100644
--- a/doc/topics/autodevops/cloud_deployments/auto_devops_with_eks.md
+++ b/doc/topics/autodevops/cloud_deployments/auto_devops_with_eks.md
@@ -217,7 +217,7 @@ you to common environment tasks:
- **Re-deploy to environment** (**{repeat}**) - For more information, see
[Retrying and rolling back](../../../ci/environments/index.md#retry-or-roll-back-a-deployment)
- **Stop environment** (**{stop}**) - For more information, see
- [Stopping an environment](../../../ci/environments/index.md#stop-an-environment)
+ [Stopping an environment](../../../ci/environments/index.md#stopping-an-environment)
GitLab displays the [deploy board](../../../user/project/deploy_boards.md) below the
environment's information, with squares representing pods in your
diff --git a/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md b/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md
index 7f608d3951c..1a03a66d17a 100644
--- a/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md
+++ b/doc/topics/autodevops/cloud_deployments/auto_devops_with_gke.md
@@ -221,7 +221,7 @@ you to common environment tasks:
- **Re-deploy to environment** (**{repeat}**) - For more information, see
[Retrying and rolling back](../../../ci/environments/index.md#retry-or-roll-back-a-deployment)
- **Stop environment** (**{stop}**) - For more information, see
- [Stopping an environment](../../../ci/environments/index.md#stop-an-environment)
+ [Stopping an environment](../../../ci/environments/index.md#stopping-an-environment)
GitLab displays the [deploy board](../../../user/project/deploy_boards.md) below the
environment's information, with squares representing pods in your
diff --git a/doc/user/application_security/secret_detection/post_processing.md b/doc/user/application_security/secret_detection/post_processing.md
index 539d9e6fd88..6d29a488ca2 100644
--- a/doc/user/application_security/secret_detection/post_processing.md
+++ b/doc/user/application_security/secret_detection/post_processing.md
@@ -32,10 +32,11 @@ GitLab supports post-processing for the following vendors and secrets:
## Feature availability
+> [Enabled for non-default branches](https://gitlab.com/gitlab-org/gitlab/-/issues/299212) in GitLab 15.11.
+
Credentials are only post-processed when Secret Detection finds them:
- In public projects, because publicly exposed credentials pose an increased threat. Expansion to private projects is considered in [issue 391379](https://gitlab.com/gitlab-org/gitlab/-/issues/391379).
-- On the project [default branch](../../project/repository/branches/default.md), for technical reasons. Expansion to all branches is tracked in [issue 299212](https://gitlab.com/gitlab-org/gitlab/-/issues/299212).
- In projects with GitLab Ultimate, for technical reasons. Expansion to all tiers is tracked in [issue 391763](https://gitlab.com/gitlab-org/gitlab/-/issues/391763).
## High-level architecture
@@ -45,8 +46,9 @@ This diagram describes how a post-processing hook revokes a secret within the Gi
```mermaid
sequenceDiagram
autonumber
- GitLab Rails->>+Sidekiq: gl-secret-detection-report.json
- Sidekiq-->+Sidekiq: StoreSecurityReportsWorker
+ GitLab Rails-->+GitLab Rails: gl-secret-detection-report.json
+ GitLab Rails->>+Sidekiq: StoreScansService
+ Sidekiq-->+Sidekiq: ScanSecurityReportSecretsWorker
Sidekiq-->+Token Revocation API: GET revocable keys types
Token Revocation API-->>-Sidekiq: OK
Sidekiq->>+Token Revocation API: POST revoke revocable keys
@@ -55,14 +57,13 @@ sequenceDiagram
Receiver Service-->>+Token Revocation API: ACCEPTED
```
-1. A pipeline with a Secret Detection job completes on the project's default branch, producing a scan
- report (**1**).
-1. The report is processed (**2**) by an asynchronous worker, which communicates with an externally
- deployed HTTP service (**3** and **4**) to determine which kinds of secrets can be automatically
- revoked.
-1. The worker sends (**5** and **6**) the list of detected secrets which the Token Revocation API is able to
+1. A pipeline with a Secret Detection job completes, producing a scan report (**1**).
+1. The report is processed (**2**) by a service class, which schedules an asychronous worker if token revocation is possible.
+1. The asynchronous worker (**3**) communicates with an externally deployed HTTP service
+ (**4** and **5**) to determine which kinds of secrets can be automatically revoked.
+1. The worker sends (**6** and **7**) the list of detected secrets which the Token Revocation API is able to
revoke.
-1. The Token Revocation API sends (**7** and **8**) each revocable token to their respective vendor's [receiver service](#integrate-your-cloud-provider-service-with-gitlabcom).
+1. The Token Revocation API sends (**8** and **9**) each revocable token to their respective vendor's [receiver service](#integrate-your-cloud-provider-service-with-gitlabcom).
See the [Token Revocation API](../../../development/sec/token_revocation_api.md) documentation for more
information.
diff --git a/doc/user/profile/account/create_accounts.md b/doc/user/profile/account/create_accounts.md
index 08d23902095..f405dc42f46 100644
--- a/doc/user/profile/account/create_accounts.md
+++ b/doc/user/profile/account/create_accounts.md
@@ -36,9 +36,27 @@ To create a user manually:
1. On the top bar, select **Main menu > Admin**.
1. On the left sidebar, select **Overview > Users** (`/admin/users`).
1. Select **New user**.
-1. Complete the fields.
+1. Complete the required fields, such as name, username, and email.
1. Select **Create user**.
+A reset link is sent to the user's email and they are forced to set their
+password on first sign in.
+
+To set a user's password without relying on the email confirmation, after you
+create a user following the previous steps:
+
+1. Select the user.
+1. Select **Edit**.
+1. Complete the password and password confirmation fields.
+1. Select **Save changes**.
+
+The user can now sign in with the new username and password, and they are asked
+to change the password you set up for them.
+
+NOTE:
+If you wanted to create a test user, you could follow the previous steps
+by providing a fake email and using the same password in the final confirmation.
+
## Create users through authentication integrations
Users are:
diff --git a/doc/user/profile/achievements.md b/doc/user/profile/achievements.md
new file mode 100644
index 00000000000..96940eec766
--- /dev/null
+++ b/doc/user/profile/achievements.md
@@ -0,0 +1,195 @@
+---
+stage: Data Stores
+group: Tenant Scale
+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
+---
+
+# Achievements (Alpha) **(FREE)**
+
+> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/113156) in GitLab 15.10 [with a flag](../../administration/feature_flags.md) named `achievements`. Disabled by default.
+
+FLAG:
+On self-managed GitLab, by default this feature is not available. To make it available,
+ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `achievements`.
+The feature is not ready for production use.
+
+Achievements are a way to reward users for their activity on GitLab.
+As a namespace maintainer or owner, you can create custom achievements for specific contributions, which you can award to or revoke from users based on your criteria.
+
+As a user, you can collect achievements to highlight your contributions to different projects or groups on your profile.
+An achievement consists of a name, a description, and an avatar.
+
+![Achievements on user profile page](img/user_profile_achievements_v15_11.png)
+
+This feature is in Alpha.
+For more information about planned work, see [epic 9429](https://gitlab.com/groups/gitlab-org/-/epics/9429).
+Tell us about your use cases by leaving comments in the epic.
+
+## Types of achievement
+
+Programmatically, there is only one way to create, award, revoke, or delete achievements.
+
+Practically, you can differentiate between achievements that are awarded:
+
+- Once and irrevocable. For example, a "First contribution merged" achievement.
+- Once and revocable. For example, a "Core team member" achievement.
+- Multiple times. For example, a "Contributor of the month" achievement.
+
+## View a user's achievements
+
+You can view a user's achievements on their profile page.
+
+Prerequisites:
+
+- The user profile must be public.
+- You must be a member of the namespace awarding the achievement, or the namespace must be public.
+
+To view a user's achievements:
+
+1. Go to the user's profile page.
+1. Below the user's avatar, see their achievements.
+1. To view details about an achievement, hover over it.
+ It displays the following information:
+
+ - Name of the achievement
+ - Description of the achievement
+ - Date when the achievement was awarded to the user
+ - Namespace that awarded the achievement
+
+To retrieve a list of a user's achievements, query the [`user` GraphQL type](../../api/graphql/reference/index.md#user).
+
+```graphql
+query {
+ user(username: "<username>") {
+ userAchievements {
+ nodes {
+ achievement {
+ name
+ description
+ avatarUrl
+ namespace {
+ fullPath
+ name
+ }
+ }
+ }
+ }
+ }
+}
+```
+
+## Create an achievement
+
+You can create custom achievements to award for specific contributions.
+
+Prerequisites:
+
+- You must have the Maintainer or Owner role for the namespace.
+
+To create an achievement, call the [`achievementsCreate` GraphQL mutation](../../api/graphql/reference/index.md#mutationachievementscreate).
+
+```graphql
+mutation achievementsCreate($file: Upload!) {
+ achievementsCreate(
+ input: {
+ namespaceId: "gid://gitlab/Namespace/<namespace id>",
+ name: "<name>",
+ description: "<description>",
+ avatar: $file}
+ ) {
+ errors
+ achievement {
+ id
+ name
+ description
+ avatarUrl
+ }
+ }
+}
+```
+
+## Award an achievement
+
+You can award an achievement to a user to recognize their contributions.
+
+Prerequisites:
+
+- You must have the Maintainer or Owner role for the namespace.
+
+To award an achievement to a user, call the [`achievementsAward` GraphQL mutation](../../api/graphql/reference/index.md#mutationachievementsaward).
+
+```graphql
+mutation {
+ achievementsAward(input: {
+ achievementId: "gid://gitlab/Achievements::Achievement/<achievement id>",
+ userId: "gid://gitlab/User/<user id>" }) {
+ userAchievement {
+ id
+ achievement {
+ id
+ name
+ }
+ user {
+ id
+ username
+ }
+ }
+ errors
+ }
+}
+```
+
+## Revoke an achievement
+
+You can revoke a user's achievement if you consider the user no longer meets the awarding criteria.
+
+Prerequisites:
+
+- You must have the Maintainer or Owner role for the namespace.
+
+To revoke an achievement, call the [`achievementsRevoke` GraphQL mutation](../../api/graphql/reference/index.md#mutationachievementsrevoke).
+
+```graphql
+mutation {
+ achievementsRevoke(input: {
+ userAchievementId: "gid://gitlab/Achievements::UserAchievement/<user achievement id>" }) {
+ userAchievement {
+ id
+ achievement {
+ id
+ name
+ }
+ user {
+ id
+ username
+ }
+ revokedAt
+ }
+ errors
+ }
+}
+```
+
+## Delete an achievement
+
+If you consider you no longer need an achievement, you can delete it.
+This will delete all related awarded and revoked instances of the achievement.
+
+Prerequisites:
+
+- You must have the Maintainer or Owner role for the namespace.
+
+To delete an achievement, call the [`achievementsDelete` GraphQL mutation](../../api/graphql/reference/index.md#mutationachievementsdelete).
+
+```graphql
+mutation {
+ achievementsDelete(input: {
+ achievementId: "gid://gitlab/Achievements::Achievement/<achievement id>" }) {
+ achievement {
+ id
+ name
+ }
+ errors
+ }
+}
+```
diff --git a/doc/user/profile/img/user_profile_achievements_v15_11.png b/doc/user/profile/img/user_profile_achievements_v15_11.png
new file mode 100644
index 00000000000..28c5661dd54
--- /dev/null
+++ b/doc/user/profile/img/user_profile_achievements_v15_11.png
Binary files differ
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index 123dd25200d..abc8ec296e1 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -4762,6 +4762,9 @@ msgstr ""
msgid "Analytics|Add to Dashboard"
msgstr ""
+msgid "Analytics|An error occurred while loading data"
+msgstr ""
+
msgid "Analytics|An error occurred while loading the %{visualizationTitle} visualization."
msgstr ""
@@ -13981,6 +13984,9 @@ msgstr ""
msgid "DeletionSettings|Owners and administrators can delete projects."
msgstr ""
+msgid "DeletionSettings|Period that deleted groups and projects will remain restorable for. Personal projects are always deleted immediately."
+msgstr ""
+
msgid "DeletionSettings|Retention period that deleted groups and projects will remain restorable. Personal projects are always deleted immediately. Some groups can opt-out their projects."
msgstr ""
diff --git a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
index 43701a6b740..daf77b7b67c 100644
--- a/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
+++ b/qa/qa/specs/features/api/1_manage/migration/gitlab_migration_project_spec.rb
@@ -6,7 +6,8 @@ module QA
include_context 'with gitlab project migration'
# this spec is used as a sanity test for gitlab migration because it can run outside of orchestrated setup
- context 'with import within same instance', :reliable, orchestrated: false, import: false do
+ # TODO: `:reliable` should be added back once https://gitlab.com/gitlab-org/gitlab/-/issues/403001 is resolved
+ context 'with import within same instance', orchestrated: false, import: false do
let!(:source_project_with_readme) { true }
let!(:source_gitlab_address) { Runtime::Scenario.gitlab_address }
let!(:source_admin_api_client) { admin_api_client }
diff --git a/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js b/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js
index 5887670a58d..ea7dabf34c9 100644
--- a/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js
+++ b/spec/frontend/vue_merge_request_widget/components/widget/widget_spec.js
@@ -287,6 +287,21 @@ describe('~/vue_merge_request_widget/components/widget/widget.vue', () => {
expect(findExpandedSection().text()).toBe('More complex content');
});
+ it('emits a toggle even when button is toggled', async () => {
+ createComponent({
+ propsData: {
+ isCollapsible: true,
+ },
+ slots: {
+ content: '<b>More complex content</b>',
+ },
+ });
+
+ expect(findExpandedSection().exists()).toBe(false);
+ findToggleButton().vm.$emit('click');
+ expect(wrapper.emitted('toggle')).toEqual([[{ expanded: true }]]);
+ });
+
it('does not display the toggle button if isCollapsible is false', () => {
createComponent({
propsData: {
diff --git a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
index 9941abbfaea..f115ec2d6ca 100644
--- a/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
+++ b/spec/frontend/vue_shared/components/filtered_search_bar/tokens/base_token_spec.js
@@ -18,6 +18,7 @@ import {
OPTIONS_NONE_ANY,
OPERATOR_IS,
OPERATOR_NOT,
+ OPERATOR_OR,
} from '~/vue_shared/components/filtered_search_bar/constants';
import {
getRecentlyUsedSuggestions,
@@ -300,6 +301,7 @@ describe('BaseToken', () => {
operator | shouldRenderFilteredSearchSuggestion
${OPERATOR_IS} | ${true}
${OPERATOR_NOT} | ${false}
+ ${OPERATOR_OR} | ${false}
`('when operator is $operator', ({ shouldRenderFilteredSearchSuggestion, operator }) => {
beforeEach(() => {
const props = {
diff --git a/spec/lib/gitlab/ci/variables/builder_spec.rb b/spec/lib/gitlab/ci/variables/builder_spec.rb
index 2c6f0320242..914159c0984 100644
--- a/spec/lib/gitlab/ci/variables/builder_spec.rb
+++ b/spec/lib/gitlab/ci/variables/builder_spec.rb
@@ -101,6 +101,8 @@ RSpec.describe Gitlab::Ci::Variables::Builder, :clean_gitlab_redis_cache, featur
value: project.pages_url },
{ key: 'CI_API_V4_URL',
value: API::Helpers::Version.new('v4').root_url },
+ { key: 'CI_API_GRAPHQL_URL',
+ value: Gitlab::Routing.url_helpers.api_graphql_url },
{ key: 'CI_TEMPLATE_REGISTRY_HOST',
value: template_registry_host },
{ key: 'CI_PIPELINE_IID',
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index e93b5733d1a..880e1d3bcee 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -2788,6 +2788,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
public: true,
masked: false },
{ key: 'CI_API_V4_URL', value: 'http://localhost/api/v4', public: true, masked: false },
+ { key: 'CI_API_GRAPHQL_URL', value: 'http://localhost/api/graphql', public: true, masked: false },
{ key: 'CI_TEMPLATE_REGISTRY_HOST', value: template_registry_host, public: true, masked: false },
{ key: 'CI_PIPELINE_IID', value: pipeline.iid.to_s, public: true, masked: false },
{ key: 'CI_PIPELINE_SOURCE', value: pipeline.source, public: true, masked: false },
diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb
index 11adbf161ee..1348ca4f3b3 100644
--- a/spec/models/project_spec.rb
+++ b/spec/models/project_spec.rb
@@ -5807,8 +5807,19 @@ RSpec.describe Project, factory_default: :keep, feature_category: :projects do
let_it_be(:project) { create(:project) }
it 'exposes API v4 URL' do
- expect(project.api_variables.first[:key]).to eq 'CI_API_V4_URL'
- expect(project.api_variables.first[:value]).to include '/api/v4'
+ v4_variable = project.api_variables.find { |variable| variable[:key] == "CI_API_V4_URL" }
+
+ expect(v4_variable).not_to be_nil
+ expect(v4_variable[:key]).to eq 'CI_API_V4_URL'
+ expect(v4_variable[:value]).to end_with '/api/v4'
+ end
+
+ it 'exposes API GraphQL URL' do
+ graphql_variable = project.api_variables.find { |variable| variable[:key] == "CI_API_GRAPHQL_URL" }
+
+ expect(graphql_variable).not_to be_nil
+ expect(graphql_variable[:key]).to eq 'CI_API_GRAPHQL_URL'
+ expect(graphql_variable[:value]).to end_with '/api/graphql'
end
it 'contains a URL variable for every supported API version' do
@@ -5823,7 +5834,7 @@ RSpec.describe Project, factory_default: :keep, feature_category: :projects do
end
expect(project.api_variables.map { |variable| variable[:key] })
- .to contain_exactly(*required_variables)
+ .to include(*required_variables)
end
end