diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION
index 86e0055efa9..9215e25cba2 100644
--- a/GITALY_SERVER_VERSION
+++ b/GITALY_SERVER_VERSION
@@ -1 +1 @@
-e0204f0c2b736bb4b72f622c64bbf8220ede14bc
+3bec5af36c5d3304174566c706807806eee8996d
diff --git a/Gemfile b/Gemfile
index 1949a156843..5672854d267 100644
--- a/Gemfile
+++ b/Gemfile
@@ -303,7 +303,7 @@ gem 'gitlab-sidekiq-fetcher',
gem 'fugit', '~> 1.11.1', feature_category: :continuous_integration
# HTTP requests
-gem 'httparty', '~> 0.21.0', feature_category: :shared
+gem 'httparty', '~> 0.22.0', feature_category: :shared
# Colored output to console
gem 'rainbow', '~> 3.0', feature_category: :shared
diff --git a/Gemfile.checksum b/Gemfile.checksum
index f91b8824c4b..eb9520c3e85 100644
--- a/Gemfile.checksum
+++ b/Gemfile.checksum
@@ -330,7 +330,7 @@
{"name":"http-accept","version":"1.7.0","platform":"ruby","checksum":"c626860682bfbb3b46462f8c39cd470fd7b0584f61b3cc9df5b2e9eb9972a126"},
{"name":"http-cookie","version":"1.0.5","platform":"ruby","checksum":"73756d46c7dbdc7023deecdb8a171348ea95a1b99810b31cfe8b4fb4e9a6318f"},
{"name":"http-form_data","version":"2.3.0","platform":"ruby","checksum":"cc4eeb1361d9876821e31d7b1cf0b68f1cf874b201d27903480479d86448a5f3"},
-{"name":"httparty","version":"0.21.0","platform":"ruby","checksum":"00ef7bf9a71f30a3bff88edeb5b16a34bea883ab67c246b3f0db2d6794fe1214"},
+{"name":"httparty","version":"0.22.0","platform":"ruby","checksum":"78652a5c9471cf0093d3b2083c2295c9c8f12b44c65112f1846af2b71430fa6c"},
{"name":"httpclient","version":"2.8.3","platform":"ruby","checksum":"2951e4991214464c3e92107e46438527d23048e634f3aee91c719e0bdfaebda6"},
{"name":"i18n","version":"1.14.4","platform":"ruby","checksum":"c7deedead0866ea9102975a4eab7968f53de50793a0c211a37808f75dd187551"},
{"name":"i18n_data","version":"0.13.1","platform":"ruby","checksum":"e5aa99b09a69b463bb0443fc1f9540351a49f3d1541c5e91316bafa035c63f66"},
diff --git a/Gemfile.lock b/Gemfile.lock
index 182538de138..c947479821c 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -74,7 +74,7 @@ PATH
gitlab-http (0.1.0)
activesupport (~> 7)
concurrent-ruby (~> 1.2)
- httparty (~> 0.21.0)
+ httparty (~> 0.21)
ipaddress (~> 0.8.3)
net-http (= 0.6.0)
railties (~> 7)
@@ -1015,7 +1015,8 @@ GEM
http-cookie (1.0.5)
domain_name (~> 0.5)
http-form_data (2.3.0)
- httparty (0.21.0)
+ httparty (0.22.0)
+ csv
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
@@ -2161,7 +2162,7 @@ DEPENDENCIES
health_check (~> 3.0)
html-pipeline (~> 2.14.3)
html2text
- httparty (~> 0.21.0)
+ httparty (~> 0.22.0)
i18n_data (~> 0.13.1)
icalendar (~> 2.10.1)
influxdb-client (~> 3.1)
@@ -2363,4 +2364,4 @@ DEPENDENCIES
yajl-ruby (~> 1.4.3)
BUNDLED WITH
- 2.5.11
+ 2.6.5
diff --git a/Gemfile.next.checksum b/Gemfile.next.checksum
index a3d40c7060c..d72dd4ed50a 100644
--- a/Gemfile.next.checksum
+++ b/Gemfile.next.checksum
@@ -330,7 +330,7 @@
{"name":"http-accept","version":"1.7.0","platform":"ruby","checksum":"c626860682bfbb3b46462f8c39cd470fd7b0584f61b3cc9df5b2e9eb9972a126"},
{"name":"http-cookie","version":"1.0.5","platform":"ruby","checksum":"73756d46c7dbdc7023deecdb8a171348ea95a1b99810b31cfe8b4fb4e9a6318f"},
{"name":"http-form_data","version":"2.3.0","platform":"ruby","checksum":"cc4eeb1361d9876821e31d7b1cf0b68f1cf874b201d27903480479d86448a5f3"},
-{"name":"httparty","version":"0.21.0","platform":"ruby","checksum":"00ef7bf9a71f30a3bff88edeb5b16a34bea883ab67c246b3f0db2d6794fe1214"},
+{"name":"httparty","version":"0.22.0","platform":"ruby","checksum":"78652a5c9471cf0093d3b2083c2295c9c8f12b44c65112f1846af2b71430fa6c"},
{"name":"httpclient","version":"2.8.3","platform":"ruby","checksum":"2951e4991214464c3e92107e46438527d23048e634f3aee91c719e0bdfaebda6"},
{"name":"i18n","version":"1.14.4","platform":"ruby","checksum":"c7deedead0866ea9102975a4eab7968f53de50793a0c211a37808f75dd187551"},
{"name":"i18n_data","version":"0.13.1","platform":"ruby","checksum":"e5aa99b09a69b463bb0443fc1f9540351a49f3d1541c5e91316bafa035c63f66"},
@@ -802,8 +802,8 @@
{"name":"webmock","version":"3.25.0","platform":"ruby","checksum":"573c23fc4887008c830f22da588db339ca38b6d59856fd57f5a068959474198e"},
{"name":"webrick","version":"1.8.2","platform":"ruby","checksum":"431746a349199546ff9dd272cae10849c865f938216e41c402a6489248f12f21"},
{"name":"websocket","version":"1.2.10","platform":"ruby","checksum":"2cc1a4a79b6e63637b326b4273e46adcddf7871caa5dc5711f2ca4061a629fa8"},
-{"name":"websocket-driver","version":"0.7.7","platform":"java","checksum":"e2520a6049feb88691e042d631063fa96d50620fb7f53b30180ae6fb2cf75eb1"},
-{"name":"websocket-driver","version":"0.7.7","platform":"ruby","checksum":"056d99f2cd545712cfb1291650fde7478e4f2661dc1db6a0fa3b966231a146b4"},
+{"name":"websocket-driver","version":"0.7.6","platform":"java","checksum":"bc894b9e9d5aee55ac04b61003e1957c4ef411a5a048199587d0499785b505c3"},
+{"name":"websocket-driver","version":"0.7.6","platform":"ruby","checksum":"f69400be7bc197879726ad8e6f5869a61823147372fd8928836a53c2c741d0db"},
{"name":"websocket-extensions","version":"0.1.5","platform":"ruby","checksum":"1c6ba63092cda343eb53fc657110c71c754c56484aad42578495227d717a8241"},
{"name":"wikicloth","version":"0.8.1","platform":"ruby","checksum":"7ac8a9ca0a948cf472851e521afc6c2a6b04a8f91ef1d824ba6a61ffbd60e6ca"},
{"name":"wisper","version":"2.0.1","platform":"ruby","checksum":"ce17bc5c3a166f241a2e6613848b025c8146fce2defba505920c1d1f3f88fae6"},
diff --git a/Gemfile.next.lock b/Gemfile.next.lock
index 55cba922a60..f8e6a8ce9f8 100644
--- a/Gemfile.next.lock
+++ b/Gemfile.next.lock
@@ -74,7 +74,7 @@ PATH
gitlab-http (0.1.0)
activesupport (~> 7)
concurrent-ruby (~> 1.2)
- httparty (~> 0.21.0)
+ httparty (~> 0.21)
ipaddress (~> 0.8.3)
net-http (= 0.6.0)
railties (~> 7)
@@ -1027,7 +1027,8 @@ GEM
http-cookie (1.0.5)
domain_name (~> 0.5)
http-form_data (2.3.0)
- httparty (0.21.0)
+ httparty (0.22.0)
+ csv
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
httpclient (2.8.3)
@@ -2007,8 +2008,7 @@ GEM
hashdiff (>= 0.4.0, < 2.0.0)
webrick (1.8.2)
websocket (1.2.10)
- websocket-driver (0.7.7)
- base64
+ websocket-driver (0.7.6)
websocket-extensions (>= 0.1.0)
websocket-extensions (0.1.5)
wikicloth (0.8.1)
@@ -2196,7 +2196,7 @@ DEPENDENCIES
health_check (~> 3.0)
html-pipeline (~> 2.14.3)
html2text
- httparty (~> 0.21.0)
+ httparty (~> 0.22.0)
i18n_data (~> 0.13.1)
icalendar (~> 2.10.1)
influxdb-client (~> 3.1)
@@ -2398,4 +2398,4 @@ DEPENDENCIES
yajl-ruby (~> 1.4.3)
BUNDLED WITH
- 2.5.11
+ 2.6.5
diff --git a/app/assets/javascripts/authentication/password/components/password_input.vue b/app/assets/javascripts/authentication/password/components/password_input.vue
index 0a3c3781248..aebd105cf73 100644
--- a/app/assets/javascripts/authentication/password/components/password_input.vue
+++ b/app/assets/javascripts/authentication/password/components/password_input.vue
@@ -51,6 +51,11 @@ export default {
type: String,
required: true,
},
+ disabled: {
+ type: Boolean,
+ required: false,
+ default: false,
+ },
},
data() {
return {
@@ -89,6 +94,7 @@ export default {
:data-track-action-for-errors="trackActionForErrors"
:title="title"
:type="type"
+ :disabled="disabled"
/>
diff --git a/app/assets/javascripts/authentication/password/index.js b/app/assets/javascripts/authentication/password/index.js
index 2af4dcad00d..3628d66b325 100644
--- a/app/assets/javascripts/authentication/password/index.js
+++ b/app/assets/javascripts/authentication/password/index.js
@@ -20,9 +20,11 @@ export const initPasswordInput = () => {
required,
autocomplete,
name,
+ disabled,
} = el.dataset;
const requiredAttr = required ? parseBoolean(required) : true;
+ const disabledAttr = disabled ? parseBoolean(disabled) : false;
// eslint-disable-next-line no-new
new Vue({
@@ -39,6 +41,7 @@ export const initPasswordInput = () => {
autocomplete,
name,
required: requiredAttr,
+ disabled: disabledAttr,
},
});
},
diff --git a/app/assets/javascripts/pages/admin/users/index.js b/app/assets/javascripts/pages/admin/users/index.js
index 0add5f24e2c..6f13c3ed030 100644
--- a/app/assets/javascripts/pages/admin/users/index.js
+++ b/app/assets/javascripts/pages/admin/users/index.js
@@ -5,9 +5,11 @@ import {
initDeleteUserModals,
} from '~/admin/users';
import initConfirmModal from '~/confirm_modal';
+import { initPasswordInput } from '~/authentication/password';
initAdminUsersFilterApp();
initAdminUserActions();
initAdminUsersApp();
initDeleteUserModals();
initConfirmModal();
+initPasswordInput();
diff --git a/app/models/ci/build.rb b/app/models/ci/build.rb
index 2a9088fa705..f35449a52af 100644
--- a/app/models/ci/build.rb
+++ b/app/models/ci/build.rb
@@ -788,14 +788,9 @@ module Ci
return unless project
return if user&.blocked?
- if Feature.enabled?(:ci_async_build_hooks_execution, project)
- return unless project.has_active_hooks?(:job_hooks) || project.has_active_integrations?(:job_hooks)
+ return unless project.has_active_hooks?(:job_hooks) || project.has_active_integrations?(:job_hooks)
- Ci::ExecuteBuildHooksWorker.perform_async(project.id, build_data)
- else
- project.execute_hooks(build_data.dup, :job_hooks) if project.has_active_hooks?(:job_hooks)
- project.execute_integrations(build_data.dup, :job_hooks) if project.has_active_integrations?(:job_hooks)
- end
+ Ci::ExecuteBuildHooksWorker.perform_async(project.id, build_data)
end
def browsable_artifacts?
diff --git a/app/models/concerns/integrations/base/discord.rb b/app/models/concerns/integrations/base/discord.rb
index 6d2e378aebf..cd05762835e 100644
--- a/app/models/concerns/integrations/base/discord.rb
+++ b/app/models/concerns/integrations/base/discord.rb
@@ -24,7 +24,7 @@ module Integrations
build_help_page_url(
'user/project/integrations/discord_notifications.md',
s_("DiscordService|Send notifications about project events to a Discord channel."),
- _('How do I set up this integration?')
+ link_text: _('How do I set up this integration?')
)
end
diff --git a/app/models/concerns/integrations/base/hangouts_chat.rb b/app/models/concerns/integrations/base/hangouts_chat.rb
index b342eee78dd..8fe463e52e8 100644
--- a/app/models/concerns/integrations/base/hangouts_chat.rb
+++ b/app/models/concerns/integrations/base/hangouts_chat.rb
@@ -29,7 +29,7 @@ module Integrations
'user/project/integrations/hangouts_chat.md',
'Before enabling this integration, create a webhook for the space in Google Chat where you want to ' \
'receive notifications from this project.',
- _('How do I set up a Google Chat webhook?')
+ link_text: _('How do I set up a Google Chat webhook?')
)
end
diff --git a/app/models/concerns/integrations/base/integration.rb b/app/models/concerns/integrations/base/integration.rb
index 191c16482aa..53605d23312 100644
--- a/app/models/concerns/integrations/base/integration.rb
+++ b/app/models/concerns/integrations/base/integration.rb
@@ -424,7 +424,7 @@ module Integrations
@field_storage || :properties
end
- def build_help_page_url(url_path, help_text, link_text = _("Learn More"), options = {})
+ def build_help_page_url(url_path, help_text, options = {}, link_text: _("Learn More"))
docs_link = ActionController::Base.helpers.link_to(
'',
Rails.application.routes.url_helpers.help_page_url(url_path, **options), # rubocop:disable Gitlab/DocumentationLinks/Link: -- existing code moved as is
diff --git a/app/models/integrations/datadog.rb b/app/models/integrations/datadog.rb
index 727f5c0683b..954774acd7f 100644
--- a/app/models/integrations/datadog.rb
+++ b/app/models/integrations/datadog.rb
@@ -196,7 +196,7 @@ module Integrations
build_help_page_url(
'integration/datadog.md',
s_('DatadogIntegration|Connect your GitLab projects to your Datadog account to synchronize repository metadata and enrich telemetry on your Datadog account.'),
- _('How do I set up this integration?')
+ link_text: _('How do I set up this integration?')
)
end
diff --git a/app/views/admin/users/_form.html.haml b/app/views/admin/users/_form.html.haml
index d933b2fcb77..f8d72fbe7bd 100644
--- a/app/views/admin/users/_form.html.haml
+++ b/app/views/admin/users/_form.html.haml
@@ -31,13 +31,13 @@
- c.with_body do
= s_('AdminUsers|Reset link will be generated and sent to the user. User will be forced to set the password on first sign in.')
- else
- .form-group.gl-form-group{ role: 'group' }
+ .form-group.gl-form-group.gl-form-input-lg{ role: 'group' }
= f.label :password, _('Password'), class: 'gl-block col-form-label'
- = f.password_field :password, disabled: f.object.force_random_password, autocomplete: 'new-password', class: 'form-control gl-form-input js-password-complexity-validation gl-form-input-lg'
+ = f.password_field :password, class: 'form-control gl-form-input js-password-complexity-validation js-password', data: { autocomplete: 'new-password', disabled: f.object.force_random_password, required: false, id: 'user_password', name: 'user[password]' }
= render_if_exists 'shared/password_requirements_list'
- .form-group.gl-form-group{ role: 'group' }
+ .form-group.gl-form-group.gl-form-input-lg{ role: 'group' }
= f.label :password_confirmation, _('Password confirmation'), class: 'gl-block col-form-label'
- = f.password_field :password_confirmation, disabled: f.object.force_random_password, autocomplete: 'new-password', class: 'form-control gl-form-input gl-form-input-lg'
+ = f.password_field :password_confirmation, class: 'form-control gl-form-input js-password', data: { autocomplete: 'new-password', disabled: f.object.force_random_password, required: false, id: 'user_password_confirmation', name: 'user[password_confirmation]' }
= render partial: 'access', locals: { f: f }
diff --git a/app/workers/ci/execute_build_hooks_worker.rb b/app/workers/ci/execute_build_hooks_worker.rb
index 2c0fbaf7e09..021bd11b8aa 100644
--- a/app/workers/ci/execute_build_hooks_worker.rb
+++ b/app/workers/ci/execute_build_hooks_worker.rb
@@ -15,6 +15,8 @@ module Ci
project = Project.find_by_id(project_id)
return unless project
+ build_data = build_data.with_indifferent_access
+
project.execute_hooks(build_data, :job_hooks) if project.has_active_hooks?(:job_hooks)
project.execute_integrations(build_data, :job_hooks) if project.has_active_integrations?(:job_hooks)
end
diff --git a/config/feature_flags/gitlab_com_derisk/ci_async_build_hooks_execution.yml b/config/feature_flags/gitlab_com_derisk/ci_async_build_hooks_execution.yml
deleted file mode 100644
index 3a029edb775..00000000000
--- a/config/feature_flags/gitlab_com_derisk/ci_async_build_hooks_execution.yml
+++ /dev/null
@@ -1,9 +0,0 @@
----
-name: ci_async_build_hooks_execution
-feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/499290
-introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/177706
-rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/512832
-milestone: '17.9'
-group: group::pipeline authoring
-type: gitlab_com_derisk
-default_enabled: false
diff --git a/doc/administration/internal_users.md b/doc/administration/internal_users.md
index 6f8172708f8..56e2ef3ea10 100644
--- a/doc/administration/internal_users.md
+++ b/doc/administration/internal_users.md
@@ -47,7 +47,7 @@ Other examples of internal users:
[GitLab Admin Bot](https://gitlab.com/gitlab-org/gitlab/-/blob/1d38cfdbed081f8b3fa14b69dd743440fe85081b/lib/users/internal.rb#L104)
is an internal user that cannot be accessed or modified by regular users and is responsible for many tasks including:
-- Applying [default compliance frameworks](../user/group/compliance_frameworks.md#default-compliance-frameworks) to
+- Applying [default compliance frameworks](../user/compliance/compliance_frameworks.md#default-compliance-frameworks) to
projects.
- [Automatically deactivating dormant users](moderate_users.md#automatically-deactivate-dormant-users).
- [Automatically deleting unconfirmed users](moderate_users.md#automatically-delete-unconfirmed-users).
diff --git a/doc/administration/server_hooks.md b/doc/administration/server_hooks.md
index 362c999e5d9..b503dba3af3 100644
--- a/doc/administration/server_hooks.md
+++ b/doc/administration/server_hooks.md
@@ -43,16 +43,16 @@ If you don't have access to the `gitaly` command, alternatives to server hooks i
## Set server hooks for a repository
-{{< tabs >}}
-
-{{< tab title="GitLab 15.11 and later" >}}
-
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/4629) in GitLab 15.11, `hooks set` command replaces direct file system access. Existing Git hooks don't need migrating for the `hooks set` command.
{{< /history >}}
+{{< tabs >}}
+
+{{< tab title="GitLab 15.11 and later" >}}
+
Prerequisites:
- The [storage name](gitaly/configure_gitaly.md#gitlab-requires-a-default-repository-storage), path to the Gitaly configuration file
@@ -181,16 +181,16 @@ subdirectories.
## Remove server hooks for a repository
-{{< tabs >}}
-
-{{< tab title="GitLab 15.11 and later" >}}
-
{{< history >}}
- [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/4629) in GitLab 15.11, `hooks set` command replaces direct file system access.
{{< /history >}}
+{{< tabs >}}
+
+{{< tab title="GitLab 15.11 and later" >}}
+
Prerequisites:
- The [storage name and relative path](repository_storage_paths.md#from-project-name-to-hashed-path) for the repository.
diff --git a/doc/administration/settings/continuous_integration.md b/doc/administration/settings/continuous_integration.md
index 3fb414975f2..a2311492727 100644
--- a/doc/administration/settings/continuous_integration.md
+++ b/doc/administration/settings/continuous_integration.md
@@ -521,7 +521,7 @@ To set the maximum file size:
This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/issues/389467) in GitLab 15.9
and was removed in 17.0. From 17.4, it is available only behind the feature flag `required_pipelines`, disabled by default.
-Use [compliance pipelines](../../user/group/compliance_pipelines.md) instead. This change is a breaking change.
+Use [compliance pipelines](../../user/compliance/compliance_pipelines.md) instead. This change is a breaking change.
{{< /alert >}}
diff --git a/doc/ci/pipelines/_index.md b/doc/ci/pipelines/_index.md
index 1ea4c46ffb2..71758850b26 100644
--- a/doc/ci/pipelines/_index.md
+++ b/doc/ci/pipelines/_index.md
@@ -141,9 +141,9 @@ In this example:
{{< alert type="note" >}}
-Because of a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/382857), projects that use [compliance pipelines](../../user/group/compliance_pipelines.md) can have prefilled variables not appear
+Because of a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/382857), projects that use [compliance pipelines](../../user/compliance/compliance_pipelines.md) can have prefilled variables not appear
when running a pipeline manually. To workaround this issue,
-[change the compliance pipeline configuration](../../user/group/compliance_pipelines.md#prefilled-variables-are-not-shown).
+[change the compliance pipeline configuration](../../user/compliance/compliance_pipelines.md#prefilled-variables-are-not-shown).
{{< /alert >}}
diff --git a/doc/ci/yaml/_index.md b/doc/ci/yaml/_index.md
index d518467549c..18ea1471629 100644
--- a/doc/ci/yaml/_index.md
+++ b/doc/ci/yaml/_index.md
@@ -554,7 +554,7 @@ start. Jobs in the current stage are not stopped and continue to run.
- If a job does not specify a [`stage`](#stage), the job is assigned the `test` stage.
- If a stage is defined but no jobs use it, the stage is not visible in the pipeline,
- which can help [compliance pipeline configurations](../../user/group/compliance_pipelines.md):
+ which can help [compliance pipeline configurations](../../user/compliance/compliance_pipelines.md):
- Stages can be defined in the compliance configuration but remain hidden if not used.
- The defined stages become visible when developers use them in job definitions.
@@ -4651,7 +4651,7 @@ In this example:
section. The project containing the `include` section can be different than the project
running the pipeline when using:
- [Nested includes](includes.md#use-nested-includes).
- - [Compliance pipelines](../../user/group/compliance_pipelines.md).
+ - [Compliance pipelines](../../user/compliance/compliance_pipelines.md).
- `rules:exists` cannot search for the presence of [artifacts](../jobs/job_artifacts.md),
because `rules` evaluation happens before jobs run and artifacts are fetched.
diff --git a/doc/development/internal_analytics/product_analytics.md b/doc/development/internal_analytics/product_analytics.md
index f8c32edb026..4860f2eba2b 100644
--- a/doc/development/internal_analytics/product_analytics.md
+++ b/doc/development/internal_analytics/product_analytics.md
@@ -106,6 +106,12 @@ you must enable and configure product analytics.
### Product analytics provider
+{{< history >}}
+
+- Self-managed provider [introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/117804) in GitLab 16.0.
+
+{{< /history >}}
+
Your GitLab instance connects to a product analytics provider.
A product analytics provider is the collection of services required to receive,
process, store and query your analytics data.
@@ -114,12 +120,6 @@ process, store and query your analytics data.
{{< tab title="GitLab-managed provider" >}}
-{{< details >}}
-
-- Offering: GitLab.com
-
-{{< /details >}}
-
On GitLab.com you can use a GitLab-managed provider offered only in the Google Cloud Platform zone `us-central-1`.
If GitLab manages your product analytics provider, then your analytics data is retained for one year.
@@ -129,8 +129,6 @@ You can request to delete your data at any time by [contacting support](https://
{{< tab title="Self-managed provider" >}}
->[Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/117804) in GitLab 16.0.
-
A self-managed product analytics provider is a deployed instance of the
[product analytics Helm charts](https://gitlab.com/gitlab-org/analytics-section/product-analytics/helm-charts).
diff --git a/doc/tutorials/compliance_pipeline/_index.md b/doc/tutorials/compliance_pipeline/_index.md
index ddef7f10dea..885e3922a62 100644
--- a/doc/tutorials/compliance_pipeline/_index.md
+++ b/doc/tutorials/compliance_pipeline/_index.md
@@ -18,13 +18,13 @@ title: 'Tutorial: Create a compliance pipeline (deprecated)'
This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/159841) in GitLab 17.3
and is planned for removal in 18.0. Use [pipeline execution policy type](../../user/application_security/policies/pipeline_execution_policies.md) instead.
-This change is a breaking change. For more information, see the [migration guide](../../user/group/compliance_pipelines.md#pipeline-execution-policies-migration).
+This change is a breaking change. For more information, see the [migration guide](../../user/compliance/compliance_pipelines.md#pipeline-execution-policies-migration).
{{< /alert >}}
-You can use [compliance pipelines](../../user/group/compliance_pipelines.md) to ensure specific
+You can use [compliance pipelines](../../user/compliance/compliance_pipelines.md) to ensure specific
compliance-related jobs are run on pipelines for all projects in a group. Compliance pipelines are applied
-to projects through [compliance frameworks](../../user/group/compliance_frameworks.md).
+to projects through [compliance frameworks](../../user/compliance/compliance_frameworks.md).
In this tutorial, you:
@@ -57,7 +57,7 @@ To create the new group:
## Create a new compliance pipeline project
Now you're ready to create a compliance pipeline project. This project contains the
-[compliance pipeline configuration](../../user/group/compliance_pipelines.md#example-configuration) to apply to all
+[compliance pipeline configuration](../../user/compliance/compliance_pipelines.md#example-configuration) to apply to all
projects with the compliance framework applied.
To create the compliance pipeline project:
@@ -191,6 +191,6 @@ Notice the pipeline runs two jobs in a **test** stage:
Congratulations, you've created and configured a compliance pipeline!
-See more [example compliance pipeline configurations](../../user/group/compliance_pipelines.md#example-configuration).
+See more [example compliance pipeline configurations](../../user/compliance/compliance_pipelines.md#example-configuration).
diff --git a/doc/user/application_security/_index.md b/doc/user/application_security/_index.md
index a6d39429e31..27994f65240 100644
--- a/doc/user/application_security/_index.md
+++ b/doc/user/application_security/_index.md
@@ -193,7 +193,7 @@ Security and compliance teams must ensure that security scans:
GitLab provides two methods of accomplishing this, each with advantages and disadvantages.
-- [Compliance framework pipelines](../group/compliance_pipelines.md)
+- [Compliance framework pipelines](../compliance/compliance_pipelines.md)
are recommended when:
- Scan execution enforcement is required for any scanner that uses a GitLab template, such as SAST IaC, DAST, Dependency Scanning,
diff --git a/doc/user/compliance/_index.md b/doc/user/compliance/_index.md
index 40bb5312c50..acd321233d0 100644
--- a/doc/user/compliance/_index.md
+++ b/doc/user/compliance/_index.md
@@ -32,8 +32,8 @@ compliance:
| Feature | Instances | Groups | Projects | Description |
|:-----------------------------------------------------------------------------------------------------------------------------------------|:-------------------------------------|:-------------------------------------|:-------------------------------------|:------------|
-| [Compliance frameworks](../group/compliance_frameworks.md) | {{< icon name="dotted-circle" >}} No | {{< icon name="check-circle" >}} Yes | {{< icon name="dotted-circle" >}} No | Describe the type of compliance requirements projects must follow. |
-| [Compliance pipelines](../group/compliance_pipelines.md) | {{< icon name="dotted-circle" >}} No | {{< icon name="check-circle" >}} Yes | {{< icon name="dotted-circle" >}} No | Define a pipeline configuration to run for any projects with a given compliance framework. |
+| [Compliance frameworks](../compliance/compliance_frameworks.md) | {{< icon name="dotted-circle" >}} No | {{< icon name="check-circle" >}} Yes | {{< icon name="dotted-circle" >}} No | Describe the type of compliance requirements projects must follow. |
+| [Compliance pipelines](../compliance/compliance_pipelines.md) | {{< icon name="dotted-circle" >}} No | {{< icon name="check-circle" >}} Yes | {{< icon name="dotted-circle" >}} No | Define a pipeline configuration to run for any projects with a given compliance framework. |
| [Merge request approval policy approval settings](../application_security/policies/merge_request_approval_policies.md#approval_settings) | {{< icon name="check-circle" >}} Yes | {{< icon name="check-circle" >}} Yes | {{< icon name="check-circle" >}} Yes | Enforce a merge request approval policy enforcing multiple approvers and override various project settings in all enforced groups or projects across your GitLab instance or group. |
## Audit management
diff --git a/doc/user/compliance/compliance_center/compliance_frameworks_report.md b/doc/user/compliance/compliance_center/compliance_frameworks_report.md
index 00067bf1b02..7e20e2e75d6 100644
--- a/doc/user/compliance/compliance_center/compliance_frameworks_report.md
+++ b/doc/user/compliance/compliance_center/compliance_frameworks_report.md
@@ -78,6 +78,34 @@ To delete a compliance framework from the compliance frameworks report:
1. Hover over framework and select **Edit the framework**.
1. Select the **Delete framework** to delete compliance framework.
+## Set and remove a compliance framework as default
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/181500) in GitLab 17.10.
+
+{{< /history >}}
+
+Prerequisites:
+
+- You must be an administrator or have the Owner role for the group.
+
+To set a compliance framework as [default](../compliance_frameworks.md#default-compliance-frameworks)] from the compliance frameworks report:
+
+1. On the left sidebar, select **Search or go to** and find your group.
+1. Select **Secure > Compliance center**.
+1. On the page, select the **Frameworks** tab.
+1. Next to the compliance framework you want to set as default, select {{< icon name="pencil" >}} action.
+1. Select the **Set as default** to set as default.
+
+To remove a compliance framework as default from the compliance frameworks report:
+
+1. On the left sidebar, select **Search or go to** and find your group.
+1. Select **Secure > Compliance center**.
+1. On the page, select the **Frameworks** tab.
+1. Next to the compliance framework that is default, select {{< icon name="pencil" >}} action.
+1. Select the **Remove as default** to remove as default.
+
## Export a report of compliance frameworks in a group
{{< history >}}
diff --git a/doc/user/compliance/compliance_frameworks.md b/doc/user/compliance/compliance_frameworks.md
new file mode 100644
index 00000000000..e6cd990c3ef
--- /dev/null
+++ b/doc/user/compliance/compliance_frameworks.md
@@ -0,0 +1,112 @@
+---
+stage: Software Supply Chain Security
+group: Compliance
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
+title: Compliance frameworks
+---
+
+{{< details >}}
+
+- Tier: Premium, Ultimate
+- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
+
+{{< /details >}}
+
+You can create a compliance framework that is a label to identify that your project has certain compliance
+requirements or needs additional oversight.
+
+In the Ultimate tier, the compliance framework can optionally enforce
+[compliance pipeline configuration](compliance_pipelines.md) and
+[security policies](../application_security/policies/_index.md#scope) to the projects on which it is applied.
+
+Compliance frameworks are created on top-level groups. If a project is moved outside of its existing top-level group,
+its frameworks are removed.
+
+You can apply up to 20 compliance frameworks to each project.
+
+For a click-through demo, see [Compliance frameworks](https://gitlab.navattic.com/compliance).
+
+
+## Prerequisites
+
+- To create, edit, and delete compliance frameworks, users must have either:
+ - The Owner role for the top-level group.
+ - Be assigned a [custom role](../custom_roles.md) with the `admin_compliance_framework`
+ [custom permission](../custom_roles/abilities.md#compliance-management).
+- To add or remove a compliance framework to or from a project, the group to which the project belongs must have a
+ compliance framework.
+
+## Create, edit, or delete a compliance framework
+
+You can create, edit, or delete a compliance framework from a compliance framework report. For more information, see:
+
+- [Create a new compliance framework](../compliance/compliance_center/compliance_frameworks_report.md#create-a-new-compliance-framework).
+- [Edit a compliance framework](../compliance/compliance_center/compliance_frameworks_report.md#edit-a-compliance-framework).
+- [Delete a compliance framework](../compliance/compliance_center/compliance_frameworks_report.md#delete-a-compliance-framework).
+
+You can create, edit, or delete a compliance framework from a compliance projects report. For more information, see:
+
+- [Create a new compliance framework](../compliance/compliance_center/compliance_projects_report.md#create-a-new-compliance-framework).
+- [Edit a compliance framework](../compliance/compliance_center/compliance_projects_report.md#edit-a-compliance-framework).
+- [Delete a compliance framework](../compliance/compliance_center/compliance_projects_report.md#delete-a-compliance-framework).
+
+Subgroups and projects have access to all compliance frameworks created on their top-level group. However, compliance frameworks cannot be created, edited,
+or deleted at the subgroup or project level. Project owners can choose a framework to apply to their projects.
+
+## Apply a compliance framework to a project
+
+{{< history >}}
+
+- Assigning multiple compliance frameworks [introduced](https://gitlab.com/groups/gitlab-org/-/epics/13294) in GitLab 17.3.
+
+{{< /history >}}
+
+You can apply multiple compliance frameworks to a project but cannot apply compliance frameworks to projects in personal namespaces.
+
+To apply a compliance framework to a project, apply the compliance framework through the
+[Compliance projects report](../compliance/compliance_center/compliance_projects_report.md#apply-a-compliance-framework-to-projects-in-a-group).
+
+You can use the [GraphQL API](../../api/graphql/reference/_index.md#mutationprojectupdatecomplianceframeworks) to apply one or many
+compliance frameworks to a project.
+
+If you create compliance frameworks on subgroups with GraphQL, the framework is created on the root ancestor if the user
+has the correct permissions. The GitLab UI presents a read-only view to discourage this behavior.
+
+## Default compliance frameworks
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/375036) in GitLab 15.6.
+
+{{< /history >}}
+
+Group owners can set a default compliance framework. The default framework is applied to all the new and imported
+projects that are created in that group. It does not affect the framework applied to the existing projects. The
+default framework cannot be deleted.
+
+A compliance framework that is set to default has a **default** label.
+
+### Set and remove a default by using the compliance center
+
+To set as default (or remove the default) from [compliance projects report](../compliance/compliance_center/compliance_projects_report.md):
+
+1. On the left sidebar, select **Search or go to** and find your group.
+1. Select **Secure > Compliance center**.
+1. On the page, select the **Projects** tab.
+1. Hover over a compliance framework, select the **Edit Framework** tab.
+1. Select **Set as default**.
+1. Select **Save changes**.
+
+To set as default (or remove the default) from [compliance framework report](../compliance/compliance_center/compliance_frameworks_report.md):
+
+1. On the left sidebar, select **Search or go to** and find your group.
+1. Select **Secure > Compliance center**.
+1. On the page, select the **Frameworks** tab.
+1. Hover over a compliance framework, select the **Edit Framework** tab.
+1. Select **Set as default**.
+1. Select **Save changes**.
+
+## Remove a compliance framework from a project
+
+To remove a compliance framework from one or multiple project in a group, remove the compliance framework through the
+[Compliance projects report](../compliance/compliance_center/compliance_projects_report.md#remove-a-compliance-framework-from-projects-in-a-group).
diff --git a/doc/user/compliance/compliance_pipelines.md b/doc/user/compliance/compliance_pipelines.md
new file mode 100644
index 00000000000..59372d7a79d
--- /dev/null
+++ b/doc/user/compliance/compliance_pipelines.md
@@ -0,0 +1,416 @@
+---
+stage: Software Supply Chain Security
+group: Compliance
+info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
+title: Compliance pipelines (deprecated)
+---
+
+
+
+{{< details >}}
+
+- Tier: Ultimate
+- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
+
+{{< /details >}}
+
+{{< alert type="warning" >}}
+
+This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/159841) in GitLab 17.3
+and is planned for removal in 19.0. Use [pipeline execution policy type](../application_security/policies/pipeline_execution_policies.md) instead.
+This change is a breaking change. For more information, see the [migration guide](#pipeline-execution-policies-migration).
+
+{{< /alert >}}
+
+Group owners can configure a compliance pipeline in a project separate to other projects. By default, the compliance
+pipeline configuration (for example, `.compliance-gitlab-ci.yml`) is run instead of the pipeline configuration (for example, `.gitlab-ci.yml`) of labeled
+projects.
+
+However, the compliance pipeline configuration can reference the `.gitlab-ci.yml` file of the labeled projects so that:
+
+- The compliance pipeline can also run jobs of labeled project pipelines. This allows for centralized control of
+ pipeline configuration.
+- Jobs and variables defined in the compliance pipeline can't be changed by variables in the labeled project's
+ `.gitlab-ci.yml` file.
+
+{{< alert type="note" >}}
+
+Because of a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/414004), project pipelines must be included first at the top of compliance pipeline configuration
+to prevent projects overriding settings downstream.
+
+{{< /alert >}}
+
+For more information, see:
+
+- [Example configuration](#example-configuration) for help configuring a compliance pipeline that runs jobs from
+ labeled project pipeline configuration.
+- The [Create a compliance pipeline](../../tutorials/compliance_pipeline/_index.md) tutorial.
+
+## Pipeline execution policies migration
+
+To consolidate and simplify scan and pipeline enforcement, we have introduced pipeline execution policies. We deprecated
+compliance pipelines in GitLab 17.3 and will remove compliance pipelines in GitLab 19.0.
+
+Pipeline execution policies extend a project's `.gitlab-ci.yml` file with the configuration provided in separate YAML file
+(for example, `pipeline-execution.yml`) linked in the pipeline execution policy.
+
+By default, when creating a new compliance framework, you are directed to use the pipeline execution policy type instead
+of compliance pipelines.
+
+Existing compliance pipelines must be migrated. Customers should migrate from compliance pipelines to the new
+[pipeline execution policy type](../application_security/policies/pipeline_execution_policies.md) as soon as possible.
+
+### Migrate an existing compliance framework
+
+To migrate an existing compliance framework to use the pipeline execution policy type:
+
+1. On the left sidebar, select **Search or go to** and find your group.
+1. Select **Secure > Compliance center**.
+1. [Edit](compliance_frameworks.md#create-edit-or-delete-a-compliance-framework) the existing compliance framework.
+1. In the banner than appears, select **Migrate pipeline to a policy** to create a new policy in the security policies.
+1. Edit the compliance framework again to remove the compliance pipeline.
+
+For more information, see [Security policy project](../application_security/policies/_index.md#security-policy-project).
+
+If you receive a `Pipeline execution policy error: Job names must be unique` error during the migration, see the
+[relevant troubleshooting information](#error-job-names-must-be-unique).
+
+## Effect on labeled projects
+
+Users have no way of knowing that a compliance pipeline has been configured and might be confused why their own
+pipelines are not running at all, or include jobs that they did not define themselves.
+
+When authoring pipelines on a labeled project, there is no indication that a compliance pipeline has been configured.
+The only marker at the project level is the compliance framework label itself, but the label does not say whether the
+framework has a compliance pipeline configured or not.
+
+Therefore, communicate with project users about compliance pipeline configuration to reduce uncertainty and confusion.
+
+### Multiple compliance frameworks
+
+You can [apply to a single project](compliance_frameworks.md#apply-a-compliance-framework-to-a-project) multiple compliance frameworks with compliance pipelines configured.
+In this case, only the first compliance framework applied to a project has its compliance pipeline included in the project pipeline.
+
+To ensure that the correct compliance pipeline is included in a project:
+
+1. Remove all compliance frameworks from the project.
+1. Apply the compliance framework with the correct compliance pipeline to the project.
+1. Apply additional compliance frameworks to the project.
+
+## Configure a compliance pipeline
+
+{{< history >}}
+
+- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/383209) in GitLab 15.11, compliance frameworks moved to compliance center.
+
+{{< /history >}}
+
+To configure a compliance pipeline:
+
+1. On the left sidebar, select **Search or go to** and find your group.
+1. Select **Secure** > **Compliance Center**.
+1. Select **Frameworks** section.
+1. Select **New framework** section, add information of compliance framework including path to the compliance framework configuration. Use the
+ `path/file.y[a]ml@group-name/project-name` format. For example:
+
+ - `.compliance-ci.yml@gitlab-org/gitlab`.
+ - `.compliance-ci.yaml@gitlab-org/gitlab`.
+
+This configuration is inherited by projects where the compliance framework label is
+[applied](../project/working_with_projects.md#add-a-compliance-framework-to-a-project). In projects with the applied compliance
+framework label, the compliance pipeline configuration is run instead of the labeled project's own pipeline configuration.
+
+The user running the pipeline in the labeled project must at least have the Reporter role on the compliance project.
+
+When used to enforce scan execution, this feature has some overlap with
+[scan execution policies](../application_security/policies/scan_execution_policies.md). We have not
+[unified the user experience for these two features](https://gitlab.com/groups/gitlab-org/-/epics/7312). For details on
+the similarities and differences between these features, see [Enforce scan execution](../application_security/_index.md#enforce-scan-execution).
+
+### Example configuration
+
+The following example `.compliance-gitlab-ci.yml` includes the `include` keyword to ensure labeled project pipeline
+configuration is also executed.
+
+```yaml
+include: # Execute individual project's configuration (if project contains .gitlab-ci.yml)
+ - project: '$CI_PROJECT_PATH'
+ file: '$CI_CONFIG_PATH'
+ ref: '$CI_COMMIT_SHA' # Must be defined or MR pipelines always use the use default branch
+ rules:
+ - if: $CI_PROJECT_PATH != "my-group/project-1" # Must run on projects other than the one hosting this configuration.
+
+# Allows compliance team to control the ordering and interweaving of stages/jobs.
+# Stages without jobs defined will remain hidden.
+stages:
+ - pre-compliance
+ - build
+ - test
+ - pre-deploy-compliance
+ - deploy
+ - post-compliance
+
+variables: # Can be overridden by setting a job-specific variable in project's local .gitlab-ci.yml
+ FOO: sast
+
+sast: # None of these attributes can be overridden by a project's local .gitlab-ci.yml
+ variables:
+ FOO: sast
+ image: ruby:2.6
+ stage: pre-compliance
+ rules:
+ - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
+ when: never
+ - when: always # or when: on_success
+ allow_failure: false
+ before_script:
+ - "# No before scripts."
+ script:
+ - echo "running $FOO"
+ after_script:
+ - "# No after scripts."
+
+sanity check:
+ image: ruby:2.6
+ stage: pre-deploy-compliance
+ rules:
+ - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
+ when: never
+ - when: always # or when: on_success
+ allow_failure: false
+ before_script:
+ - "# No before scripts."
+ script:
+ - echo "running $FOO"
+ after_script:
+ - "# No after scripts."
+
+audit trail:
+ image: ruby:2.7
+ stage: post-compliance
+ rules:
+ - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
+ when: never
+ - when: always # or when: on_success
+ allow_failure: false
+ before_script:
+ - "# No before scripts."
+ script:
+ - echo "running $FOO"
+ after_script:
+ - "# No after scripts."
+```
+
+The `rules` configuration in the `include` definition avoids circular inclusion in case the compliance pipeline must be able to run in the host project itself.
+You can leave it out if your compliance pipeline only ever runs in labeled projects.
+
+#### Compliance pipelines and custom pipeline configuration hosted externally
+
+The example above assumes that all projects host their pipeline configuration in the same project.
+If any projects use [configuration hosted externally](../../ci/pipelines/settings.md#specify-a-custom-cicd-configuration-file),
+the example configuration does not work. See [issue 393960](https://gitlab.com/gitlab-org/gitlab/-/issues/393960)
+for more details.
+
+With projects that use externally hosted configuration, you can try the this workaround:
+
+- The `include` section in the example compliance pipeline configuration must be adjusted.
+ For example, using [`include:rules`](../../ci/yaml/includes.md#use-rules-with-include):
+
+ ```yaml
+ include:
+ # If the custom path variables are defined, include the project's external config file.
+ - project: '$PROTECTED_PIPELINE_CI_PROJECT_PATH'
+ file: '$PROTECTED_PIPELINE_CI_CONFIG_PATH'
+ ref: '$PROTECTED_PIPELINE_CI_REF'
+ rules:
+ - if: $PROTECTED_PIPELINE_CI_PROJECT_PATH && $PROTECTED_PIPELINE_CI_CONFIG_PATH && $PROTECTED_PIPELINE_CI_REF
+ # If any custom path variable is not defined, include the project's internal config file as normal.
+ - project: '$CI_PROJECT_PATH'
+ file: '$CI_CONFIG_PATH'
+ ref: '$CI_COMMIT_SHA'
+ rules:
+ - if: $PROTECTED_PIPELINE_CI_PROJECT_PATH == null || $PROTECTED_PIPELINE_CI_CONFIG_PATH == null || $PROTECTED_PIPELINE_CI_REF == null
+ ```
+
+- [CI/CD variables](../../ci/variables/_index.md) must be added to projects with external
+ pipeline configuration. In this example:
+
+ - `PROTECTED_PIPELINE_CI_PROJECT_PATH`: The path to the project hosting the configuration file, for example `group/subgroup/project`.
+ - `PROTECTED_PIPELINE_CI_CONFIG_PATH`: The path to the configuration file in the project, for example `path/to/.gitlab-ci.yml`.
+ - `PROTECTED_PIPELINE_CI_REF`: The ref to use when retrieving the configuration file, for example `main`.
+
+#### Compliance pipelines in merge requests originating in project forks
+
+When a merge request originates in a fork, the branch to be merged usually only exists in the fork.
+When creating such a merge request against a project with compliance pipelines, the above snippet fails with a
+`Project reference does not exist!` error message.
+This error occurs because in the context of the target project, `$CI_COMMIT_REF_NAME` evaluates to a non-existing
+branch name.
+
+To get the correct context, use `$CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` instead of `$CI_PROJECT_PATH`.
+This variable is only available in
+[merge request pipelines](../../ci/pipelines/merge_request_pipelines.md).
+
+For example, for a configuration that supports both merge request pipelines originating in project forks and branch pipelines,
+you need to [combine both `include` directives with `rules:if`](../../ci/yaml/includes.md#use-rules-with-include):
+
+```yaml
+include: # Execute individual project's configuration (if project contains .gitlab-ci.yml)
+ - project: '$CI_MERGE_REQUEST_SOURCE_PROJECT_PATH'
+ file: '$CI_CONFIG_PATH'
+ ref: '$CI_COMMIT_REF_NAME'
+ rules:
+ - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
+ - project: '$CI_PROJECT_PATH'
+ file: '$CI_CONFIG_PATH'
+ ref: '$CI_COMMIT_REF_NAME'
+ rules:
+ - if: $CI_PIPELINE_SOURCE != 'merge_request_event'
+```
+
+#### Compliance pipelines in projects with no configuration file
+
+The [example configuration](#example-configuration) above assumes that all projects contain
+a pipeline configuration file (`.gitlab-ci.yml` by default). However, in projects
+with no configuration file (and therefore no pipelines by default), the compliance pipeline
+fails because the file specified in `include:project` is required.
+
+To only include a configuration file if it exists in a target project, use
+[`rules:exists:project`](../../ci/yaml/_index.md#rulesexistsproject):
+
+```yaml
+include: # Execute individual project's configuration
+ - project: '$CI_PROJECT_PATH'
+ file: '$CI_CONFIG_PATH'
+ ref: '$CI_COMMIT_SHA'
+ rules:
+ - exists:
+ paths:
+ - '$CI_CONFIG_PATH'
+ project: '$CI_PROJECT_PATH'
+ ref: '$CI_COMMIT_SHA'
+```
+
+In this example, a configuration file is only included if it exists for the given `ref`
+in the project in `exists:project: $CI_PROJECT_PATH'`.
+
+If `exists:project` is not specified in the compliance pipeline configuration, it searches for files in the project
+in which the `include` is defined. In compliance pipelines, the `include` from the example above
+is defined in the project hosting the compliance pipeline configuration file, not the project
+running the pipeline.
+
+## Ensure compliance jobs are always run
+
+Compliance pipelines [use GitLab CI/CD](../../ci/_index.md) to give you an incredible amount of flexibility
+for defining any sort of compliance jobs you like. Depending on your goals, these jobs
+can be configured to be:
+
+- Modified by users.
+- Non-modifiable.
+
+Generally, if a value in a compliance job:
+
+- Is set, it cannot be changed or overridden by project-level configurations.
+- Is not set, a project-level configuration may be set.
+
+Either might be wanted or not depending on your use case.
+
+The following are a few best practices for ensuring that these jobs are always run exactly
+as you define them and that downstream, project-level pipeline configurations
+cannot change them:
+
+- Add [a `rules:when:always` block](../../ci/yaml/_index.md#when) to each of your compliance jobs. This ensures they are
+ non-modifiable and are always run.
+- Explicitly set any [variables](../../ci/yaml/_index.md#variables) the job references. This:
+ - Ensures that project-level pipeline configurations do not set them and alter their
+ behavior. For example, see `before_script` and `after_script` configuration in the [example configuration](#example-configuration).
+ - Includes any jobs that drive the logic of your job.
+- Explicitly set the [container image](../../ci/yaml/_index.md#image) to run the job in. This ensures that your script
+ steps execute in the correct environment.
+- Explicitly set any relevant GitLab pre-defined [job keywords](../../ci/yaml/_index.md#job-keywords).
+ This ensures that your job uses the settings you intend and that they are not overridden by
+ project-level pipelines.
+
+## Troubleshooting
+
+### Compliance jobs are overwritten by target repository
+
+If you use the `extends` statement in a compliance pipeline configuration, compliance jobs are overwritten by the target repository job. For example,
+you could have the following `.compliance-gitlab-ci.yml` configuration:
+
+```yaml
+"compliance job":
+ extends:
+ - .compliance_template
+ stage: build
+
+.compliance_template:
+ script:
+ - echo "take compliance action"
+```
+
+You could also have the following `.gitlab-ci.yml` configuration:
+
+```yaml
+"compliance job":
+ stage: test
+ script:
+ - echo "overwriting compliance action"
+```
+
+This configuration results in the target repository pipeline overwriting the compliance pipeline, and you get the following message:
+`overwriting compliance action`.
+
+To avoid overwriting a compliance job, don't use the `extends` keyword in compliance pipeline configuration. For example,
+you could have the following `.compliance-gitlab-ci.yml` configuration:
+
+```yaml
+"compliance job":
+ stage: build
+ script:
+ - echo "take compliance action"
+```
+
+You could also have the following `.gitlab-ci.yml` configuration:
+
+```yaml
+"compliance job":
+ stage: test
+ script:
+ - echo "overwriting compliance action"
+```
+
+This configuration doesn't overwrite the compliance pipeline and you get the following message:
+`take compliance action`.
+
+### Prefilled variables are not shown
+
+Because of a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/382857),
+compliance pipelines in GitLab 15.3 and later can prevent
+[prefilled variables](../../ci/pipelines/_index.md#prefill-variables-in-manual-pipelines)
+from appearing when manually starting a pipeline.
+
+To workaround this issue, use `ref: '$CI_COMMIT_SHA'` instead of `ref: '$CI_COMMIT_REF_NAME'`
+in the `include:` statement that executes the individual project's configuration.
+
+The [example configuration](#example-configuration) has been updated with this change:
+
+```yaml
+include:
+ - project: '$CI_PROJECT_PATH'
+ file: '$CI_CONFIG_PATH'
+ ref: '$CI_COMMIT_SHA'
+```
+
+### Error: `Job names must be unique`
+
+To configure a compliance pipeline, the [example configuration](#example-configuration) recommends including the
+individual project configuration with `include.project`.
+
+The configuration can lead to an error when running the projects pipeline: `Pipeline execution policy error: Job names must be unique`.
+This error occurs because the pipeline execution policy includes the project's `.gitlab-ci.yml` and tries to insert the
+jobs when the jobs have already been declared in the pipeline.
+
+To resolve this error, remove `include.project` from the separate YAML file linked in the pipeline execution policy.
+
+
diff --git a/doc/user/compliance/license_approval_policies.md b/doc/user/compliance/license_approval_policies.md
index 220cd76de7b..620c2a2015b 100644
--- a/doc/user/compliance/license_approval_policies.md
+++ b/doc/user/compliance/license_approval_policies.md
@@ -43,7 +43,7 @@ License approval policies rely on the output of a dependency scanning job to ver
To ensure enforcement of your policies, you should enable dependency scanning on your target development projects. You can achieve this a few different ways:
- Create a global [scan execution policy](../application_security/policies/scan_execution_policies.md) that enforces Dependency Scanning to run in all target development projects.
-- Use a [Compliance Pipeline](../group/compliance_frameworks.md) to define a Dependency Scanning job that is enforced on projects enforced by a given Compliance Framework.
+- Use a [Compliance Pipeline](../compliance/compliance_frameworks.md) to define a Dependency Scanning job that is enforced on projects enforced by a given Compliance Framework.
- Work with development teams to configure [Dependency Scanning](../application_security/dependency_scanning/_index.md) in each of their project's `.gitlab-ci.yml` files or enable by using the [Security Configuration panel](../application_security/configuration/_index.md).
License approval policies require license information from [GitLab-supported packages](license_scanning_of_cyclonedx_files/_index.md#supported-languages-and-package-managers).
diff --git a/doc/user/group/compliance_frameworks.md b/doc/user/group/compliance_frameworks.md
index e6cd990c3ef..b6d6df66700 100644
--- a/doc/user/group/compliance_frameworks.md
+++ b/doc/user/group/compliance_frameworks.md
@@ -1,112 +1,13 @@
---
-stage: Software Supply Chain Security
-group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
-title: Compliance frameworks
+redirect_to: '../compliance/compliance_frameworks.md'
+remove_date: '2025-05-25'
---
-{{< details >}}
+
-- Tier: Premium, Ultimate
-- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
+This document was moved to [another location](../compliance/compliance_frameworks.md).
-{{< /details >}}
-
-You can create a compliance framework that is a label to identify that your project has certain compliance
-requirements or needs additional oversight.
-
-In the Ultimate tier, the compliance framework can optionally enforce
-[compliance pipeline configuration](compliance_pipelines.md) and
-[security policies](../application_security/policies/_index.md#scope) to the projects on which it is applied.
-
-Compliance frameworks are created on top-level groups. If a project is moved outside of its existing top-level group,
-its frameworks are removed.
-
-You can apply up to 20 compliance frameworks to each project.
-
-For a click-through demo, see [Compliance frameworks](https://gitlab.navattic.com/compliance).
-
-
-## Prerequisites
-
-- To create, edit, and delete compliance frameworks, users must have either:
- - The Owner role for the top-level group.
- - Be assigned a [custom role](../custom_roles.md) with the `admin_compliance_framework`
- [custom permission](../custom_roles/abilities.md#compliance-management).
-- To add or remove a compliance framework to or from a project, the group to which the project belongs must have a
- compliance framework.
-
-## Create, edit, or delete a compliance framework
-
-You can create, edit, or delete a compliance framework from a compliance framework report. For more information, see:
-
-- [Create a new compliance framework](../compliance/compliance_center/compliance_frameworks_report.md#create-a-new-compliance-framework).
-- [Edit a compliance framework](../compliance/compliance_center/compliance_frameworks_report.md#edit-a-compliance-framework).
-- [Delete a compliance framework](../compliance/compliance_center/compliance_frameworks_report.md#delete-a-compliance-framework).
-
-You can create, edit, or delete a compliance framework from a compliance projects report. For more information, see:
-
-- [Create a new compliance framework](../compliance/compliance_center/compliance_projects_report.md#create-a-new-compliance-framework).
-- [Edit a compliance framework](../compliance/compliance_center/compliance_projects_report.md#edit-a-compliance-framework).
-- [Delete a compliance framework](../compliance/compliance_center/compliance_projects_report.md#delete-a-compliance-framework).
-
-Subgroups and projects have access to all compliance frameworks created on their top-level group. However, compliance frameworks cannot be created, edited,
-or deleted at the subgroup or project level. Project owners can choose a framework to apply to their projects.
-
-## Apply a compliance framework to a project
-
-{{< history >}}
-
-- Assigning multiple compliance frameworks [introduced](https://gitlab.com/groups/gitlab-org/-/epics/13294) in GitLab 17.3.
-
-{{< /history >}}
-
-You can apply multiple compliance frameworks to a project but cannot apply compliance frameworks to projects in personal namespaces.
-
-To apply a compliance framework to a project, apply the compliance framework through the
-[Compliance projects report](../compliance/compliance_center/compliance_projects_report.md#apply-a-compliance-framework-to-projects-in-a-group).
-
-You can use the [GraphQL API](../../api/graphql/reference/_index.md#mutationprojectupdatecomplianceframeworks) to apply one or many
-compliance frameworks to a project.
-
-If you create compliance frameworks on subgroups with GraphQL, the framework is created on the root ancestor if the user
-has the correct permissions. The GitLab UI presents a read-only view to discourage this behavior.
-
-## Default compliance frameworks
-
-{{< history >}}
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/375036) in GitLab 15.6.
-
-{{< /history >}}
-
-Group owners can set a default compliance framework. The default framework is applied to all the new and imported
-projects that are created in that group. It does not affect the framework applied to the existing projects. The
-default framework cannot be deleted.
-
-A compliance framework that is set to default has a **default** label.
-
-### Set and remove a default by using the compliance center
-
-To set as default (or remove the default) from [compliance projects report](../compliance/compliance_center/compliance_projects_report.md):
-
-1. On the left sidebar, select **Search or go to** and find your group.
-1. Select **Secure > Compliance center**.
-1. On the page, select the **Projects** tab.
-1. Hover over a compliance framework, select the **Edit Framework** tab.
-1. Select **Set as default**.
-1. Select **Save changes**.
-
-To set as default (or remove the default) from [compliance framework report](../compliance/compliance_center/compliance_frameworks_report.md):
-
-1. On the left sidebar, select **Search or go to** and find your group.
-1. Select **Secure > Compliance center**.
-1. On the page, select the **Frameworks** tab.
-1. Hover over a compliance framework, select the **Edit Framework** tab.
-1. Select **Set as default**.
-1. Select **Save changes**.
-
-## Remove a compliance framework from a project
-
-To remove a compliance framework from one or multiple project in a group, remove the compliance framework through the
-[Compliance projects report](../compliance/compliance_center/compliance_projects_report.md#remove-a-compliance-framework-from-projects-in-a-group).
+
+
+
+
\ No newline at end of file
diff --git a/doc/user/group/compliance_pipelines.md b/doc/user/group/compliance_pipelines.md
index 59372d7a79d..5e8d166a477 100644
--- a/doc/user/group/compliance_pipelines.md
+++ b/doc/user/group/compliance_pipelines.md
@@ -1,416 +1,13 @@
---
-stage: Software Supply Chain Security
-group: Compliance
-info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://handbook.gitlab.com/handbook/product/ux/technical-writing/#assignments
-title: Compliance pipelines (deprecated)
+redirect_to: '../compliance/compliance_pipelines.md'
+remove_date: '2025-05-25'
---
-
+
-{{< details >}}
+This document was moved to [another location](../compliance/compliance_pipelines.md).
-- Tier: Ultimate
-- Offering: GitLab.com, GitLab Self-Managed, GitLab Dedicated
-
-{{< /details >}}
-
-{{< alert type="warning" >}}
-
-This feature was [deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/159841) in GitLab 17.3
-and is planned for removal in 19.0. Use [pipeline execution policy type](../application_security/policies/pipeline_execution_policies.md) instead.
-This change is a breaking change. For more information, see the [migration guide](#pipeline-execution-policies-migration).
-
-{{< /alert >}}
-
-Group owners can configure a compliance pipeline in a project separate to other projects. By default, the compliance
-pipeline configuration (for example, `.compliance-gitlab-ci.yml`) is run instead of the pipeline configuration (for example, `.gitlab-ci.yml`) of labeled
-projects.
-
-However, the compliance pipeline configuration can reference the `.gitlab-ci.yml` file of the labeled projects so that:
-
-- The compliance pipeline can also run jobs of labeled project pipelines. This allows for centralized control of
- pipeline configuration.
-- Jobs and variables defined in the compliance pipeline can't be changed by variables in the labeled project's
- `.gitlab-ci.yml` file.
-
-{{< alert type="note" >}}
-
-Because of a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/414004), project pipelines must be included first at the top of compliance pipeline configuration
-to prevent projects overriding settings downstream.
-
-{{< /alert >}}
-
-For more information, see:
-
-- [Example configuration](#example-configuration) for help configuring a compliance pipeline that runs jobs from
- labeled project pipeline configuration.
-- The [Create a compliance pipeline](../../tutorials/compliance_pipeline/_index.md) tutorial.
-
-## Pipeline execution policies migration
-
-To consolidate and simplify scan and pipeline enforcement, we have introduced pipeline execution policies. We deprecated
-compliance pipelines in GitLab 17.3 and will remove compliance pipelines in GitLab 19.0.
-
-Pipeline execution policies extend a project's `.gitlab-ci.yml` file with the configuration provided in separate YAML file
-(for example, `pipeline-execution.yml`) linked in the pipeline execution policy.
-
-By default, when creating a new compliance framework, you are directed to use the pipeline execution policy type instead
-of compliance pipelines.
-
-Existing compliance pipelines must be migrated. Customers should migrate from compliance pipelines to the new
-[pipeline execution policy type](../application_security/policies/pipeline_execution_policies.md) as soon as possible.
-
-### Migrate an existing compliance framework
-
-To migrate an existing compliance framework to use the pipeline execution policy type:
-
-1. On the left sidebar, select **Search or go to** and find your group.
-1. Select **Secure > Compliance center**.
-1. [Edit](compliance_frameworks.md#create-edit-or-delete-a-compliance-framework) the existing compliance framework.
-1. In the banner than appears, select **Migrate pipeline to a policy** to create a new policy in the security policies.
-1. Edit the compliance framework again to remove the compliance pipeline.
-
-For more information, see [Security policy project](../application_security/policies/_index.md#security-policy-project).
-
-If you receive a `Pipeline execution policy error: Job names must be unique` error during the migration, see the
-[relevant troubleshooting information](#error-job-names-must-be-unique).
-
-## Effect on labeled projects
-
-Users have no way of knowing that a compliance pipeline has been configured and might be confused why their own
-pipelines are not running at all, or include jobs that they did not define themselves.
-
-When authoring pipelines on a labeled project, there is no indication that a compliance pipeline has been configured.
-The only marker at the project level is the compliance framework label itself, but the label does not say whether the
-framework has a compliance pipeline configured or not.
-
-Therefore, communicate with project users about compliance pipeline configuration to reduce uncertainty and confusion.
-
-### Multiple compliance frameworks
-
-You can [apply to a single project](compliance_frameworks.md#apply-a-compliance-framework-to-a-project) multiple compliance frameworks with compliance pipelines configured.
-In this case, only the first compliance framework applied to a project has its compliance pipeline included in the project pipeline.
-
-To ensure that the correct compliance pipeline is included in a project:
-
-1. Remove all compliance frameworks from the project.
-1. Apply the compliance framework with the correct compliance pipeline to the project.
-1. Apply additional compliance frameworks to the project.
-
-## Configure a compliance pipeline
-
-{{< history >}}
-
-- [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/383209) in GitLab 15.11, compliance frameworks moved to compliance center.
-
-{{< /history >}}
-
-To configure a compliance pipeline:
-
-1. On the left sidebar, select **Search or go to** and find your group.
-1. Select **Secure** > **Compliance Center**.
-1. Select **Frameworks** section.
-1. Select **New framework** section, add information of compliance framework including path to the compliance framework configuration. Use the
- `path/file.y[a]ml@group-name/project-name` format. For example:
-
- - `.compliance-ci.yml@gitlab-org/gitlab`.
- - `.compliance-ci.yaml@gitlab-org/gitlab`.
-
-This configuration is inherited by projects where the compliance framework label is
-[applied](../project/working_with_projects.md#add-a-compliance-framework-to-a-project). In projects with the applied compliance
-framework label, the compliance pipeline configuration is run instead of the labeled project's own pipeline configuration.
-
-The user running the pipeline in the labeled project must at least have the Reporter role on the compliance project.
-
-When used to enforce scan execution, this feature has some overlap with
-[scan execution policies](../application_security/policies/scan_execution_policies.md). We have not
-[unified the user experience for these two features](https://gitlab.com/groups/gitlab-org/-/epics/7312). For details on
-the similarities and differences between these features, see [Enforce scan execution](../application_security/_index.md#enforce-scan-execution).
-
-### Example configuration
-
-The following example `.compliance-gitlab-ci.yml` includes the `include` keyword to ensure labeled project pipeline
-configuration is also executed.
-
-```yaml
-include: # Execute individual project's configuration (if project contains .gitlab-ci.yml)
- - project: '$CI_PROJECT_PATH'
- file: '$CI_CONFIG_PATH'
- ref: '$CI_COMMIT_SHA' # Must be defined or MR pipelines always use the use default branch
- rules:
- - if: $CI_PROJECT_PATH != "my-group/project-1" # Must run on projects other than the one hosting this configuration.
-
-# Allows compliance team to control the ordering and interweaving of stages/jobs.
-# Stages without jobs defined will remain hidden.
-stages:
- - pre-compliance
- - build
- - test
- - pre-deploy-compliance
- - deploy
- - post-compliance
-
-variables: # Can be overridden by setting a job-specific variable in project's local .gitlab-ci.yml
- FOO: sast
-
-sast: # None of these attributes can be overridden by a project's local .gitlab-ci.yml
- variables:
- FOO: sast
- image: ruby:2.6
- stage: pre-compliance
- rules:
- - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
- when: never
- - when: always # or when: on_success
- allow_failure: false
- before_script:
- - "# No before scripts."
- script:
- - echo "running $FOO"
- after_script:
- - "# No after scripts."
-
-sanity check:
- image: ruby:2.6
- stage: pre-deploy-compliance
- rules:
- - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
- when: never
- - when: always # or when: on_success
- allow_failure: false
- before_script:
- - "# No before scripts."
- script:
- - echo "running $FOO"
- after_script:
- - "# No after scripts."
-
-audit trail:
- image: ruby:2.7
- stage: post-compliance
- rules:
- - if: $CI_COMMIT_BRANCH && $CI_OPEN_MERGE_REQUESTS && $CI_PIPELINE_SOURCE == "push"
- when: never
- - when: always # or when: on_success
- allow_failure: false
- before_script:
- - "# No before scripts."
- script:
- - echo "running $FOO"
- after_script:
- - "# No after scripts."
-```
-
-The `rules` configuration in the `include` definition avoids circular inclusion in case the compliance pipeline must be able to run in the host project itself.
-You can leave it out if your compliance pipeline only ever runs in labeled projects.
-
-#### Compliance pipelines and custom pipeline configuration hosted externally
-
-The example above assumes that all projects host their pipeline configuration in the same project.
-If any projects use [configuration hosted externally](../../ci/pipelines/settings.md#specify-a-custom-cicd-configuration-file),
-the example configuration does not work. See [issue 393960](https://gitlab.com/gitlab-org/gitlab/-/issues/393960)
-for more details.
-
-With projects that use externally hosted configuration, you can try the this workaround:
-
-- The `include` section in the example compliance pipeline configuration must be adjusted.
- For example, using [`include:rules`](../../ci/yaml/includes.md#use-rules-with-include):
-
- ```yaml
- include:
- # If the custom path variables are defined, include the project's external config file.
- - project: '$PROTECTED_PIPELINE_CI_PROJECT_PATH'
- file: '$PROTECTED_PIPELINE_CI_CONFIG_PATH'
- ref: '$PROTECTED_PIPELINE_CI_REF'
- rules:
- - if: $PROTECTED_PIPELINE_CI_PROJECT_PATH && $PROTECTED_PIPELINE_CI_CONFIG_PATH && $PROTECTED_PIPELINE_CI_REF
- # If any custom path variable is not defined, include the project's internal config file as normal.
- - project: '$CI_PROJECT_PATH'
- file: '$CI_CONFIG_PATH'
- ref: '$CI_COMMIT_SHA'
- rules:
- - if: $PROTECTED_PIPELINE_CI_PROJECT_PATH == null || $PROTECTED_PIPELINE_CI_CONFIG_PATH == null || $PROTECTED_PIPELINE_CI_REF == null
- ```
-
-- [CI/CD variables](../../ci/variables/_index.md) must be added to projects with external
- pipeline configuration. In this example:
-
- - `PROTECTED_PIPELINE_CI_PROJECT_PATH`: The path to the project hosting the configuration file, for example `group/subgroup/project`.
- - `PROTECTED_PIPELINE_CI_CONFIG_PATH`: The path to the configuration file in the project, for example `path/to/.gitlab-ci.yml`.
- - `PROTECTED_PIPELINE_CI_REF`: The ref to use when retrieving the configuration file, for example `main`.
-
-#### Compliance pipelines in merge requests originating in project forks
-
-When a merge request originates in a fork, the branch to be merged usually only exists in the fork.
-When creating such a merge request against a project with compliance pipelines, the above snippet fails with a
-`Project reference does not exist!` error message.
-This error occurs because in the context of the target project, `$CI_COMMIT_REF_NAME` evaluates to a non-existing
-branch name.
-
-To get the correct context, use `$CI_MERGE_REQUEST_SOURCE_PROJECT_PATH` instead of `$CI_PROJECT_PATH`.
-This variable is only available in
-[merge request pipelines](../../ci/pipelines/merge_request_pipelines.md).
-
-For example, for a configuration that supports both merge request pipelines originating in project forks and branch pipelines,
-you need to [combine both `include` directives with `rules:if`](../../ci/yaml/includes.md#use-rules-with-include):
-
-```yaml
-include: # Execute individual project's configuration (if project contains .gitlab-ci.yml)
- - project: '$CI_MERGE_REQUEST_SOURCE_PROJECT_PATH'
- file: '$CI_CONFIG_PATH'
- ref: '$CI_COMMIT_REF_NAME'
- rules:
- - if: $CI_PIPELINE_SOURCE == 'merge_request_event'
- - project: '$CI_PROJECT_PATH'
- file: '$CI_CONFIG_PATH'
- ref: '$CI_COMMIT_REF_NAME'
- rules:
- - if: $CI_PIPELINE_SOURCE != 'merge_request_event'
-```
-
-#### Compliance pipelines in projects with no configuration file
-
-The [example configuration](#example-configuration) above assumes that all projects contain
-a pipeline configuration file (`.gitlab-ci.yml` by default). However, in projects
-with no configuration file (and therefore no pipelines by default), the compliance pipeline
-fails because the file specified in `include:project` is required.
-
-To only include a configuration file if it exists in a target project, use
-[`rules:exists:project`](../../ci/yaml/_index.md#rulesexistsproject):
-
-```yaml
-include: # Execute individual project's configuration
- - project: '$CI_PROJECT_PATH'
- file: '$CI_CONFIG_PATH'
- ref: '$CI_COMMIT_SHA'
- rules:
- - exists:
- paths:
- - '$CI_CONFIG_PATH'
- project: '$CI_PROJECT_PATH'
- ref: '$CI_COMMIT_SHA'
-```
-
-In this example, a configuration file is only included if it exists for the given `ref`
-in the project in `exists:project: $CI_PROJECT_PATH'`.
-
-If `exists:project` is not specified in the compliance pipeline configuration, it searches for files in the project
-in which the `include` is defined. In compliance pipelines, the `include` from the example above
-is defined in the project hosting the compliance pipeline configuration file, not the project
-running the pipeline.
-
-## Ensure compliance jobs are always run
-
-Compliance pipelines [use GitLab CI/CD](../../ci/_index.md) to give you an incredible amount of flexibility
-for defining any sort of compliance jobs you like. Depending on your goals, these jobs
-can be configured to be:
-
-- Modified by users.
-- Non-modifiable.
-
-Generally, if a value in a compliance job:
-
-- Is set, it cannot be changed or overridden by project-level configurations.
-- Is not set, a project-level configuration may be set.
-
-Either might be wanted or not depending on your use case.
-
-The following are a few best practices for ensuring that these jobs are always run exactly
-as you define them and that downstream, project-level pipeline configurations
-cannot change them:
-
-- Add [a `rules:when:always` block](../../ci/yaml/_index.md#when) to each of your compliance jobs. This ensures they are
- non-modifiable and are always run.
-- Explicitly set any [variables](../../ci/yaml/_index.md#variables) the job references. This:
- - Ensures that project-level pipeline configurations do not set them and alter their
- behavior. For example, see `before_script` and `after_script` configuration in the [example configuration](#example-configuration).
- - Includes any jobs that drive the logic of your job.
-- Explicitly set the [container image](../../ci/yaml/_index.md#image) to run the job in. This ensures that your script
- steps execute in the correct environment.
-- Explicitly set any relevant GitLab pre-defined [job keywords](../../ci/yaml/_index.md#job-keywords).
- This ensures that your job uses the settings you intend and that they are not overridden by
- project-level pipelines.
-
-## Troubleshooting
-
-### Compliance jobs are overwritten by target repository
-
-If you use the `extends` statement in a compliance pipeline configuration, compliance jobs are overwritten by the target repository job. For example,
-you could have the following `.compliance-gitlab-ci.yml` configuration:
-
-```yaml
-"compliance job":
- extends:
- - .compliance_template
- stage: build
-
-.compliance_template:
- script:
- - echo "take compliance action"
-```
-
-You could also have the following `.gitlab-ci.yml` configuration:
-
-```yaml
-"compliance job":
- stage: test
- script:
- - echo "overwriting compliance action"
-```
-
-This configuration results in the target repository pipeline overwriting the compliance pipeline, and you get the following message:
-`overwriting compliance action`.
-
-To avoid overwriting a compliance job, don't use the `extends` keyword in compliance pipeline configuration. For example,
-you could have the following `.compliance-gitlab-ci.yml` configuration:
-
-```yaml
-"compliance job":
- stage: build
- script:
- - echo "take compliance action"
-```
-
-You could also have the following `.gitlab-ci.yml` configuration:
-
-```yaml
-"compliance job":
- stage: test
- script:
- - echo "overwriting compliance action"
-```
-
-This configuration doesn't overwrite the compliance pipeline and you get the following message:
-`take compliance action`.
-
-### Prefilled variables are not shown
-
-Because of a [known issue](https://gitlab.com/gitlab-org/gitlab/-/issues/382857),
-compliance pipelines in GitLab 15.3 and later can prevent
-[prefilled variables](../../ci/pipelines/_index.md#prefill-variables-in-manual-pipelines)
-from appearing when manually starting a pipeline.
-
-To workaround this issue, use `ref: '$CI_COMMIT_SHA'` instead of `ref: '$CI_COMMIT_REF_NAME'`
-in the `include:` statement that executes the individual project's configuration.
-
-The [example configuration](#example-configuration) has been updated with this change:
-
-```yaml
-include:
- - project: '$CI_PROJECT_PATH'
- file: '$CI_CONFIG_PATH'
- ref: '$CI_COMMIT_SHA'
-```
-
-### Error: `Job names must be unique`
-
-To configure a compliance pipeline, the [example configuration](#example-configuration) recommends including the
-individual project configuration with `include.project`.
-
-The configuration can lead to an error when running the projects pipeline: `Pipeline execution policy error: Job names must be unique`.
-This error occurs because the pipeline execution policy includes the project's `.gitlab-ci.yml` and tries to insert the
-jobs when the jobs have already been declared in the pipeline.
-
-To resolve this error, remove `include.project` from the separate YAML file linked in the pipeline execution policy.
-
-
+
+
+
+
\ No newline at end of file
diff --git a/doc/user/permissions.md b/doc/user/permissions.md
index cc103ea4525..1aca8607b43 100644
--- a/doc/user/permissions.md
+++ b/doc/user/permissions.md
@@ -469,8 +469,8 @@ Group permissions for [compliance](compliance/_index.md) features including comp
| View [audit events](compliance/audit_events.md) | | | | ✓ | ✓ | ✓ | Users can view only events based on their individual actions. For more details, see the [prerequisites](compliance/audit_events.md#prerequisites). |
| View licenses in the [dependency list](application_security/dependency_list/_index.md) | | | | ✓ | ✓ | ✓ | |
| View the [compliance center](compliance/compliance_center/_index.md) | | | | | | ✓ | |
-| Manage [compliance frameworks](group/compliance_frameworks.md) | | | | | | ✓ | |
-| Assign [compliance frameworks](group/compliance_frameworks.md) to projects | | | | | | ✓ | |
+| Manage [compliance frameworks](compliance/compliance_frameworks.md) | | | | | | ✓ | |
+| Assign [compliance frameworks](compliance/compliance_frameworks.md) to projects | | | | | | ✓ | |
| Manage [audit streams](compliance/audit_event_streaming.md) | | | | | | ✓ | |
### GitLab Duo group permissions
diff --git a/doc/user/project/working_with_projects.md b/doc/user/project/working_with_projects.md
index 6327e75795e..2ff05bd53b7 100644
--- a/doc/user/project/working_with_projects.md
+++ b/doc/user/project/working_with_projects.md
@@ -597,7 +597,7 @@ To leave a project:
{{< /details >}}
-You can add compliance frameworks to projects in a group that has a [compliance framework](../group/compliance_frameworks.md).
+You can add compliance frameworks to projects in a group that has a [compliance framework](../compliance/compliance_frameworks.md).
## Manage project access through LDAP groups
diff --git a/gems/gitlab-http/Gemfile.lock b/gems/gitlab-http/Gemfile.lock
index 1bf4da41da5..4785a657cf9 100644
--- a/gems/gitlab-http/Gemfile.lock
+++ b/gems/gitlab-http/Gemfile.lock
@@ -21,7 +21,7 @@ PATH
gitlab-http (0.1.0)
activesupport (~> 7)
concurrent-ruby (~> 1.2)
- httparty (~> 0.21.0)
+ httparty (~> 0.21)
ipaddress (~> 0.8.3)
net-http (= 0.6.0)
railties (~> 7)
@@ -62,6 +62,7 @@ GEM
crack (0.4.5)
rexml
crass (1.0.6)
+ csv (3.3.2)
debug_inspector (1.2.0)
diff-lcs (1.5.0)
erubi (1.12.0)
@@ -75,7 +76,8 @@ GEM
rubocop-rspec (~> 3.0.4)
rubocop-rspec_rails (~> 2.30.0)
hashdiff (1.0.1)
- httparty (0.21.0)
+ httparty (0.22.0)
+ csv
mini_mime (>= 1.0.0)
multi_xml (>= 0.5.2)
i18n (1.14.1)
diff --git a/gems/gitlab-http/gitlab-http.gemspec b/gems/gitlab-http/gitlab-http.gemspec
index 359fddd209a..405573520d4 100644
--- a/gems/gitlab-http/gitlab-http.gemspec
+++ b/gems/gitlab-http/gitlab-http.gemspec
@@ -21,7 +21,7 @@ Gem::Specification.new do |spec|
spec.add_runtime_dependency 'activesupport', '~> 7'
spec.add_runtime_dependency 'concurrent-ruby', '~> 1.2'
- spec.add_runtime_dependency 'httparty', '~> 0.21.0'
+ spec.add_runtime_dependency 'httparty', '~> 0.21'
spec.add_runtime_dependency 'ipaddress', '~> 0.8.3'
spec.add_runtime_dependency "railties", "~> 7"
# See lib/net_http/connect_patch.rb
diff --git a/lib/api/ci/job_artifacts.rb b/lib/api/ci/job_artifacts.rb
index e64e8c348f6..86d606b64e4 100644
--- a/lib/api/ci/job_artifacts.rb
+++ b/lib/api/ci/job_artifacts.rb
@@ -70,7 +70,8 @@ module API
'available only on Premium and Ultimate tiers.'
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_jobs
+ route_setting :authorization, job_token_policies: :read_jobs,
+ allow_public_access_for_enabled_project_features: [:repository, :builds]
get ':id/jobs/artifacts/:ref_name/raw/*artifact_path',
urgency: :low,
format: false,
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index 714322c4931..66369f450f4 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -392,7 +392,8 @@ module API
optional :direct_download, default: false, type: Boolean, desc: 'Perform direct download from remote storage instead of proxying artifacts'
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_jobs
+ route_setting :authorization, job_token_policies: :read_jobs,
+ allow_public_access_for_enabled_project_features: [:repository, :builds]
get '/:id/artifacts', feature_category: :job_artifacts do
authenticate_job_via_dependent_job!
authorize_job_token_policies!(current_job.project)
diff --git a/lib/api/composer_packages.rb b/lib/api/composer_packages.rb
index 736a27ae8ff..5840ae8db72 100644
--- a/lib/api/composer_packages.rb
+++ b/lib/api/composer_packages.rb
@@ -204,7 +204,8 @@ module API
requires :package_name, type: String, file_path: true, desc: 'The Composer package name', documentation: { example: 'my-composer-package' }
end
route_setting :authentication, job_token_allowed: :basic_auth, basic_auth_personal_access_token: true, deploy_token_allowed: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get 'archives/*package_name', urgency: :default do
project = authorized_user_project(action: :read_package)
authorize_job_token_policies!(project)
diff --git a/lib/api/conan/v2/project_packages.rb b/lib/api/conan/v2/project_packages.rb
index e1469bf5081..add60950f3d 100644
--- a/lib/api/conan/v2/project_packages.rb
+++ b/lib/api/conan/v2/project_packages.rb
@@ -59,7 +59,8 @@ module API
tags %w[conan_packages]
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get urgency: :low do
download_package_file(:recipe_file)
end
diff --git a/lib/api/concerns/packages/conan/v1_endpoints.rb b/lib/api/concerns/packages/conan/v1_endpoints.rb
index cae70eb2de9..6faf8f10b4e 100644
--- a/lib/api/concerns/packages/conan/v1_endpoints.rb
+++ b/lib/api/concerns/packages/conan/v1_endpoints.rb
@@ -110,7 +110,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get 'packages/:conan_package_reference', urgency: :low do
authorize_read_package!(project)
@@ -137,7 +138,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get urgency: :low do
authorize_read_package!(project)
@@ -168,7 +170,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get 'packages/:conan_package_reference/digest', urgency: :low do
present_package_download_urls
@@ -186,7 +189,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get 'digest', urgency: :low do
present_recipe_download_urls
@@ -215,7 +219,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get 'packages/:conan_package_reference/download_urls', urgency: :low do
present_package_download_urls
@@ -233,7 +238,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get 'download_urls', urgency: :low do
present_recipe_download_urls
@@ -263,7 +269,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
post 'packages/:conan_package_reference/upload_urls', urgency: :low do
authorize_read_package!(project)
@@ -284,7 +291,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
post 'upload_urls', urgency: :low do
authorize_read_package!(project)
@@ -358,7 +366,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get urgency: :low do
download_package_file(:recipe_file)
@@ -430,7 +439,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get urgency: :low do
download_package_file(:package_file)
diff --git a/lib/api/concerns/packages/npm_endpoints.rb b/lib/api/concerns/packages/npm_endpoints.rb
index 15053871925..65f944e36f0 100644
--- a/lib/api/concerns/packages/npm_endpoints.rb
+++ b/lib/api/concerns/packages/npm_endpoints.rb
@@ -79,7 +79,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true,
authenticate_non_public: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get 'dist-tags', format: false, requirements: ::API::Helpers::Packages::Npm::NPM_ENDPOINT_REQUIREMENTS do
package_name = params[:package_name]
@@ -194,7 +195,8 @@ module API
tags %w[npm_packages]
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
post '-/npm/v1/security/advisories/bulk' do
redirect_or_present_audit_report
end
@@ -214,7 +216,8 @@ module API
tags %w[npm_packages]
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
post '-/npm/v1/security/audits/quick' do
redirect_or_present_audit_report
end
diff --git a/lib/api/concerns/packages/npm_namespace_endpoints.rb b/lib/api/concerns/packages/npm_namespace_endpoints.rb
index f3224702a3c..879db486540 100644
--- a/lib/api/concerns/packages/npm_namespace_endpoints.rb
+++ b/lib/api/concerns/packages/npm_namespace_endpoints.rb
@@ -59,7 +59,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true,
authenticate_non_public: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get '*package_name', format: false, requirements: ::API::Helpers::Packages::Npm::NPM_ENDPOINT_REQUIREMENTS do
package_name = declared_params[:package_name]
packages =
diff --git a/lib/api/deployments.rb b/lib/api/deployments.rb
index ef93f70c4b5..17bcc029283 100644
--- a/lib/api/deployments.rb
+++ b/lib/api/deployments.rb
@@ -69,7 +69,8 @@ module API
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_deployments
+ route_setting :authorization, job_token_policies: :read_deployments,
+ allow_public_access_for_enabled_project_features: [:repository, :builds, :environments]
get ':id/deployments' do
authorize! :read_deployment, user_project
@@ -95,7 +96,8 @@ module API
requires :deployment_id, type: Integer, desc: 'The ID of the deployment'
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_deployments
+ route_setting :authorization, job_token_policies: :read_deployments,
+ allow_public_access_for_enabled_project_features: [:repository, :builds, :environments]
get ':id/deployments/:deployment_id' do
authorize! :read_deployment, user_project
@@ -251,7 +253,8 @@ module API
use :merge_requests_base_params
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_deployments
+ route_setting :authorization, job_token_policies: :read_deployments,
+ allow_public_access_for_enabled_project_features: [:repository, :builds, :environments]
get ':id/deployments/:deployment_id/merge_requests' do
authorize! :read_deployment, user_project
diff --git a/lib/api/environments.rb b/lib/api/environments.rb
index 046cc171676..8a7dcdaa6ea 100644
--- a/lib/api/environments.rb
+++ b/lib/api/environments.rb
@@ -39,7 +39,8 @@ module API
mutually_exclusive :name, :search, message: 'cannot be used together'
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_environments
+ route_setting :authorization, job_token_policies: :read_environments,
+ allow_public_access_for_enabled_project_features: [:repository, :builds, :environments]
get ':id/environments' do
authorize! :read_environment, user_project
@@ -271,7 +272,8 @@ module API
requires :environment_id, type: Integer, desc: 'The ID of the environment'
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_environments
+ route_setting :authorization, job_token_policies: :read_environments,
+ allow_public_access_for_enabled_project_features: [:repository, :builds, :environments]
get ':id/environments/:environment_id' do
authorize! :read_environment, user_project
diff --git a/lib/api/generic_packages.rb b/lib/api/generic_packages.rb
index 9404e5e1397..5c28303c5ec 100644
--- a/lib/api/generic_packages.rb
+++ b/lib/api/generic_packages.rb
@@ -128,7 +128,8 @@ module API
end
route_setting :authentication, job_token_allowed: %i[request basic_auth], basic_auth_personal_access_token: true, deploy_token_allowed: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get do
project = authorized_user_project(action: :read_package)
diff --git a/lib/api/go_proxy.rb b/lib/api/go_proxy.rb
index eaedc1531db..6badf5d79ef 100755
--- a/lib/api/go_proxy.rb
+++ b/lib/api/go_proxy.rb
@@ -69,7 +69,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, basic_auth_personal_access_token: true,
authenticate_non_public: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
resource :projects, requirements: API::NAMESPACE_OR_PROJECT_REQUIREMENTS do
before do
authorize_read_package!(project)
diff --git a/lib/api/helpers.rb b/lib/api/helpers.rb
index 74a9120a477..d72d9cf8f99 100644
--- a/lib/api/helpers.rb
+++ b/lib/api/helpers.rb
@@ -1038,6 +1038,7 @@ module API
return true unless current_user&.from_ci_job_token?
return true unless Feature.enabled?(:add_policies_to_ci_job_token, project)
return true if skip_job_token_policies?
+ return true if publicly_accessible_feature?(project)
current_user.ci_job_token_scope.policies_allowed?(project, job_token_policies)
end
@@ -1069,6 +1070,19 @@ module API
route_setting(:authorization).try(:fetch, :skip_job_token_policies, false)
end
+
+ def publicly_accessible_feature?(project)
+ return false unless respond_to?(:route_setting)
+ return false unless project.public? || project.internal?
+ return false unless project&.project_feature
+
+ project_features = Array(route_setting(:authorization).try(:fetch, :allow_public_access_for_enabled_project_features, nil))
+ return false if project_features.empty?
+
+ project_features.all? do |project_feature|
+ project.project_feature.access_level(project_feature) >= ProjectFeature::ENABLED
+ end
+ end
end
end
diff --git a/lib/api/maven_packages.rb b/lib/api/maven_packages.rb
index 5e25f8b81e0..6eddd7f5a5b 100644
--- a/lib/api/maven_packages.rb
+++ b/lib/api/maven_packages.rb
@@ -102,7 +102,8 @@ module API
use :path_and_file_name
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get 'packages/maven/*path/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do
# return a similar failure to authorize_read_package!(project)
@@ -158,7 +159,8 @@ module API
use :path_and_file_name
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get ':id/-/packages/maven/*path/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do
# return a similar failure to group = find_group(params[:id])
group = find_authorized_group!(action: :read_package_within_public_registries)
@@ -200,7 +202,8 @@ module API
use :path_and_file_name
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true, basic_auth_personal_access_token: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get ':id/packages/maven/*path/:file_name', requirements: MAVEN_ENDPOINT_REQUIREMENTS do
project = authorized_user_project(action: :read_package)
diff --git a/lib/api/npm_project_packages.rb b/lib/api/npm_project_packages.rb
index 31529343901..e04063761a1 100644
--- a/lib/api/npm_project_packages.rb
+++ b/lib/api/npm_project_packages.rb
@@ -61,7 +61,8 @@ module API
requires :file_name, type: String, desc: 'Package file name'
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get '*package_name/-/*file_name', format: false do
authorize_read_package!(project)
@@ -141,7 +142,8 @@ module API
end
route_setting :authentication, job_token_allowed: true, deploy_token_allowed: true,
authenticate_non_public: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get '*package_name', format: false, requirements: ::API::Helpers::Packages::Npm::NPM_ENDPOINT_REQUIREMENTS do
package_name = declared_params[:package_name]
packages = ::Packages::Npm::PackageFinder.new(project: project_or_nil, params: { package_name: package_name }).execute
diff --git a/lib/api/package_files.rb b/lib/api/package_files.rb
index df0ceddb5eb..9f9ad173d32 100644
--- a/lib/api/package_files.rb
+++ b/lib/api/package_files.rb
@@ -31,7 +31,8 @@ module API
use :pagination
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get ':id/packages/:package_id/package_files' do
package = ::Packages::PackageFinder
.new(user_project, params[:package_id]).execute
diff --git a/lib/api/project_packages.rb b/lib/api/project_packages.rb
index 9be1a97a4e7..99d9658d9d5 100644
--- a/lib/api/project_packages.rb
+++ b/lib/api/project_packages.rb
@@ -54,7 +54,8 @@ module API
desc: 'Return packages with specified status'
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get ':id/packages' do
packages = ::Packages::PackagesFinder.new(
user_project,
@@ -77,7 +78,8 @@ module API
requires :package_id, type: Integer, desc: 'The ID of a package'
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get ':id/packages/:package_id' do
render_api_error!('Package not found', 404) unless package.detailed_info?
@@ -104,7 +106,8 @@ module API
values: 1..20
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get ':id/packages/:package_id/pipelines' do
not_found!('Package not found') unless package.detailed_info?
diff --git a/lib/api/pypi_packages.rb b/lib/api/pypi_packages.rb
index d50ce9a6798..37cd169c4e4 100644
--- a/lib/api/pypi_packages.rb
+++ b/lib/api/pypi_packages.rb
@@ -131,7 +131,8 @@ module API
end
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get 'files/:sha256/*file_identifier' do
group = find_authorized_group!
authorize_read_package!(group)
@@ -212,7 +213,8 @@ module API
end
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get 'files/:sha256/*file_identifier' do
project = project!
authorize_job_token_policies!(project)
@@ -240,7 +242,8 @@ module API
# An API entry point but returns an HTML file instead of JSON.
# PyPi simple API returns a list of packages as a simple HTML file.
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get 'simple', format: :txt do
project = project!
authorize_job_token_policies!(project)
@@ -265,7 +268,8 @@ module API
# An API entry point but returns an HTML file instead of JSON.
# PyPi simple API returns the package descriptor as a simple HTML file.
route_setting :authentication, deploy_token_allowed: true, basic_auth_personal_access_token: true, job_token_allowed: :basic_auth
- route_setting :authorization, job_token_policies: :read_packages
+ route_setting :authorization, job_token_policies: :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry
get 'simple/*package_name', format: :txt do
project = project!
authorize_job_token_policies!(project)
diff --git a/lib/api/release/links.rb b/lib/api/release/links.rb
index 06dd5e06754..e38b8a3049d 100644
--- a/lib/api/release/links.rb
+++ b/lib/api/release/links.rb
@@ -38,7 +38,8 @@ module API
use :pagination
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_releases
+ route_setting :authorization, job_token_policies: :read_releases,
+ allow_public_access_for_enabled_project_features: :releases
get 'links' do
authorize! :read_release, release
@@ -95,7 +96,8 @@ module API
tags release_links_tags
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_releases
+ route_setting :authorization, job_token_policies: :read_releases,
+ allow_public_access_for_enabled_project_features: :releases
get do
authorize! :read_release, release
diff --git a/lib/api/releases.rb b/lib/api/releases.rb
index e02aad88d31..3a99271ca19 100644
--- a/lib/api/releases.rb
+++ b/lib/api/releases.rb
@@ -98,7 +98,8 @@ module API
optional :updated_after, type: DateTime, desc: 'Return releases updated after the specified datetime. Format: ISO 8601 YYYY-MM-DDTHH:MM:SSZ'
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_releases
+ route_setting :authorization, job_token_policies: :read_releases,
+ allow_public_access_for_enabled_project_features: [:repository, :releases]
get ':id/releases' do
releases = ::ReleasesFinder.new(user_project, current_user, declared_params.slice(:order_by, :sort, :updated_before, :updated_after)).execute
@@ -134,7 +135,8 @@ module API
desc: 'If `true`, a response includes HTML rendered markdown of the release description'
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_releases
+ route_setting :authorization, job_token_policies: :read_releases,
+ allow_public_access_for_enabled_project_features: [:repository, :releases]
get ':id/releases/:tag_name', requirements: RELEASE_ENDPOINT_REQUIREMENTS do
authorize_read_code!
@@ -162,7 +164,8 @@ module API
as: :filepath
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_releases
+ route_setting :authorization, job_token_policies: :read_releases,
+ allow_public_access_for_enabled_project_features: [:repository, :releases]
get ':id/releases/:tag_name/downloads/*direct_asset_path', format: false, requirements: RELEASE_ENDPOINT_REQUIREMENTS do
authorize_read_code!
@@ -191,7 +194,8 @@ module API
desc: 'The path to be suffixed to the latest release'
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_releases
+ route_setting :authorization, job_token_policies: :read_releases,
+ allow_public_access_for_enabled_project_features: [:repository, :releases]
get ':id/releases/permalink/latest(/)(*suffix_path)', format: false, requirements: RELEASE_ENDPOINT_REQUIREMENTS do
authorize_read_code!
diff --git a/lib/api/repositories.rb b/lib/api/repositories.rb
index 6a8358957e9..60f86704ba5 100644
--- a/lib/api/repositories.rb
+++ b/lib/api/repositories.rb
@@ -293,7 +293,8 @@ module API
desc: "The file path to the configuration file as stored in the project's Git repository. Defaults to '.gitlab/changelog_config.yml'"
end
route_setting :authentication, job_token_allowed: true
- route_setting :authorization, job_token_policies: :read_releases
+ route_setting :authorization, job_token_policies: :read_releases,
+ allow_public_access_for_enabled_project_features: :repository
get ':id/repository/changelog' do
check_rate_limit!(:project_repositories_changelog, scope: [current_user, user_project]) do
render_api_error!({ error: 'This changelog has been requested too many times. Try again later.' }, 429)
diff --git a/package.json b/package.json
index d053ffcfa30..c4fbdc2ad44 100644
--- a/package.json
+++ b/package.json
@@ -63,7 +63,7 @@
"@gitlab/fonts": "^1.3.0",
"@gitlab/query-language-rust": "0.4.0",
"@gitlab/svgs": "3.123.0",
- "@gitlab/ui": "108.3.1",
+ "@gitlab/ui": "108.4.1",
"@gitlab/vue-router-vue3": "npm:vue-router@4.5.0",
"@gitlab/vuex-vue3": "npm:vuex@4.1.0",
"@gitlab/web-ide": "^0.0.1-dev-20250211142744",
diff --git a/spec/frontend/authentication/password/components/password_input_spec.js b/spec/frontend/authentication/password/components/password_input_spec.js
index c52baf87451..ee71184a270 100644
--- a/spec/frontend/authentication/password/components/password_input_spec.js
+++ b/spec/frontend/authentication/password/components/password_input_spec.js
@@ -40,6 +40,7 @@ describe('PasswordInput', () => {
expect(passwordInput.attributes('data-testid')).toBe(propsData.testid);
expect(passwordInput.attributes('title')).toBe(propsData.title);
expect(passwordInput.attributes('required')).toBe('true');
+ expect(passwordInput.attributes('disabled')).toBeUndefined();
});
describe('when password input is not required', () => {
@@ -73,4 +74,13 @@ describe('PasswordInput', () => {
});
});
});
+
+ describe('when password input is disabled', () => {
+ it('disables the input field and the toggle button', () => {
+ wrapper = createComponent({ disabled: true });
+
+ expect(findPasswordInput().attributes('disabled')).toBeDefined();
+ expect(findToggleButton().attributes('disabled')).toBeDefined();
+ });
+ });
});
diff --git a/spec/lib/api/helpers_spec.rb b/spec/lib/api/helpers_spec.rb
index 6075a0aa8ad..375240a0ab8 100644
--- a/spec/lib/api/helpers_spec.rb
+++ b/spec/lib/api/helpers_spec.rb
@@ -334,6 +334,16 @@ RSpec.describe API::Helpers, feature_category: :shared do
it { is_expected.to eq project }
end
+
+ context 'when the project feature is publicly accessible' do
+ let_it_be(:project) { create(:project, :public, :builds_enabled) }
+
+ before do
+ allow(helper).to receive(:route_setting).with(:authorization).and_return(allow_public_access_for_enabled_project_features: :builds)
+ end
+
+ it { is_expected.to eq project }
+ end
end
context 'when no policy is given' do
diff --git a/spec/models/ci/build_spec.rb b/spec/models/ci/build_spec.rb
index 3a6e154641d..3842000a931 100644
--- a/spec/models/ci/build_spec.rb
+++ b/spec/models/ci/build_spec.rb
@@ -5112,79 +5112,7 @@ RSpec.describe Ci::Build, feature_category: :continuous_integration, factory_def
build.clear_memoization(:build_data)
end
- context 'when ci_async_build_hooks_execution flag is disabled' do
- before do
- stub_feature_flags(ci_async_build_hooks_execution: false)
- end
-
- context 'with project services' do
- before do
- create(:integration, active: true, job_events: true, project: project)
- end
-
- it 'executes services' do
- allow_next_instance_of(Integration) do |integration|
- expect(integration).to receive(:async_execute)
- end
-
- build.execute_hooks
- end
- end
-
- context 'without relevant project services' do
- before do
- create(:integration, active: true, job_events: false, project: project)
- end
-
- it 'does not execute services' do
- allow_next_instance_of(Integration) do |integration|
- expect(integration).not_to receive(:async_execute)
- end
-
- build.execute_hooks
- end
- end
-
- context 'with project hooks' do
- let(:build_data) { double(:BuildData, dup: double(:DupedData)) }
-
- before do
- create(:project_hook, project: project, job_events: true)
- end
-
- it 'executes hooks' do
- expect(::Gitlab::DataBuilder::Build)
- .to receive(:build).with(build).and_return(build_data)
-
- expect(build.project)
- .to receive(:execute_hooks).with(build_data.dup, :job_hooks)
-
- build.execute_hooks
- end
-
- context 'with blocked users' do
- before do
- allow(build).to receive(:user) { FactoryBot.build(:user, :blocked) }
- end
-
- it 'does not execute hooks' do
- expect(build.project).not_to receive(:execute_hooks)
-
- build.execute_hooks
- end
- end
- end
-
- context 'without project hooks' do
- it 'does not execute hooks' do
- expect(build.project).not_to receive(:execute_hooks)
-
- build.execute_hooks
- end
- end
- end
-
- context 'when ci_async_build_hooks_execution flag is enabled' do
+ context 'when project hooks exists' do
let(:build_data) { double(:BuildData) }
before do
diff --git a/spec/models/integrations/campfire_spec.rb b/spec/models/integrations/campfire_spec.rb
index dc92b6b81ad..60c286f46ee 100644
--- a/spec/models/integrations/campfire_spec.rb
+++ b/spec/models/integrations/campfire_spec.rb
@@ -35,6 +35,12 @@ RSpec.describe Integrations::Campfire, feature_category: :integrations do
end
end
+ describe '.help' do
+ it 'links to the help page correctly' do
+ expect(described_class.help).to include('help/api/integrations.md#campfire', 'Learn More')
+ end
+ end
+
describe "#execute" do
let(:user) { build_stubbed(:user) }
let(:project) { build_stubbed(:project, :repository) }
diff --git a/spec/models/integrations/datadog_spec.rb b/spec/models/integrations/datadog_spec.rb
index 882b5722c46..ad6ed58b691 100644
--- a/spec/models/integrations/datadog_spec.rb
+++ b/spec/models/integrations/datadog_spec.rb
@@ -152,11 +152,10 @@ RSpec.describe Integrations::Datadog, feature_category: :integrations do
end
end
- describe '#help' do
- subject { instance.help }
-
- it { is_expected.to be_a(String) }
- it { is_expected.not_to be_empty }
+ describe '.help' do
+ it 'links to the help page correctly' do
+ expect(described_class.help).to include('help/integration/datadog.md', 'How do I set up this integration?')
+ end
end
describe 'upgrade from previous version' do
diff --git a/spec/requests/api/ci/job_artifacts_spec.rb b/spec/requests/api/ci/job_artifacts_spec.rb
index 90b0540dd37..727f70943f3 100644
--- a/spec/requests/api/ci/job_artifacts_spec.rb
+++ b/spec/requests/api/ci/job_artifacts_spec.rb
@@ -506,10 +506,7 @@ RSpec.describe API::Ci::JobArtifacts, feature_category: :job_artifacts do
it_behaves_like 'enforcing job token policies', :read_jobs do
before do
stub_licensed_features(cross_project_pipelines: true)
- end
-
- around do |example|
- Sidekiq::Testing.inline! { example.run }
+ pipeline.update!(status: :success)
end
let(:request) do
@@ -701,6 +698,19 @@ RSpec.describe API::Ci::JobArtifacts, feature_category: :job_artifacts do
expect(response.headers.to_h)
.not_to include('Gitlab-Workhorse-Send-Data' => /artifacts-entry/)
end
+
+ it_behaves_like 'enforcing job token policies', :read_jobs,
+ allow_public_access_for_enabled_project_features: [:repository, :builds] do
+ before do
+ stub_licensed_features(cross_project_pipelines: true)
+ pipeline.update!(status: :success)
+ end
+
+ let(:request) do
+ get api("/projects/#{source_project.id}/jobs/artifacts/#{pipeline.ref}/raw/#{artifact}"),
+ params: { job: job.name, job_token: target_job.token }
+ end
+ end
end
end
diff --git a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
index e7f267c4565..ec239ecf510 100644
--- a/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
+++ b/spec/requests/api/ci/runner/jobs_artifacts_spec.rb
@@ -1082,7 +1082,8 @@ RSpec.describe API::Ci::Runner, :clean_gitlab_redis_shared_state, feature_catego
expect(response).to have_gitlab_http_status(:forbidden)
end
- it_behaves_like 'enforcing job token policies', :read_jobs do
+ it_behaves_like 'enforcing job token policies', :read_jobs,
+ allow_public_access_for_enabled_project_features: [:repository, :builds] do
let(:token) { target_job.token }
let(:request) { download_artifact }
end
diff --git a/spec/requests/api/composer_packages_spec.rb b/spec/requests/api/composer_packages_spec.rb
index 7126a31d49f..555e53ec6eb 100644
--- a/spec/requests/api/composer_packages_spec.rb
+++ b/spec/requests/api/composer_packages_spec.rb
@@ -595,7 +595,8 @@ RSpec.describe API::ComposerPackages, feature_category: :package_registry do
let(:branch) { project.repository.find_branch('master') }
let(:sha) { branch.target }
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
before_all do
project.add_developer(user)
end
diff --git a/spec/requests/api/conan/v2/project_packages_spec.rb b/spec/requests/api/conan/v2/project_packages_spec.rb
index da6774abdda..707cce3c666 100644
--- a/spec/requests/api/conan/v2/project_packages_spec.rb
+++ b/spec/requests/api/conan/v2/project_packages_spec.rb
@@ -43,6 +43,11 @@ RSpec.describe API::Conan::V2::ProjectPackages, feature_category: :package_regis
it_behaves_like 'accept get request on private project with access to package registry for everyone'
it_behaves_like 'project not found by project id'
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
+ let(:headers) { job_basic_auth_header(target_job) }
+ end
+
context 'when feature flag is disabled' do
before do
stub_feature_flags(conan_package_revisions_support: false)
diff --git a/spec/requests/api/deployments_spec.rb b/spec/requests/api/deployments_spec.rb
index 51f979e3853..594d27457bd 100644
--- a/spec/requests/api/deployments_spec.rb
+++ b/spec/requests/api/deployments_spec.rb
@@ -23,7 +23,8 @@ RSpec.describe API::Deployments, feature_category: :continuous_delivery do
get api("/projects/#{project.id}/deployments", user), params: params
end
- it_behaves_like 'enforcing job token policies', :read_deployments do
+ it_behaves_like 'enforcing job token policies', :read_deployments,
+ allow_public_access_for_enabled_project_features: [:repository, :builds, :environments] do
let(:request) do
get api("/projects/#{source_project.id}/deployments"), params: { job_token: target_job.token }
end
@@ -174,7 +175,8 @@ RSpec.describe API::Deployments, feature_category: :continuous_delivery do
shared_examples "returns project deployments" do
let(:project) { deployment.environment.project }
- it_behaves_like 'enforcing job token policies', :read_deployments do
+ it_behaves_like 'enforcing job token policies', :read_deployments,
+ allow_public_access_for_enabled_project_features: [:repository, :builds, :environments] do
let(:request) do
get api("/projects/#{source_project.id}/deployments/#{deployment.id}"),
params: { job_token: target_job.token }
@@ -670,7 +672,8 @@ RSpec.describe API::Deployments, feature_category: :continuous_delivery do
subject { get api("/projects/#{project.id}/deployments/#{deployment.id}/merge_requests", user) }
- it_behaves_like 'enforcing job token policies', :read_deployments do
+ it_behaves_like 'enforcing job token policies', :read_deployments,
+ allow_public_access_for_enabled_project_features: [:repository, :builds, :environments] do
let(:request) do
get api("/projects/#{source_project.id}/deployments/#{deployment.id}/merge_requests"), params: { job_token: target_job.token }
end
diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb
index c08cc783fdf..cbbe67defaf 100644
--- a/spec/requests/api/environments_spec.rb
+++ b/spec/requests/api/environments_spec.rb
@@ -124,7 +124,8 @@ RSpec.describe API::Environments, feature_category: :continuous_delivery do
end
end
- it_behaves_like 'enforcing job token policies', :read_environments do
+ it_behaves_like 'enforcing job token policies', :read_environments,
+ allow_public_access_for_enabled_project_features: [:repository, :builds, :environments] do
let(:request) do
get api("/projects/#{source_project.id}/environments"), params: { job_token: target_job.token }
end
@@ -646,7 +647,8 @@ RSpec.describe API::Environments, feature_category: :continuous_delivery do
let_it_be(:bridge_job) { create(:ci_bridge, :running, project: project, user: user) }
let_it_be(:build_job) { create(:ci_build, :running, project: project, user: user) }
- it_behaves_like 'enforcing job token policies', :read_environments do
+ it_behaves_like 'enforcing job token policies', :read_environments,
+ allow_public_access_for_enabled_project_features: [:repository, :builds, :environments] do
let(:request) do
get api("/projects/#{source_project.id}/environments/#{environment.id}"),
params: { job_token: target_job.token }
diff --git a/spec/requests/api/generic_packages_spec.rb b/spec/requests/api/generic_packages_spec.rb
index 948c0692c25..dc09ae26189 100644
--- a/spec/requests/api/generic_packages_spec.rb
+++ b/spec/requests/api/generic_packages_spec.rb
@@ -691,7 +691,8 @@ RSpec.describe API::GenericPackages, feature_category: :package_registry do
let_it_be(:package) { create(:generic_package, project: project) }
let_it_be(:package_file) { create(:package_file, :generic, package: package) }
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
before do
source_project.add_developer(user)
end
diff --git a/spec/requests/api/go_proxy_spec.rb b/spec/requests/api/go_proxy_spec.rb
index 6277647a749..7897086027b 100644
--- a/spec/requests/api/go_proxy_spec.rb
+++ b/spec/requests/api/go_proxy_spec.rb
@@ -190,7 +190,8 @@ RSpec.describe API::GoProxy, feature_category: :package_registry do
it_behaves_like 'a missing module version list resource'
end
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:module_name) { base }
let(:resource) { 'list' }
let(:request) { get_resource(job_token: target_job.token) }
@@ -250,7 +251,8 @@ RSpec.describe API::GoProxy, feature_category: :package_registry do
end
end
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:module_name) { base }
let(:resource) { 'v1.0.1.info' }
let(:request) { get_resource(job_token: target_job.token) }
@@ -278,7 +280,8 @@ RSpec.describe API::GoProxy, feature_category: :package_registry do
it_behaves_like 'a missing module file resource', 'v1.0.1', path: '/mod'
end
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:module_name) { base }
let(:resource) { 'v1.0.1.mod' }
let(:request) { get_resource(job_token: target_job.token) }
@@ -306,7 +309,8 @@ RSpec.describe API::GoProxy, feature_category: :package_registry do
it_behaves_like 'a module archive resource', 'v2.0.0', ['go.mod', 'a.go', 'x.go'], path: '/v2'
end
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:module_name) { base }
let(:resource) { 'v1.0.1.zip' }
let(:request) { get_resource(job_token: target_job.token) }
diff --git a/spec/requests/api/maven_packages_spec.rb b/spec/requests/api/maven_packages_spec.rb
index db9c7da710c..8f85a98bf76 100644
--- a/spec/requests/api/maven_packages_spec.rb
+++ b/spec/requests/api/maven_packages_spec.rb
@@ -475,7 +475,8 @@ RSpec.describe API::MavenPackages, feature_category: :package_registry do
end
end
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
before_all do
project.add_maintainer(user)
end
@@ -649,7 +650,8 @@ RSpec.describe API::MavenPackages, feature_category: :package_registry do
end
end
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:request) do
download_file(file_name: package_file.file_name, params: { job_token: target_job.token })
end
@@ -842,7 +844,8 @@ RSpec.describe API::MavenPackages, feature_category: :package_registry do
subject { download_file_with_token(file_name: package_file.file_name) }
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:request) do
download_file(file_name: package_file.file_name, params: { job_token: target_job.token })
end
diff --git a/spec/requests/api/npm_project_packages_spec.rb b/spec/requests/api/npm_project_packages_spec.rb
index 37048305b20..59d97910359 100644
--- a/spec/requests/api/npm_project_packages_spec.rb
+++ b/spec/requests/api/npm_project_packages_spec.rb
@@ -203,7 +203,8 @@ RSpec.describe API::NpmProjectPackages, feature_category: :package_registry do
project.update!(visibility_level: Gitlab::VisibilityLevel::PRIVATE)
end
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:headers) { build_token_auth_header(target_job.token) }
end
diff --git a/spec/requests/api/package_files_spec.rb b/spec/requests/api/package_files_spec.rb
index 910e82a5d2f..301e2cd81bf 100644
--- a/spec/requests/api/package_files_spec.rb
+++ b/spec/requests/api/package_files_spec.rb
@@ -23,7 +23,8 @@ RSpec.describe API::PackageFiles, feature_category: :package_registry do
project.add_developer(user)
end
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:request) { get api(url), params: { job_token: target_job.token } }
end
diff --git a/spec/requests/api/project_packages_spec.rb b/spec/requests/api/project_packages_spec.rb
index 52c2823cac6..d26bbdb7b06 100644
--- a/spec/requests/api/project_packages_spec.rb
+++ b/spec/requests/api/project_packages_spec.rb
@@ -22,7 +22,8 @@ RSpec.describe API::ProjectPackages, feature_category: :package_registry do
subject(:request) { get api(url), params: params }
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:params) { { job_token: target_job.token } }
end
@@ -231,7 +232,8 @@ RSpec.describe API::ProjectPackages, feature_category: :package_registry do
subject { get api(package_url, user) }
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:request) { get api(package_url), params: { job_token: target_job.token } }
end
@@ -421,7 +423,8 @@ RSpec.describe API::ProjectPackages, feature_category: :package_registry do
end
end
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:request) { get api(package_pipelines_url), params: { job_token: target_job.token } }
end
diff --git a/spec/requests/api/release/links_spec.rb b/spec/requests/api/release/links_spec.rb
index d6f37ca3dc3..b0c0f5ef5b7 100644
--- a/spec/requests/api/release/links_spec.rb
+++ b/spec/requests/api/release/links_spec.rb
@@ -25,7 +25,8 @@ RSpec.describe API::Release::Links, feature_category: :release_orchestration do
end
describe 'GET /projects/:id/releases/:tag_name/assets/links' do
- it_behaves_like 'enforcing job token policies', :read_releases do
+ it_behaves_like 'enforcing job token policies', :read_releases,
+ allow_public_access_for_enabled_project_features: :releases do
let_it_be(:user) { maintainer }
let(:request) do
get api("/projects/#{source_project.id}/releases/v0.1/assets/links"),
@@ -114,7 +115,8 @@ RSpec.describe API::Release::Links, feature_category: :release_orchestration do
describe 'GET /projects/:id/releases/:tag_name/assets/links/:link_id' do
let!(:release_link) { create(:release_link, release: release) }
- it_behaves_like 'enforcing job token policies', :read_releases do
+ it_behaves_like 'enforcing job token policies', :read_releases,
+ allow_public_access_for_enabled_project_features: :releases do
let_it_be(:user) { maintainer }
let(:request) do
get api("/projects/#{source_project.id}/releases/v0.1/assets/links/#{release_link.id}"),
diff --git a/spec/requests/api/releases_spec.rb b/spec/requests/api/releases_spec.rb
index 3836d4462e3..64bb6f16b07 100644
--- a/spec/requests/api/releases_spec.rb
+++ b/spec/requests/api/releases_spec.rb
@@ -19,7 +19,8 @@ RSpec.describe API::Releases, :aggregate_failures, feature_category: :release_or
end
describe 'GET /projects/:id/releases', :use_clean_rails_redis_caching do
- it_behaves_like 'enforcing job token policies', :read_releases do
+ it_behaves_like 'enforcing job token policies', :read_releases,
+ allow_public_access_for_enabled_project_features: [:repository, :releases] do
let(:user) { developer }
let(:request) do
get api("/projects/#{source_project.id}/releases"), params: { job_token: target_job.token }
@@ -326,7 +327,8 @@ RSpec.describe API::Releases, :aggregate_failures, feature_category: :release_or
)
end
- it_behaves_like 'enforcing job token policies', :read_releases do
+ it_behaves_like 'enforcing job token policies', :read_releases,
+ allow_public_access_for_enabled_project_features: [:repository, :releases] do
let(:user) { developer }
let(:request) do
get api("/projects/#{source_project.id}/releases/v0.1"), params: { job_token: target_job.token }
@@ -595,7 +597,8 @@ RSpec.describe API::Releases, :aggregate_failures, feature_category: :release_or
context 'with a valid release tag' do
context 'when filepath is provided' do
context 'when filepath exists' do
- it_behaves_like 'enforcing job token policies', :read_releases, expected_success_status: :redirect do
+ it_behaves_like 'enforcing job token policies', :read_releases, expected_success_status: :redirect,
+ allow_public_access_for_enabled_project_features: [:repository, :releases] do
let(:user) { developer }
let(:request) do
get api("/projects/#{source_project.id}/releases/v0.1/downloads#{filepath}"),
@@ -731,7 +734,8 @@ RSpec.describe API::Releases, :aggregate_failures, feature_category: :release_or
)
end
- it_behaves_like 'enforcing job token policies', :read_releases, expected_success_status: :redirect do
+ it_behaves_like 'enforcing job token policies', :read_releases, expected_success_status: :redirect,
+ allow_public_access_for_enabled_project_features: [:repository, :releases] do
let(:user) { developer }
let(:request) do
get api("/projects/#{source_project.id}/releases/permalink/latest"), params: { job_token: target_job.token }
diff --git a/spec/requests/api/repositories_spec.rb b/spec/requests/api/repositories_spec.rb
index 303a14a8a80..247dd938cd6 100644
--- a/spec/requests/api/repositories_spec.rb
+++ b/spec/requests/api/repositories_spec.rb
@@ -855,7 +855,8 @@ RSpec.describe API::Repositories, feature_category: :source_code_management do
end
describe 'GET /projects/:id/repository/changelog' do
- it_behaves_like 'enforcing job token policies', :read_releases do
+ it_behaves_like 'enforcing job token policies', :read_releases,
+ allow_public_access_for_enabled_project_features: :repository do
before do
allow(Repositories::ChangelogService).to receive(:new)
.and_return(instance_spy(Repositories::ChangelogService))
diff --git a/spec/support/shared_examples/ci/job_token_policies_shared_examples.rb b/spec/support/shared_examples/ci/job_token_policies_shared_examples.rb
index c4ea01e3b40..8aef52ffd27 100644
--- a/spec/support/shared_examples/ci/job_token_policies_shared_examples.rb
+++ b/spec/support/shared_examples/ci/job_token_policies_shared_examples.rb
@@ -1,13 +1,23 @@
# frozen_string_literal: true
-RSpec.shared_examples 'enforcing job token policies' do |policies, expected_success_status: :success|
+RSpec.shared_examples 'enforcing job token policies' do |policies, expected_success_status: :success,
+ allow_public_access_for_enabled_project_features: nil|
+
context 'when authenticating with a CI job token from another project' do
let(:source_project) { project }
- let(:target_job) { create(:ci_build, :running, user: user) }
+ let(:job_user) { user }
+ let(:target_job) { create(:ci_build, :running, user: job_user) }
let(:allowed_policies) { Array(policies) }
let(:default_permissions) { false }
+ let!(:features_state) do
+ source_project.project_feature.attributes
+ .slice(*::ProjectFeature::FEATURES.map { |feature| "#{feature}_access_level" })
+ end
before do
+ # Make all project features private
+ enable_project_features(source_project, nil)
+
create(:ci_job_token_project_scope_link,
source_project: source_project,
target_project: target_job.project,
@@ -17,6 +27,11 @@ RSpec.shared_examples 'enforcing job token policies' do |policies, expected_succ
)
end
+ after do
+ # Reinstate the initial project features
+ source_project.project_feature.update!(features_state)
+ end
+
subject(:do_request) do
request
response
@@ -58,5 +73,59 @@ RSpec.shared_examples 'enforcing job token policies' do |policies, expected_succ
it { is_expected.to have_gitlab_http_status(expected_success_status) }
end
end
+
+ context 'when the source project is public and the target job user is not a member of the source project' do
+ let(:visibility_level) { source_project.visibility_level }
+ let(:job_user) { create(:user) }
+
+ before do
+ if visibility_level != ::Gitlab::VisibilityLevel::PUBLIC
+ source_project.update!(visibility_level: ::Gitlab::VisibilityLevel::PUBLIC)
+ end
+ end
+
+ after do
+ if visibility_level != ::Gitlab::VisibilityLevel::PUBLIC
+ source_project.update!(visibility_level: visibility_level)
+ end
+ end
+
+ context 'when policies are not allowed, but the specified project features allow public access',
+ if: allow_public_access_for_enabled_project_features.present? do
+ let(:allowed_policies) { [] }
+
+ context 'when all project features are private' do
+ it { is_expected.to have_gitlab_http_status(:forbidden) }
+ end
+
+ context 'when the specified project features are public' do
+ before do
+ enable_project_features(source_project, allow_public_access_for_enabled_project_features)
+ end
+
+ it { is_expected.to have_gitlab_http_status(expected_success_status) }
+ end
+ end
+
+ context 'when policies are allowed and all project features are public',
+ unless: allow_public_access_for_enabled_project_features.present? do
+ before do
+ enable_project_features(source_project, ::ProjectFeature::FEATURES)
+ end
+
+ it 'denies access' do
+ expect(do_request).to have_gitlab_http_status(:forbidden)
+ .or have_gitlab_http_status(:unauthorized)
+ .or have_gitlab_http_status(:bad_request)
+ end
+ end
+ end
+ end
+
+ def enable_project_features(project, project_features)
+ attrs = ::ProjectFeature::FEATURES.index_with(::ProjectFeature::PRIVATE)
+ attrs.merge!(Array(project_features).index_with(::ProjectFeature::ENABLED)) if project_features.present?
+ attrs.transform_keys! { |feature| "#{feature}_access_level" }
+ project.project_feature.update!(attrs)
end
end
diff --git a/spec/support/shared_examples/models/concerns/integrations/base/discord_shared_examples.rb b/spec/support/shared_examples/models/concerns/integrations/base/discord_shared_examples.rb
index 779e3eedb43..9c24790b62e 100644
--- a/spec/support/shared_examples/models/concerns/integrations/base/discord_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/integrations/base/discord_shared_examples.rb
@@ -40,6 +40,15 @@ RSpec.shared_examples Integrations::Base::Discord do
end
end
+ describe '.help' do
+ it 'links to help page correctly' do
+ expect(described_class.help).to include(
+ 'user/project/integrations/discord_notifications.md',
+ 'How do I set up this integration?'
+ )
+ end
+ end
+
describe '#execute' do
include StubRequests
diff --git a/spec/support/shared_examples/models/concerns/integrations/base/hangouts_chat_shared_examples.rb b/spec/support/shared_examples/models/concerns/integrations/base/hangouts_chat_shared_examples.rb
index 60de534f4da..14e63887bfb 100644
--- a/spec/support/shared_examples/models/concerns/integrations/base/hangouts_chat_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/integrations/base/hangouts_chat_shared_examples.rb
@@ -16,6 +16,15 @@ RSpec.shared_examples Integrations::Base::HangoutsChat do
let(:webhook_url_regex) { /\A#{webhook_url}.*/ }
let(:query_params) { { messageReplyOption: Integrations::HangoutsChat::REPLY_MESSAGE_FALLBACK_TO_NEW_THREAD } }
+ describe '.help' do
+ it 'links to help page correctly' do
+ expect(described_class.help).to include(
+ 'user/project/integrations/hangouts_chat.md',
+ 'How do I set up a Google Chat webhook?'
+ )
+ end
+ end
+
describe "#execute" do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository, :wiki_repo) }
diff --git a/spec/support/shared_examples/models/concerns/integrations/base/irker_shared_examples.rb b/spec/support/shared_examples/models/concerns/integrations/base/irker_shared_examples.rb
index 6f310c1339a..4b1817e4c11 100644
--- a/spec/support/shared_examples/models/concerns/integrations/base/irker_shared_examples.rb
+++ b/spec/support/shared_examples/models/concerns/integrations/base/irker_shared_examples.rb
@@ -23,6 +23,15 @@ RSpec.shared_examples Integrations::Base::Irker do
end
end
+ describe '.help' do
+ it 'links to help page correctly' do
+ expect(described_class.help).to include(
+ 'help/user/project/integrations/irker.md#set-up-an-irker-daemon',
+ 'Learn More'
+ )
+ end
+ end
+
describe 'Execute' do
let_it_be(:user) { create(:user) }
let_it_be(:project) { create(:project, :repository) }
diff --git a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
index 2e24d0005d8..2a7ee15aad2 100644
--- a/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/npm_packages_shared_examples.rb
@@ -131,7 +131,8 @@ RSpec.shared_examples 'handling get metadata requests' do |scope: :project|
end
end
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:headers) { build_token_auth_header(target_job.token) }
end
@@ -346,7 +347,8 @@ RSpec.shared_examples 'handling audit request' do |path:, scope: :project|
it_behaves_like 'accept audit request', status: :ok
end
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: scope == :project ? :package_registry : nil do
before_all do
project.add_reporter(user)
end
@@ -491,7 +493,8 @@ RSpec.shared_examples 'handling get dist tags requests' do |scope: :project|
end
end
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:headers) { build_token_auth_header(target_job.token) }
end
diff --git a/spec/support/shared_examples/requests/api/packages_shared_examples.rb b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
index 28f9c60ec9d..1dbdbb04eb6 100644
--- a/spec/support/shared_examples/requests/api/packages_shared_examples.rb
+++ b/spec/support/shared_examples/requests/api/packages_shared_examples.rb
@@ -101,7 +101,8 @@ RSpec.shared_examples 'job token for package GET requests' do
end
RSpec.shared_examples 'enforcing read_packages job token policy' do
- it_behaves_like 'enforcing job token policies', :read_packages do
+ it_behaves_like 'enforcing job token policies', :read_packages,
+ allow_public_access_for_enabled_project_features: :package_registry do
let(:headers) { job_basic_auth_header(target_job) }
end
end
diff --git a/spec/workers/ci/execute_build_hooks_worker_spec.rb b/spec/workers/ci/execute_build_hooks_worker_spec.rb
index ecba8a4ce9c..154644eefce 100644
--- a/spec/workers/ci/execute_build_hooks_worker_spec.rb
+++ b/spec/workers/ci/execute_build_hooks_worker_spec.rb
@@ -24,6 +24,73 @@ RSpec.describe Ci::ExecuteBuildHooksWorker, feature_category: :pipeline_composit
describe '#perform' do
subject(:perform) { described_class.new.perform(project.id, build_data) }
+ context 'when build_data has string keys' do
+ let(:string_build_data) do
+ {
+ 'object_kind' => 'build',
+ 'ref' => 'main',
+ 'build_id' => build.id,
+ 'build_name' => build.name,
+ 'build_stage' => build.stage_name,
+ 'build_status' => build.status,
+ 'project_id' => project.id,
+ 'project_name' => project.full_name
+ }
+ end
+
+ it 'converts data to indifferent access' do
+ allow_next_instance_of(Project) do |project|
+ expect(project).to receive(:execute_hooks).with(
+ kind_of(ActiveSupport::HashWithIndifferentAccess),
+ :job_hooks
+ )
+ end
+
+ described_class.new.perform(project.id, string_build_data)
+ end
+
+ it 'allows both string and symbol access to build data' do
+ allow_next_instance_of(Project) do |project|
+ allow(project).to receive(:has_active_hooks?).and_return(true)
+ expect(project).to receive(:execute_hooks) do |data, _hook_type|
+ expect(data[:object_kind]).to eq('build')
+ expect(data['object_kind']).to eq('build')
+ expect(data[:build_name]).to eq(build.name)
+ expect(data['build_name']).to eq(build.name)
+ end
+ end
+
+ described_class.new.perform(project.id, string_build_data)
+ end
+ end
+
+ context 'when build_data has symbol keys' do
+ it 'converts data to indifferent access' do
+ allow_next_instance_of(Project) do |project|
+ expect(project).to receive(:execute_hooks).with(
+ kind_of(ActiveSupport::HashWithIndifferentAccess),
+ :job_hooks
+ )
+ end
+
+ perform
+ end
+
+ it 'allows both string and symbol access to build data' do
+ allow_next_instance_of(Project) do |project|
+ allow(project).to receive(:has_active_hooks?).and_return(true)
+ expect(project).to receive(:execute_hooks) do |data, _hook_type|
+ expect(data[:object_kind]).to eq('build')
+ expect(data['object_kind']).to eq('build')
+ expect(data[:build_name]).to eq(build.name)
+ expect(data['build_name']).to eq(build.name)
+ end
+ end
+
+ perform
+ end
+ end
+
context 'when project exists' do
context 'with project services' do
let!(:integration) { create(:integration, active: true, job_events: true, project: project) }
diff --git a/yarn.lock b/yarn.lock
index c986430a23c..25aa949cdf7 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -1436,10 +1436,10 @@
resolved "https://registry.yarnpkg.com/@gitlab/svgs/-/svgs-3.123.0.tgz#1fa3b1a709755ff7c8ef67e18c0442101655ebf0"
integrity sha512-yjVn+utOTIKk8d9JlvGo6EgJ4TQ+CKpe3RddflAqtsQqQuL/2MlVdtaUePybxYzWIaumFuh5LouQ6BrWyw1niQ==
-"@gitlab/ui@108.3.1":
- version "108.3.1"
- resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-108.3.1.tgz#eb1db6c1ddc0ad7a239e6bcf21624fd1bc54b27b"
- integrity sha512-O4haNCEJl3nHK8DB1mi01YRJOZomNXI0sBA600BLrbptm/NAO9oVE7O/U8sFEdXM7EtFHYwRYcF/LrWwfJmE9g==
+"@gitlab/ui@108.4.1":
+ version "108.4.1"
+ resolved "https://registry.yarnpkg.com/@gitlab/ui/-/ui-108.4.1.tgz#d45dbcc3a9f568694f53eebb795544157ddbf44f"
+ integrity sha512-o3mcR/AQ5tkKd3mMClMvsJIHhLWzU6n1L0m3bp4Yr4zaNtRG3c8gEGF7MR6pMhlnyb5r/FQk2wigxHaUuOSblQ==
dependencies:
"@floating-ui/dom" "1.4.3"
echarts "^5.3.2"