diff options
Diffstat (limited to 'doc/ci/environments')
-rw-r--r-- | doc/ci/environments/deployment_safety.md | 72 | ||||
-rw-r--r-- | doc/ci/environments/incremental_rollouts.md | 14 | ||||
-rw-r--r-- | doc/ci/environments/index.md | 107 | ||||
-rw-r--r-- | doc/ci/environments/protected_environments.md | 14 |
4 files changed, 132 insertions, 75 deletions
diff --git a/doc/ci/environments/deployment_safety.md b/doc/ci/environments/deployment_safety.md index 95419e58d36..4dac076ffb7 100644 --- a/doc/ci/environments/deployment_safety.md +++ b/doc/ci/environments/deployment_safety.md @@ -14,6 +14,9 @@ You can: - [Restrict write-access to a critical environment](#restrict-write-access-to-a-critical-environment) - [Prevent deployments during deploy freeze windows](#prevent-deployments-during-deploy-freeze-windows) +- [Set appropriate roles to your project](#setting-appropriate-roles-to-your-project) +- [Protect production secrets](#protect-production-secrets) +- [Separate project for deployments](#separate-project-for-deployments) If you are using a continuous deployment workflow and want to ensure that concurrent deployments to the same environment do not happen, you should enable the following options: @@ -38,8 +41,8 @@ For example: ```yaml deploy: - script: deploy-to-prod - resource_group: prod + script: deploy-to-prod + resource_group: prod ``` Example of a problematic pipeline flow **before** using the resource group: @@ -89,6 +92,56 @@ If you want to prevent deployments for a particular period, for example during a vacation period when most employees are out, you can set up a [Deploy Freeze](../../user/project/releases/index.md#prevent-unintentional-releases-by-setting-a-deploy-freeze). During a deploy freeze period, no deployment can be executed. This is helpful to ensure that deployments do not happen unexpectedly. + +## Setting appropriate roles to your project + +GitLab supports several different roles that can be assigned to your project members. See +[Project members permissions](../../user/permissions.md#project-members-permissions) +for an explanation of these roles and the permissions of each. + +<div class="video-fallback"> + See the video: <a href="https://www.youtube.com/watch?v=Mq3C1KveDc0">How to secure your CD pipelines</a>. +</div> +<figure class="video-container"> + <iframe src="https://www.youtube.com/embed/Mq3C1KveDc0" frameborder="0" allowfullscreen="true"> </iframe> +</figure> + +## Protect production secrets + +Production secrets are needed to deploy successfully. For example, when deploying to the cloud, +cloud providers require these secrets to connect to their services. In the project settings, you can +define and protect environment variables for these secrets. [Protected variables](../variables/README.md#protect-a-custom-variable) +are only passed to pipelines running on [protected branches](../../user/project/protected_branches.md) +or [protected tags](../../user/project/protected_tags.md). +The other pipelines don't get the protected variable. You can also +[scope variables to specific environments](../variables/where_variables_can_be_used.md#variables-with-an-environment-scope). +We recommend that you use protected variables on protected environments to make sure that the +secrets aren't exposed unintentionally. You can also define production secrets on the +[runner side](../runners/README.md#prevent-runners-from-revealing-sensitive-information). +This prevents other maintainers from reading the secrets and makes sure that the runner only runs on +protected branches. + +For more information, see [pipeline security](../pipelines/index.md#pipeline-security-on-protected-branches). + +## Separate project for deployments + +All project maintainers have access to production secrets. If you need to limit the number of users +that can deploy to a production environment, you can create a separate project and configure a new +permission model that isolates the CD permissions from the original project and prevents the +original project's maintainers from accessing the production secret and CD configuration. You can +connect the CD project to your development projects by using [multi-project pipelines](../multi_project_pipelines.md). + +## Protect `gitlab-ci.yml` from change + +A `.gitlab-ci.yml` may contain rules to deploy an application to the production server. This +deployment usually runs automatically after pushing a merge request. To prevent developers from +changing the `gitlab-ci.yml`, you can define it in a different repository. The configuration can +reference a file in another project with a completely different set of permissions (similar to +[separating a project for deployments](#separate-project-for-deployments)). +In this scenario, the `gitlab-ci.yml` is publicly accessible, but can only be edited by users with +appropriate permissions in the other project. + +For more information, see [Custom CI configuration path](../pipelines/settings.md#custom-ci-configuration-path). ## Troubleshooting @@ -99,14 +152,13 @@ If you have multiple jobs for the same environment (including non-deployment job ```yaml build:service-a: - environment: - name: production - + environment: + name: production + build:service-b: - environment: - name: production + environment: + name: production ``` -The [Skip outdated deployment jobs](../pipelines/settings.md#skip-outdated-deployment-jobs) might not work well with this configuration, and will need to be disabled. - -There is a [plan to introduce a new annotation for environments](https://gitlab.com/gitlab-org/gitlab/-/issues/208655) to address this issue. +The [Skip outdated deployment jobs](../pipelines/settings.md#skip-outdated-deployment-jobs) might +not work well with this configuration, and must be disabled. diff --git a/doc/ci/environments/incremental_rollouts.md b/doc/ci/environments/incremental_rollouts.md index 81acc3a36e9..15eb4d2c526 100644 --- a/doc/ci/environments/incremental_rollouts.md +++ b/doc/ci/environments/incremental_rollouts.md @@ -44,8 +44,8 @@ allows more control over the this feature. The steps in an incremental rollout d number of pods that are defined for the deployment, which are configured when the Kubernetes cluster is created. -For example, if your application has 10 pods and a 10% rollout job is run, the new instance of the -application will be deployed to a single pod while the remaining 9 will present the previous instance. +For example, if your application has 10 pods and a 10% rollout job runs, the new instance of the +application is deployed to a single pod while the remaining nine are present the previous instance. First we [define the template as manual](https://gitlab.com/gl-release/incremental-rollout-example/blob/master/.gitlab-ci.yml#L100-103): @@ -65,7 +65,7 @@ rollout 10%: ROLLOUT_PERCENTAGE: 10 ``` -When the jobs are built, a **play** button will appear next to the job's name. Click the **play** button +When the jobs are built, a **play** button appears next to the job's name. Click the **play** button to release each stage of pods. You can also rollback by running a lower percentage job. Once 100% is reached, you cannot roll back using this method. It is still possible to roll back by redeploying the old version using the **Rollback** button on the environment page. @@ -79,13 +79,13 @@ available, demonstrating manually triggered incremental rollouts. > [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7545) in GitLab 11.4. -Timed rollouts behave in the same way as manual rollouts, except that each job is defined with a delay -in minutes before it will deploy. Clicking on the job will reveal the countdown. +Timed rollouts behave in the same way as manual rollouts, except that each job is defined with a +delay in minutes before it deploys. Clicking the job reveals the countdown. ![Timed rollout](img/timed_rollout_v12_7.png) -It is possible to combine this functionality with manual incremental rollouts so that the job will -countdown and then deploy. +It is possible to combine this functionality with manual incremental rollouts so that the job +counts down and then deploys. First we [define the template as timed](https://gitlab.com/gl-release/timed-rollout-example/blob/master/.gitlab-ci.yml#L86-89): diff --git a/doc/ci/environments/index.md b/doc/ci/environments/index.md index 10513e0797e..7bf30ef1b95 100644 --- a/doc/ci/environments/index.md +++ b/doc/ci/environments/index.md @@ -28,7 +28,7 @@ This helps find bugs in your software, and also in the deployment process as wel GitLab CI/CD is capable of not only testing or building your projects, but also deploying them in your infrastructure, with the added benefit of giving you a -way to track your deployments. In other words, you will always know what is +way to track your deployments. In other words, you always know what is currently being deployed or has been deployed on your servers. It's important to know that: @@ -102,12 +102,12 @@ We have defined three [stages](../yaml/README.md#stages): - `build` - `deploy` -The jobs assigned to these stages will run in this order. If any job fails, then -the pipeline fails and jobs that are assigned to the next stage won't run. +The jobs assigned to these stages run in this order. If any job fails, then +the pipeline fails and jobs that are assigned to the next stage don't run. In our case: -- The `test` job will run first. +- The `test` job runs first. - Then the `build` job. - Lastly the `deploy_staging` job. @@ -127,13 +127,13 @@ numbers, spaces, and `-`, `_`, `/`, `{`, `}`, or `.`. Also, it must not start no In summary, with the above `.gitlab-ci.yml` we have achieved the following: -- All branches will run the `test` and `build` jobs. -- The `deploy_staging` job will run [only](../yaml/README.md#onlyexcept-basic) on the `master` +- All branches run the `test` and `build` jobs. +- The `deploy_staging` job runs [only](../yaml/README.md#onlyexcept-basic) on the `master` branch, which means all merge requests that are created from branches don't get deployed to the staging server. -- When a merge request is merged, all jobs will run and the `deploy_staging` - job will deploy our code to a staging server while the deployment - will be recorded in an environment named `staging`. +- When a merge request is merged, all jobs run and the `deploy_staging` + job deploys our code to a staging server while the deployment + is recorded in an environment named `staging`. #### Environment variables and runners @@ -147,8 +147,8 @@ two forms: If you change the name of an existing environment, the: -- `$CI_ENVIRONMENT_NAME` variable will be updated with the new environment name. -- `$CI_ENVIRONMENT_SLUG` variable will remain unchanged to prevent unintended side +- `$CI_ENVIRONMENT_NAME` variable is updated with the new environment name. +- `$CI_ENVIRONMENT_SLUG` variable remains unchanged to prevent unintended side effects. Starting with GitLab 9.3, the environment URL is exposed to the runner via @@ -214,13 +214,13 @@ It parses the `deploy.env` report artifact, registers a list of variables as run uses it for expanding `environment:url: $DYNAMIC_ENVIRONMENT_URL` and sets it to the environment URL. You can also specify a static part of the URL at `environment:url:`, such as `https://$DYNAMIC_ENVIRONMENT_URL`. If the value of `DYNAMIC_ENVIRONMENT_URL` is -`example.com`, the final result will be `https://example.com`. +`example.com`, the final result is `https://example.com`. The assigned URL for the `review/your-branch-name` environment is [visible in the UI](#using-the-environment-url). Note the following: -- `stop_review` doesn't generate a dotenv report artifact, so it won't recognize the +- `stop_review` doesn't generate a dotenv report artifact, so it doesn't recognize the `DYNAMIC_ENVIRONMENT_URL` variable. Therefore you shouldn't set `environment:url:` in the `stop_review` job. - If the environment URL isn't valid (for example, the URL is malformed), the system doesn't update @@ -280,7 +280,7 @@ deploy_prod: The `when: manual` action: - Exposes a "play" button in the GitLab UI for that job. -- Means the `deploy_prod` job will only be triggered when the "play" button is clicked. +- Means the `deploy_prod` job is only triggered when the "play" button is clicked. You can find the "play" button in the pipelines, environments, deployments, and jobs views. @@ -330,7 +330,7 @@ For more information, see [Where variables can be used](../variables/where_varia Runners expose various [environment variables](../variables/README.md) when a job runs, so you can use them as environment names. -In the following example, the job will deploy to all branches except `master`: +In the following example, the job deploys to all branches except `master`: ```yaml deploy_review: @@ -363,7 +363,7 @@ For the value of: may contain a `/` or other characters that would be invalid in a domain name or URL, so we use `$CI_ENVIRONMENT_SLUG` to guarantee that we get a valid URL. - For example, given a `$CI_COMMIT_REF_NAME` of `100-Do-The-Thing`, the URL will be something + For example, given a `$CI_COMMIT_REF_NAME` of `100-Do-The-Thing`, the URL is something like `https://100-do-the-4f99a2.example.com`. Again, the way you set up the web server to serve these requests is based on your setup. @@ -396,7 +396,7 @@ The following configuration options are supported: - [`namespace`](https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/) -In the following example, the job will deploy your application to the +In the following example, the job deploys your application to the `production` Kubernetes namespace. ```yaml @@ -414,7 +414,7 @@ deploy: ``` When deploying to a Kubernetes cluster using the GitLab Kubernetes integration, -information about the cluster and namespace will be displayed above the job +information about the cluster and namespace is displayed above the job trace on the deployment job page: ![Deployment cluster information](../img/environments_deployment_cluster_v12_8.png) @@ -502,7 +502,7 @@ deploy_prod: A more realistic example would also include copying files to a location where a webserver (for example, NGINX) could then access and serve them. -The example below will copy the `public` directory to `/srv/nginx/$CI_COMMIT_REF_SLUG/public`: +The example below copies the `public` directory to `/srv/nginx/$CI_COMMIT_REF_SLUG/public`: ```yaml review_app: @@ -514,7 +514,7 @@ review_app: url: https://$CI_COMMIT_REF_SLUG.example.com ``` -This example requires that NGINX and GitLab Runner are set up on the server this job will run on. +This example requires that NGINX and GitLab Runner are set up on the server this job runs on. See the [limitations](#limitations) section for some edge cases regarding the naming of your branches and Review Apps. @@ -526,10 +526,10 @@ The complete example provides the following workflow to developers: - Push the branch to GitLab. - Create a merge request. -Behind the scenes, the runner will: +Behind the scenes, the runner: -- Pick up the changes and start running the jobs. -- Run the jobs sequentially as defined in `stages`: +- Picks up the changes and starts running the jobs. +- Runs the jobs sequentially as defined in `stages`: - First, run the tests. - If the tests succeed, build the app. - If the build succeeds, the app is deployed to an environment with a name specific to the @@ -561,7 +561,7 @@ A list of environments and deployment statuses is available on each project's ** For example: -![Environment view](../img/environments_available.png) +![Environment view](../img/environments_available_13_7.png) This example shows: @@ -571,10 +571,16 @@ This example shows: - The commit information of the last deployment, such as who committed it, to what branch, and the Git SHA of the commit. - The exact time the last deployment was performed. +- The upcoming deployment, if a deployment for the environment is in progress. +- When the environment stops automatically. - A button that takes you to the URL that you defined under the `environment` keyword in `.gitlab-ci.yml`. -- A button that re-deploys the latest deployment, meaning it runs the job - defined by the environment name for that specific commit. +- A number of deployment actions, including: + - Prevent the environment from [stopping automatically](#automatically-stopping-an-environment). + - [Open the live environment](#using-the-environment-url). + - Trigger [a manual deployment to a different environment](#configuring-manual-deployments). + - [Retry the deployment](#retrying-and-rolling-back). + - [Stop the environment](#stopping-an-environment). The information shown in the **Environments** page is limited to the latest deployments, but an environment can have multiple deployments. @@ -587,7 +593,7 @@ deployments, but an environment can have multiple deployments. > - The environments page can only be viewed by users with [Reporter permission](../../user/permissions.md#project-members-permissions) > and above. For more information on permissions, see the [permissions documentation](../../user/permissions.md). > - Only deploys that happen after your `.gitlab-ci.yml` is properly configured -> will show up in the **Environment** and **Last deployment** lists. +> show up in the **Environment** and **Last deployment** lists. ### Viewing deployment history @@ -619,7 +625,7 @@ To retry or rollback a deployment: #### What to expect with a rollback Pressing the **Rollback** button on a specific commit triggers a _new_ deployment with its own -unique job ID. This means that you will see a new deployment that points to the commit you're +unique job ID. This new deployment points to the commit you're rolling back to. Note that the defined deployment process in the job's `script` determines whether the rollback @@ -633,7 +639,7 @@ places within GitLab: - In a merge request widget as a link: ![Environment URL in merge request](../img/environments_mr_review_app.png) - In the Environments view as a button: - ![Environment URL in environments](../img/environments_available.png) + ![Environment URL in environments](../img/environments_available_13_7.png) - In the Deployments view as a button: ![Environment URL in deployments](../img/deployments_view.png) @@ -698,20 +704,20 @@ stop_review: If you can't use [Pipelines for merge requests](../merge_request_pipelines/index.md), setting the [`GIT_STRATEGY`](../runners/README.md#git-strategy) to `none` is necessary in the -`stop_review` job so that the [runner](https://docs.gitlab.com/runner/) won't +`stop_review` job so that the [runner](https://docs.gitlab.com/runner/) doesn't try to check out the code after the branch is deleted. When you have an environment that has a stop action defined (typically when -the environment describes a Review App), GitLab will automatically trigger a +the environment describes a Review App), GitLab automatically triggers a stop action when the associated branch is deleted. The `stop_review` job must be in the same `stage` as the `deploy_review` job in order for the environment to automatically stop. Additionally, both jobs should have matching [`rules`](../yaml/README.md#onlyexcept-basic) or [`only/except`](../yaml/README.md#onlyexcept-basic) configuration. In the example -above, if the configuration is not identical, the `stop_review` job might not be -included in all pipelines that include the `deploy_review` job, and it will not be -possible to trigger the `action: stop` to stop the environment automatically. +above, if the configuration isn't identical, the `stop_review` job might not be +included in all pipelines that include the `deploy_review` job, and it isn't +possible to trigger `action: stop` to stop the environment automatically. You can read more in the [`.gitlab-ci.yml` reference](../yaml/README.md#environmenton_stop). @@ -767,7 +773,7 @@ stop_review_app: ``` As long as a merge request is active and keeps getting new commits, -the review app will not stop, so developers don't need to worry about +the review app doesn't stop, so developers don't need to worry about re-initiating review app. On the other hand, since `stop_review_app` is set to `auto_stop_in: 1 week`, @@ -777,8 +783,8 @@ GitLab automatically triggers the `stop_review_app` job to stop the environment. You can also check the expiration date of environments through the GitLab UI. To do so, go to **Operations > Environments > Environment**. You can see the auto-stop period at the left-top section and a pin-mark button at the right-top section. This pin-mark -button can be used to prevent auto-stopping the environment. By clicking this button, the `auto_stop_in` setting is over-written -and the environment will be active until it's stopped manually. +button can be used to prevent auto-stopping the environment. By clicking this button, the +`auto_stop_in` setting is overwritten and the environment is active until it's stopped manually. ![Environment auto stop](../img/environment_auto_stop_v12_8.png) @@ -820,8 +826,8 @@ build with the specified environment runs. Newer deployments can also You may want to specify an environment keyword to [protect builds from unauthorized access](protected_environments.md), or to get access to [scoped variables](#scoping-environments-with-specs). In these cases, -you can use the `action: prepare` keyword to ensure deployments won't be created, -and no builds would be canceled: +you can use the `action: prepare` keyword to ensure deployments aren't created, +and no builds are canceled: ```yaml build: @@ -929,13 +935,13 @@ dashboard to appear, you need to Configure Prometheus to collect at least one In GitLab 9.2 and later, all deployments to an environment are shown directly on the monitoring dashboard. -Once configured, GitLab will attempt to retrieve [supported performance metrics](../../user/project/integrations/prometheus_library/index.md) +Once configured, GitLab attempts to retrieve [supported performance metrics](../../user/project/integrations/prometheus_library/index.md) for any environment that has had a successful deployment. If monitoring data was -successfully retrieved, a **Monitoring** button will appear for each environment. +successfully retrieved, a **Monitoring** button appears for each environment. ![Environment Detail with Metrics](../img/deployments_view.png) -Clicking on the **Monitoring** button will display a new page showing up to the last +Clicking the **Monitoring** button displays a new page showing up to the last 8 hours of performance data. It may take a minute or two for data to appear after initial deployment. @@ -962,10 +968,10 @@ of your web browser. To enable it, follow the instructions given in the service documentation. Note that container-based deployments often lack basic tools (like an editor), and may -be stopped or restarted at any time. If this happens, you will lose all your +be stopped or restarted at any time. If this happens, you lose all your changes. Treat this as a debugging tool, not a comprehensive online IDE. -Once enabled, your environments will gain a "terminal" button: +Once enabled, your environments gain a **Terminal** button: ![Terminal button on environment index](../img/environments_terminal_button_on_index.png) @@ -973,12 +979,12 @@ You can also access the terminal button from the page for a specific environment ![Terminal button for an environment](../img/environments_terminal_button_on_show.png) -Wherever you find it, clicking the button will take you to a separate page to +Wherever you find it, clicking the button takes you to a separate page to establish the terminal session: ![Terminal page](../img/environments_terminal_page.png) -This works just like any other terminal. You'll be in the container created +This works like any other terminal. You're in the container created by your deployment so you can: - Run shell commands and get responses in real time. @@ -1008,9 +1014,8 @@ fetch = +refs/environments/*:refs/remotes/origin/environments/* You can limit the environment scope of a variable by defining which environments it can be available for. -Wildcards can be used, and the default environment scope is `*`, which means -any jobs will have this variable, not matter if an environment is defined or -not. +Wildcards can be used and the default environment scope is `*`. This means that +any jobs can have this variable regardless of whether an environment is defined. For example, if the environment scope is `production`, then only the jobs having the environment `production` defined would have this specific variable. @@ -1057,7 +1062,7 @@ environment's operational health. ## Limitations In the `environment: name`, you are limited to only the [predefined environment variables](../variables/predefined_variables.md). -Re-using variables defined inside `script` as part of the environment name will not work. +Re-using variables defined inside `script` as part of the environment name doesn't work. ## Further reading @@ -1066,7 +1071,7 @@ Below are some links you may find interesting: - [The `.gitlab-ci.yml` definition of environments](../yaml/README.md#environment) - [A blog post on Deployments & Environments](https://about.gitlab.com/blog/2016/08/26/ci-deployment-and-environments/) - [Review Apps - Use dynamic environments to deploy your code for every branch](../review_apps/index.md) -- [Deploy Boards for your applications running on Kubernetes](../../user/project/deploy_boards.md) **(PREMIUM)** +- [Deploy Boards for your applications running on Kubernetes](../../user/project/deploy_boards.md) <!-- ## Troubleshooting diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md index 94f9aac51d6..0e4ad1df65f 100644 --- a/doc/ci/environments/protected_environments.md +++ b/doc/ci/environments/protected_environments.md @@ -36,14 +36,14 @@ To protect an environment: 1. In the **Allowed to Deploy** dropdown menu, select the role, users, or groups you want to give deploy access to. Keep in mind that: - There are two roles to choose from: - - **Maintainers**: will allow access to all maintainers in the project. - - **Developers**: will allow access to all maintainers and all developers in the project. + - **Maintainers**: Allows access to all maintainers in the project. + - **Developers**: Allows access to all maintainers and all developers in the project. - You can only select groups that are already associated with the project. - - Only users that have at least Developer permission level will appear in + - Only users that have at least the Developer permission level appear in the **Allowed to Deploy** dropdown menu. 1. Click the **Protect** button. -The protected environment will now appear in the list of protected environments. +The protected environment now appears in the list of protected environments. ### Use the API to protect an environment @@ -79,7 +79,7 @@ Alternatively, you can use the API to protect an environment: 1. Use the API to add a user to the group as a reporter: ```shell - $ curl --request POST --header "PRIVATE-TOKEN: xxxxxxxxxxxx" --data "user_id=3222377&access_level=20" "https://gitlab.com/api/v4/groups/9899826/members" + $ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --data "user_id=3222377&access_level=20" "https://gitlab.com/api/v4/groups/9899826/members" {"id":3222377,"name":"Sean Carroll","username":"sfcarroll","state":"active","avatar_url":"https://assets.gitlab-static.net/uploads/-/system/user/avatar/3222377/avatar.png","web_url":"https://gitlab.com/sfcarroll","access_level":20,"created_at":"2020-10-26T17:37:50.309Z","expires_at":null} ``` @@ -87,7 +87,7 @@ Alternatively, you can use the API to protect an environment: 1. Use the API to add the group to the project as a reporter: ```shell - $ curl --request POST --header "PRIVATE-TOKEN: xxxxxxxxxxxx" --request POST "https://gitlab.com/api/v4/projects/22034114/share?group_id=9899826&group_access=20" + $ curl --request POST --header "PRIVATE-TOKEN: <your_access_token>" --request POST "https://gitlab.com/api/v4/projects/22034114/share?group_id=9899826&group_access=20" {"id":1233335,"project_id":22034114,"group_id":9899826,"group_access":20,"expires_at":null} ``` @@ -95,7 +95,7 @@ Alternatively, you can use the API to protect an environment: 1. Use the API to add the group with protected environment access: ```shell - curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' --header "PRIVATE-TOKEN: xxxxxxxxxxx" "https://gitlab.com/api/v4/projects/22034114/protected_environments" + curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}]}' --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.com/api/v4/projects/22034114/protected_environments" ``` The group now has access and can be seen in the UI. |