Commit e588a17d authored by Andrew Fontaine's avatar Andrew Fontaine

Merge branch 'ali/add-approval-count-to-protected-environment-ui' into 'master'

Add required approvals to Protected Environment settings

See merge request gitlab-org/gitlab!78931
parents 8ba1caeb 65ffaea1
......@@ -53,9 +53,16 @@ Example:
### Require approvals for a protected environment
NOTE:
At this time, only API-based configuration is available. UI-based configuration is planned for the near future. See [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/344675).
At this time, it is not possible to require approvals for an existing protected environment. The workaround is to unprotect the environment and configure approvals when re-protecting the environment.
Use the [Protected Environments API](../../api/protected_environments.md#protect-repository-environments) to create an environment with `required_approval_count` > 0. After this is set, all jobs deploying to this environment automatically go into a blocked state and wait for approvals before running.
There are two ways to configure approvals for a protected environment:
1. Using the [UI](protected_environments.md#protecting-environments)
1. Set the **Required approvals** field to 1 or more.
1. Using the [REST API](../../api/protected_environments.md#protect-repository-environments)
2. Set the `required_approval_count` field to 1 or more.
After this is configured, all jobs deploying to this environment automatically go into a blocked state and wait for approvals before running. Ensure that the number of required approvals is less than the number of users allowed to deploy.
Example:
......@@ -66,6 +73,7 @@ curl --header 'Content-Type: application/json' --request POST \
"https://gitlab.example.com/api/v4/projects/22034114/protected_environments"
```
NOTE:
To protect, update, or unprotect an environment, you must have at least the
Maintainer role.
......
......@@ -38,6 +38,9 @@ To protect an environment:
- You can select groups that are already associated with the project only.
- Users must have at least the Developer role to appear in
the **Allowed to deploy** list.
1. In the **Required approvals** list, select the number of approvals required to deploy to this environment.
- Ensure that this number is less than the number of users allowed to deploy.
- See [Deployment Approvals](deployment_approvals.md) for more information about this feature.
1. Select **Protect**.
The protected environment now appears in the list of protected environments.
......@@ -94,7 +97,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}]}' \
curl --header 'Content-Type: application/json' --request POST --data '{"name": "production", "deploy_access_levels": [{"group_id": 9899826}], "required_approval_count": 0}' \
--header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.com/api/v4/projects/22034114/protected_environments"
```
......
......@@ -8,6 +8,8 @@ import { initAccessDropdown } from '~/projects/settings/init_access_dropdown';
import { ACCESS_LEVELS } from './constants';
const PROTECTED_ENVIRONMENT_INPUT = 'input[name="protected_environment[name]"]';
const REQUIRED_APPROVAL_COUNT_INPUT =
'select[name="protected_environment[required_approval_count]"]';
export default class ProtectedEnvironmentCreate {
constructor() {
......@@ -82,6 +84,7 @@ export default class ProtectedEnvironmentCreate {
authenticity_token: this.$form.find('input[name="authenticity_token"]').val(),
protected_environment: {
name: this.$form.find(PROTECTED_ENVIRONMENT_INPUT).val(),
required_approval_count: this.$form.find(REQUIRED_APPROVAL_COUNT_INPUT).val(),
},
};
formData.protected_environment[`${ACCESS_LEVELS.DEPLOY}_attributes`] = this.selected;
......
......@@ -8,12 +8,14 @@
%colgroup
%col{ width: '30%' }
%col
%col
- if can_admin_project
%col{ width: '10%' }
%thead
%tr
%th= s_('ProtectedEnvironment|Protected Environment (%{protected_environments_count})') % { protected_environments_count: limited_counter_with_delimiter(@protected_environments) }
%th= s_('ProtectedEnvironment|Allowed to deploy')
%th= s_('ProtectedEnvironment|Required approvals')
- if can_admin_project
%th
%tbody
......
......@@ -15,5 +15,11 @@
= s_('ProtectedEnvironment|Allowed to deploy')
.js-allowed-to-deploy-dropdown
.form-group
= f.label :required_approval_count, s_('ProtectedEnvironment|Required approvals'), class: 'label-bold gl-display-block'
.dropdown.b-dropdown.gl-new-dropdown.gl-min-w-20.btn-group
= f.select :required_approval_count, (0..5).map { |num| [num.to_s, num] }, {}, class: 'dropdown-menu-toggle select-control'
= sprite_icon('chevron-down', css_class: 'gl-absolute gl-top-3 gl-right-3 gl-text-gray-500')
.card-footer
= f.submit s_('ProtectedEnvironment|Protect'), class: 'gl-button btn btn-confirm', disabled: true
......@@ -6,6 +6,8 @@
%span.ref-name= protected_environment.name
%td
= render partial: 'projects/protected_environments/update_deploy_access_level_dropdown', locals: { protected_environment: protected_environment, access_levels: protected_environment.deploy_access_levels, disabled: !can_admin_project }
%td.gl-min-w-20
= protected_environment.required_approval_count
- if can_admin_project
%td
......
......@@ -52,10 +52,10 @@ RSpec.describe 'Protected Environments' do
end
it 'allows creating explicit protected environments', :js do
set_protected_environment('staging')
within('.js-new-protected-environment') do
set_protected_environment('staging')
set_allowed_to_deploy('Developers + Maintainers')
set_required_approvals(1)
click_on('Protect')
end
......@@ -63,6 +63,11 @@ RSpec.describe 'Protected Environments' do
within('.protected-branches-list') do
expect(page).to have_content('staging')
within('tr', text: 'staging') do
expect(page).to have_content('Developers + Maintainers')
expect(page).to have_content('1')
end
end
end
......@@ -111,11 +116,9 @@ RSpec.describe 'Protected Environments' do
end
def set_protected_environment(environment_name)
within('.js-new-protected-environment') do
find('.js-protected-environment-select').click
find('.dropdown-input-field').set(environment_name)
find('.is-focused').click
end
find('.js-protected-environment-select').click
find('.dropdown-input-field').set(environment_name)
find('.is-focused').click
end
def set_allowed_to_deploy(option)
......@@ -125,4 +128,8 @@ RSpec.describe 'Protected Environments' do
Array(option).each { |opt| find('.gl-new-dropdown-item', text: opt).click }
end
end
def set_required_approvals(number)
select(number.to_s, from: 'protected_environment_required_approval_count')
end
end
......@@ -29340,6 +29340,9 @@ msgstr ""
msgid "ProtectedEnvironment|Protected Environment (%{protected_environments_count})"
msgstr ""
msgid "ProtectedEnvironment|Required approvals"
msgstr ""
msgid "ProtectedEnvironment|Select an environment"
msgstr ""
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment