diff --git a/app/models/group.rb b/app/models/group.rb index 86f4b14cb6cfdbf5d116f897335311a7c156e53e..5369e873d17f358f98300575fe8c092d34fb1ba2 100644 --- a/app/models/group.rb +++ b/app/models/group.rb @@ -863,6 +863,12 @@ def feature_available?(feature, user = nil) end end + def gitlab_deploy_token + strong_memoize(:gitlab_deploy_token) do + deploy_tokens.gitlab_deploy_token + end + end + private def feature_flag_enabled_for_self_or_ancestor?(feature_flag) diff --git a/app/models/project.rb b/app/models/project.rb index a215ff2a8781c6a08b1d518ef844b2eb2f46b6a9..f1dfd27f41ad8ed74288e0c562f344425a1ef378 100644 --- a/app/models/project.rb +++ b/app/models/project.rb @@ -2509,7 +2509,13 @@ def toggle_ci_cd_settings!(settings_attribute) end def gitlab_deploy_token - @gitlab_deploy_token ||= deploy_tokens.gitlab_deploy_token + strong_memoize(:gitlab_deploy_token) do + if Feature.enabled?(:ci_variable_for_group_gitlab_deploy_token, self) + deploy_tokens.gitlab_deploy_token || group&.gitlab_deploy_token + else + deploy_tokens.gitlab_deploy_token + end + end end def any_lfs_file_locks? diff --git a/config/feature_flags/development/ci_variable_for_group_gitlab_deploy_token.yml b/config/feature_flags/development/ci_variable_for_group_gitlab_deploy_token.yml new file mode 100644 index 0000000000000000000000000000000000000000..6474e8aa85e5cf957b3f68af208adb5b13334038 --- /dev/null +++ b/config/feature_flags/development/ci_variable_for_group_gitlab_deploy_token.yml @@ -0,0 +1,8 @@ +--- +name: ci_variable_for_group_gitlab_deploy_token +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/88696 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/363621 +milestone: '15.1' +type: development +group: group::pipeline authoring +default_enabled: false diff --git a/doc/user/project/deploy_tokens/index.md b/doc/user/project/deploy_tokens/index.md index 64c18ab6f3b8f0411f6973bab57a2f0a2e3d4658..0854b95275ab18a1a4d6cc370487468ec54680e3 100644 --- a/doc/user/project/deploy_tokens/index.md +++ b/doc/user/project/deploy_tokens/index.md @@ -190,6 +190,8 @@ To pull images from the Dependency Proxy, you must: ### GitLab deploy token +> Support for `gitlab-deploy-token` at the group level [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/214014) in GitLab 15.1 [with a flag](../../../administration/feature_flags.md) named `ci_variable_for_group_gitlab_deploy_token`. Disabled by default. + There's a special case when it comes to deploy tokens. If a user creates one named `gitlab-deploy-token`, the username and token of the deploy token is automatically exposed to the CI/CD jobs as CI/CD variables: `CI_DEPLOY_USER` @@ -203,9 +205,10 @@ docker login -u $CI_DEPLOY_USER -p $CI_DEPLOY_PASSWORD $CI_REGISTRY ``` NOTE: -The special handling for the `gitlab-deploy-token` deploy token is not -implemented for group deploy tokens. To make the group-level deploy token available for -CI/CD jobs, the `CI_DEPLOY_USER` and `CI_DEPLOY_PASSWORD` variables should be set under **Settings** to the name and token of the group deploy token respectively. +In GitLab 15.0 and earlier, the special handling for the `gitlab-deploy-token` deploy token +does not work for group deploy tokens. To make the group-level deploy token available +for CI/CD jobs, the `CI_DEPLOY_USER` and `CI_DEPLOY_PASSWORD` CI/CD variables must be +set in **Settings > CI/CD > Variables** to the name and token of the group deploy token. ## Troubleshooting diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb index bdad18fa65901c0b587b209942cb86db32a5869c..d00277479049624c547dad8a6c404ba080e7f781 100644 --- a/spec/models/ci/build_spec.rb +++ b/spec/models/ci/build_spec.rb @@ -3538,7 +3538,7 @@ ] end - context 'when gitlab-deploy-token exists' do + context 'when gitlab-deploy-token exists for project' do before do project.deploy_tokens << deploy_token end @@ -3548,11 +3548,32 @@ end end - context 'when gitlab-deploy-token does not exist' do + context 'when gitlab-deploy-token does not exist for project' do it 'does not include deploy token variables' do expect(subject.find { |v| v[:key] == 'CI_DEPLOY_USER'}).to be_nil expect(subject.find { |v| v[:key] == 'CI_DEPLOY_PASSWORD'}).to be_nil end + + context 'when gitlab-deploy-token exists for group' do + before do + group.deploy_tokens << deploy_token + end + + it 'includes deploy token variables' do + is_expected.to include(*deploy_token_variables) + end + + context 'when the FF ci_variable_for_group_gitlab_deploy_token is disabled' do + before do + stub_feature_flags(ci_variable_for_group_gitlab_deploy_token: false) + end + + it 'does not include deploy token variables' do + expect(subject.find { |v| v[:key] == 'CI_DEPLOY_USER'}).to be_nil + expect(subject.find { |v| v[:key] == 'CI_DEPLOY_PASSWORD'}).to be_nil + end + end + end end end diff --git a/spec/models/group_spec.rb b/spec/models/group_spec.rb index e7c830ce5e7986ec02bf2b153cb7b07a240364ac..ab92606e6fcee0a0abf9c04fe3953dd36a3cc020 100644 --- a/spec/models/group_spec.rb +++ b/spec/models/group_spec.rb @@ -3396,4 +3396,42 @@ def define_cache_expectations(cache_key) end end end + + describe '#gitlab_deploy_token' do + subject(:gitlab_deploy_token) { group.gitlab_deploy_token } + + context 'when there is a gitlab deploy token associated' do + let!(:deploy_token) { create(:deploy_token, :group, :gitlab_deploy_token, groups: [group]) } + + it { is_expected.to eq(deploy_token) } + end + + context 'when there is no a gitlab deploy token associated' do + it { is_expected.to be_nil } + end + + context 'when there is a gitlab deploy token associated but is has been revoked' do + let!(:deploy_token) { create(:deploy_token, :group, :gitlab_deploy_token, :revoked, groups: [group]) } + + it { is_expected.to be_nil } + end + + context 'when there is a gitlab deploy token associated but it is expired' do + let!(:deploy_token) { create(:deploy_token, :group, :gitlab_deploy_token, :expired, groups: [group]) } + + it { is_expected.to be_nil } + end + + context 'when there is a deploy token associated with a different name' do + let!(:deploy_token) { create(:deploy_token, :group, groups: [group]) } + + it { is_expected.to be_nil } + end + + context 'when there is a gitlab deploy token associated to a different group' do + let!(:deploy_token) { create(:deploy_token, :group, :gitlab_deploy_token, groups: [create(:group)]) } + + it { is_expected.to be_nil } + end + end end diff --git a/spec/models/project_spec.rb b/spec/models/project_spec.rb index 44d4b99bc3640cfb6f3271fd04a704efce90f90d..21978321a0f30a04c491ccf8d252bdc004742371 100644 --- a/spec/models/project_spec.rb +++ b/spec/models/project_spec.rb @@ -6220,7 +6220,7 @@ def has_external_wiki describe '#gitlab_deploy_token' do let(:project) { create(:project) } - subject { project.gitlab_deploy_token } + subject(:gitlab_deploy_token) { project.gitlab_deploy_token } context 'when there is a gitlab deploy token associated' do let!(:deploy_token) { create(:deploy_token, :gitlab_deploy_token, projects: [project]) } @@ -6252,10 +6252,43 @@ def has_external_wiki context 'when there is a deploy token associated to a different project' do let(:project_2) { create(:project) } - let!(:deploy_token) { create(:deploy_token, projects: [project_2]) } + let!(:deploy_token) { create(:deploy_token, :gitlab_deploy_token, projects: [project_2]) } it { is_expected.to be_nil } end + + context 'when the project group has a gitlab deploy token associated' do + let(:group) { create(:group) } + let(:project) { create(:project, group: group) } + let!(:deploy_token) { create(:deploy_token, :gitlab_deploy_token, :group, groups: [group]) } + + it { is_expected.to eq(deploy_token) } + + context 'when the FF ci_variable_for_group_gitlab_deploy_token is disabled' do + before do + stub_feature_flags(ci_variable_for_group_gitlab_deploy_token: false) + end + + it { is_expected.to be_nil } + end + end + + context 'when the project and its group has a gitlab deploy token associated' do + let(:group) { create(:group) } + let(:project) { create(:project, group: group) } + let!(:project_deploy_token) { create(:deploy_token, :gitlab_deploy_token, projects: [project]) } + let!(:group_deploy_token) { create(:deploy_token, :gitlab_deploy_token, :group, groups: [group]) } + + it { is_expected.to eq(project_deploy_token) } + + context 'when the FF ci_variable_for_group_gitlab_deploy_token is disabled' do + before do + stub_feature_flags(ci_variable_for_group_gitlab_deploy_token: false) + end + + it { is_expected.to eq(project_deploy_token) } + end + end end context 'with uploads' do