diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-01-11 06:16:07 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-01-11 06:16:07 +0300 |
commit | f60515eae2fc00c56742462826ae00826eb8826e (patch) | |
tree | d8d3cc877f7f9d9c20d27dd95eb145918d2d77bb | |
parent | d9c0b200e192c340f50fa165a66e4b6ff805f9fc (diff) |
Add latest changes from gitlab-org/gitlab@master
-rw-r--r-- | app/assets/javascripts/diffs/components/image_diff_overlay.vue | 16 | ||||
-rw-r--r-- | app/controllers/groups/application_controller.rb | 12 | ||||
-rw-r--r-- | app/controllers/groups/runners_controller.rb | 7 | ||||
-rw-r--r-- | app/finders/ci/runners_finder.rb | 2 | ||||
-rw-r--r-- | app/graphql/types/deprecated_mutations.rb | 3 | ||||
-rw-r--r-- | app/graphql/types/mutation_type.rb | 1 | ||||
-rw-r--r-- | app/policies/group_policy.rb | 9 | ||||
-rw-r--r-- | app/views/projects/runners/_group_runners.html.haml | 4 | ||||
-rw-r--r-- | doc/api/graphql/reference/index.md | 31 | ||||
-rw-r--r-- | doc/ci/caching/index.md | 33 | ||||
-rw-r--r-- | doc/user/permissions.md | 325 | ||||
-rw-r--r-- | lib/sidebars/groups/menus/ci_cd_menu.rb | 4 | ||||
-rw-r--r-- | locale/gitlab.pot | 11 | ||||
-rw-r--r-- | spec/features/runners_spec.rb | 25 | ||||
-rw-r--r-- | spec/frontend/diffs/components/image_diff_overlay_spec.js | 19 | ||||
-rw-r--r-- | spec/graphql/types/mutation_type_spec.rb | 8 | ||||
-rw-r--r-- | spec/policies/group_policy_spec.rb | 6 | ||||
-rw-r--r-- | spec/support/shared_contexts/policies/group_policy_shared_context.rb | 26 |
18 files changed, 324 insertions, 218 deletions
diff --git a/app/assets/javascripts/diffs/components/image_diff_overlay.vue b/app/assets/javascripts/diffs/components/image_diff_overlay.vue index 5572338908f..eede8e52292 100644 --- a/app/assets/javascripts/diffs/components/image_diff_overlay.vue +++ b/app/assets/javascripts/diffs/components/image_diff_overlay.vue @@ -4,8 +4,8 @@ import { isArray } from 'lodash'; import { mapActions, mapGetters } from 'vuex'; import imageDiffMixin from 'ee_else_ce/diffs/mixins/image_diff'; -function calcPercent(pos, size, renderedSize) { - return (((pos / size) * 100) / ((renderedSize / size) * 100)) * 100; +function calcPercent(pos, renderedSize) { + return (100 * pos) / renderedSize; } export default { @@ -65,8 +65,8 @@ export default { ...mapActions('diffs', ['openDiffFileCommentForm']), getImageDimensions() { return { - width: this.$parent.width, - height: this.$parent.height, + width: Math.round(this.$parent.width), + height: Math.round(this.$parent.height), }; }, getPositionForObject(meta) { @@ -87,15 +87,15 @@ export default { }, clickedImage(x, y) { const { width, height } = this.getImageDimensions(); - const xPercent = calcPercent(x, width, this.renderedWidth); - const yPercent = calcPercent(y, height, this.renderedHeight); + const xPercent = calcPercent(x, this.renderedWidth); + const yPercent = calcPercent(y, this.renderedHeight); this.openDiffFileCommentForm({ fileHash: this.fileHash, width, height, - x: width * (xPercent / 100), - y: height * (yPercent / 100), + x: Math.round(width * (xPercent / 100)), + y: Math.round(height * (yPercent / 100)), xPercent, yPercent, }); diff --git a/app/controllers/groups/application_controller.rb b/app/controllers/groups/application_controller.rb index ab67a007bd9..f9c875b80b2 100644 --- a/app/controllers/groups/application_controller.rb +++ b/app/controllers/groups/application_controller.rb @@ -37,6 +37,18 @@ class Groups::ApplicationController < ApplicationController end end + def authorize_admin_group_runners! + unless can?(current_user, :admin_group_runners, group) + render_404 + end + end + + def authorize_read_group_runners! + unless can?(current_user, :read_group_runners, group) + render_404 + end + end + def authorize_create_deploy_token! unless can?(current_user, :create_deploy_token, group) render_404 diff --git a/app/controllers/groups/runners_controller.rb b/app/controllers/groups/runners_controller.rb index 5c21c7b023c..f602d02a165 100644 --- a/app/controllers/groups/runners_controller.rb +++ b/app/controllers/groups/runners_controller.rb @@ -1,9 +1,8 @@ # frozen_string_literal: true class Groups::RunnersController < Groups::ApplicationController - # TODO Proper policies, such as `read_group_runners, should be implemented per - # https://gitlab.com/gitlab-org/gitlab/-/issues/334802 - before_action :authorize_admin_group! + before_action :authorize_read_group_runners!, only: [:index, :show] + before_action :authorize_admin_group_runners!, only: [:edit, :update, :destroy, :pause, :resume] before_action :runner_list_group_view_vue_ui_enabled, only: [:index] before_action :runner, only: [:edit, :update, :destroy, :pause, :resume, :show] @@ -17,7 +16,7 @@ class Groups::RunnersController < Groups::ApplicationController end def runner_list_group_view_vue_ui_enabled - return render_404 unless Feature.enabled?(:runner_list_group_view_vue_ui, group, default_enabled: :yaml) + render_404 unless Feature.enabled?(:runner_list_group_view_vue_ui, group, default_enabled: :yaml) end def show diff --git a/app/finders/ci/runners_finder.rb b/app/finders/ci/runners_finder.rb index a514d2e8d03..3ebf6bd1562 100644 --- a/app/finders/ci/runners_finder.rb +++ b/app/finders/ci/runners_finder.rb @@ -47,7 +47,7 @@ module Ci end def group_runners - raise Gitlab::Access::AccessDeniedError unless can?(@current_user, :admin_group, @group) + raise Gitlab::Access::AccessDeniedError unless can?(@current_user, :read_group_runners, @group) @runners = case @params[:membership] when :direct diff --git a/app/graphql/types/deprecated_mutations.rb b/app/graphql/types/deprecated_mutations.rb index 49bad56b6f9..70d5fc31cd1 100644 --- a/app/graphql/types/deprecated_mutations.rb +++ b/app/graphql/types/deprecated_mutations.rb @@ -5,7 +5,8 @@ module Types extend ActiveSupport::Concern prepended do - # placeholder for any FOSS mutations to be deprecated + mount_mutation Mutations::Clusters::AgentTokens::Delete, + deprecated: { reason: 'Tokens must be revoked with ClusterAgentTokenRevoke', milestone: '14.7' } end end end diff --git a/app/graphql/types/mutation_type.rb b/app/graphql/types/mutation_type.rb index c9f083efd27..e01bb0b4e70 100644 --- a/app/graphql/types/mutation_type.rb +++ b/app/graphql/types/mutation_type.rb @@ -35,7 +35,6 @@ module Types mount_mutation Mutations::Clusters::Agents::Create mount_mutation Mutations::Clusters::Agents::Delete mount_mutation Mutations::Clusters::AgentTokens::Create - mount_mutation Mutations::Clusters::AgentTokens::Delete mount_mutation Mutations::Clusters::AgentTokens::Revoke mount_mutation Mutations::Commits::Create, calls_gitaly: true mount_mutation Mutations::CustomEmoji::Create, feature_flag: :custom_emoji diff --git a/app/policies/group_policy.rb b/app/policies/group_policy.rb index 71133008565..05adcd51082 100644 --- a/app/policies/group_policy.rb +++ b/app/policies/group_policy.rb @@ -165,7 +165,6 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy enable :destroy_package enable :create_projects enable :admin_pipeline - enable :admin_group_runners enable :admin_build enable :read_cluster enable :add_cluster @@ -183,6 +182,10 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy enable :admin_group_member enable :change_visibility_level + enable :read_group_runners + enable :admin_group_runners + enable :register_group_runners + enable :set_note_created_at enable :set_emails_disabled enable :change_prevent_sharing_groups_outside_hierarchy @@ -208,10 +211,6 @@ class GroupPolicy < Namespaces::GroupProjectNamespaceSharedPolicy enable :read_nested_project_resources end - rule { can?(:admin_group_runners) }.policy do - enable :register_group_runners - end - rule { owner }.enable :create_subgroup rule { maintainer & maintainer_can_create_group }.enable :create_subgroup diff --git a/app/views/projects/runners/_group_runners.html.haml b/app/views/projects/runners/_group_runners.html.haml index 183e747afdd..c25fd7a7587 100644 --- a/app/views/projects/runners/_group_runners.html.haml +++ b/app/views/projects/runners/_group_runners.html.haml @@ -29,9 +29,9 @@ - if can?(current_user, :admin_group_runners, @project.group) - group_link = link_to _("group's CI/CD settings."), group_settings_ci_cd_path(@project.group) - = _('Group maintainers can register group runners in the %{link}').html_safe % { link: group_link } + = _('Group owners can register group runners in the %{link}').html_safe % { link: group_link } - else - = _('Ask your group maintainer to set up a group runner.') + = _('Ask your group owner to set up a group runner.') - else %h4.underlined-title diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index e5cd42dc4da..465c3027838 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -954,6 +954,10 @@ Input type: `ClusterAgentTokenCreateInput` ### `Mutation.clusterAgentTokenDelete` +WARNING: +**Deprecated** in 14.7. +Tokens must be revoked with ClusterAgentTokenRevoke. + Input type: `ClusterAgentTokenDeleteInput` #### Arguments @@ -4931,6 +4935,27 @@ Input type: `VulnerabilityExternalIssueLinkDestroyInput` | <a id="mutationvulnerabilityexternalissuelinkdestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | | <a id="mutationvulnerabilityexternalissuelinkdestroyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | +### `Mutation.vulnerabilityFindingDismiss` + +Input type: `VulnerabilityFindingDismissInput` + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="mutationvulnerabilityfindingdismissclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| <a id="mutationvulnerabilityfindingdismisscomment"></a>`comment` | [`String`](#string) | Comment why finding should be dismissed. | +| <a id="mutationvulnerabilityfindingdismissdismissalreason"></a>`dismissalReason` | [`VulnerabilityDismissalReason`](#vulnerabilitydismissalreason) | Reason why finding should be dismissed. | +| <a id="mutationvulnerabilityfindingdismissid"></a>`id` | [`VulnerabilitiesFindingID!`](#vulnerabilitiesfindingid) | ID of the finding to be dismissed. | + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="mutationvulnerabilityfindingdismissclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| <a id="mutationvulnerabilityfindingdismisserrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | +| <a id="mutationvulnerabilityfindingdismissfinding"></a>`finding` | [`PipelineSecurityReportFinding`](#pipelinesecurityreportfinding) | Finding after dismissal. | + ### `Mutation.vulnerabilityResolve` Input type: `VulnerabilityResolveInput` @@ -18182,6 +18207,12 @@ A `VulnerabilitiesExternalIssueLinkID` is a global ID. It is encoded as a string An example `VulnerabilitiesExternalIssueLinkID` is: `"gid://gitlab/Vulnerabilities::ExternalIssueLink/1"`. +### `VulnerabilitiesFindingID` + +A `VulnerabilitiesFindingID` is a global ID. It is encoded as a string. + +An example `VulnerabilitiesFindingID` is: `"gid://gitlab/Vulnerabilities::Finding/1"`. + ### `VulnerabilitiesScannerID` A `VulnerabilitiesScannerID` is a global ID. It is encoded as a string. diff --git a/doc/ci/caching/index.md b/doc/ci/caching/index.md index 491454aed28..c634491662d 100644 --- a/doc/ci/caching/index.md +++ b/doc/ci/caching/index.md @@ -235,6 +235,39 @@ test_async: - node ./specs/start.js ./specs/async.spec.js ``` +#### Compute the cache key from the lock file + +You can use [`cache:key:files`](../yaml/index.md#cachekeyfiles) to compute the cache +key from a lock file like `package-lock.json` or `yarn.lock`, and reuse it in many jobs. + +```yaml +# Cache modules using lock file +cache: + key: + files: + - package-lock.json + paths: + - .npm/ +``` + +If you're using [Yarn](https://yarnpkg.com/), you can use [`yarn-offline-mirror`](https://classic.yarnpkg.com/blog/2016/11/24/offline-mirror/) +to cache the zipped `node_modules` tarballs. The cache generates more quickly, because +fewer files have to be compressed: + +```yaml +job: + script: + - echo 'yarn-offline-mirror ".yarn-cache/"' >> .yarnrc + - echo 'yarn-offline-mirror-pruning true' >> .yarnrc + - yarn install --frozen-lockfile --no-progress + cache: + key: + files: + - yarn.lock + paths: + - .yarn-cache/ +``` + ### Cache PHP dependencies If your project uses [Composer](https://getcomposer.org/) to install diff --git a/doc/user/permissions.md b/doc/user/permissions.md index 3cb07ecfe99..36c49e39151 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -46,168 +46,169 @@ The following table lists project permissions available for each role: <!-- Keep this table sorted: By topic first, then by minimum role, then alphabetically. --> -| Action | Guest | Reporter | Developer | Maintainer | Owner | -|-------------------------------------------------------------------------------------------------------------------------|----------|----------|-----------|------------|-------| -| [Analytics](analytics/index.md):<br>View issue analytics **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Analytics](analytics/index.md):<br>View [merge request analytics](analytics/merge_request_analytics.md) **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Analytics](analytics/index.md):<br>View value stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Analytics](analytics/index.md):<br>View [DORA metrics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ | -| [Analytics](analytics/index.md):<br>View [CI/CD analytics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ | -| [Analytics](analytics/index.md):<br>View [code review analytics](analytics/code_review_analytics.md) **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ | -| [Analytics](analytics/index.md):<br>View [repository analytics](analytics/repository_analytics.md) | | ✓ | ✓ | ✓ | ✓ | -| [Application security](application_security/index.md):<br>View licenses in [dependency list](application_security/dependency_list/index.md) **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | -| [Application security](application_security/index.md):<br>Create and run [on-demand DAST scans](application_security/dast/index.md#on-demand-scans) **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Application security](application_security/index.md):<br>Manage [security policy](application_security/policies/index.md) **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Application security](application_security/index.md):<br>View [dependency list](application_security/dependency_list/index.md) **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Application security](application_security/index.md):<br>View [threats list](application_security/threat_monitoring/index.md#threat-monitoring) **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Application security](application_security/index.md):<br>Create a [CVE ID Request](application_security/cve_id_request.md) **(FREE SAAS)** | | | | ✓ | ✓ | -| [Application security](application_security/index.md):<br>Create or assign [security policy project](application_security/policies/index.md) **(ULTIMATE)** | | | | | ✓ | -| [CI/CD](../ci/index.md):<br>Download and browse job artifacts | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>View a job log | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>View list of jobs | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>View [environments](../ci/environments/index.md) | | ✓ | ✓ | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>Cancel and retry jobs | | | ✓ | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>Create new [environments](../ci/environments/index.md) | | | ✓ | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>Run CI/CD pipeline against a protected branch | | | ✓ (*5*) | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>Stop [environments](../ci/environments/index.md) | | | ✓ | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>View a job with [debug logging](../ci/variables/index.md#debug-logging) | | | ✓ | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>Manage CI/CD variables | | | | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>Manage job triggers | | | | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>Manage runners | | | | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>Run Web IDE's Interactive Web Terminals **(ULTIMATE ONLY)** | | | | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>Use [environment terminals](../ci/environments/index.md#web-terminals-deprecated) | | | | ✓ | ✓ | -| [CI/CD](../ci/index.md):<br>Delete pipelines | | | | | ✓ | -| [Clusters](infrastructure/clusters/index.md):<br>View [pod logs](project/clusters/kubernetes_pod_logs.md) | | | ✓ | ✓ | ✓ | -| [Clusters](infrastructure/clusters/index.md):<br>Manage clusters | | | | ✓ | ✓ | -| [Container Registry](packages/container_registry/index.md):<br>Create, edit, delete cleanup policies | | | ✓ | ✓ | ✓ | -| [Container Registry](packages/container_registry/index.md):<br>Remove a container registry image | | | ✓ | ✓ | ✓ | -| [Container Registry](packages/container_registry/index.md):<br>Update container registry | | | ✓ | ✓ | ✓ | -| [GitLab Pages](project/pages/index.md):<br>View Pages protected by [access control](project/pages/introduction.md#gitlab-pages-access-control) | ✓ | ✓ | ✓ | ✓ | ✓ | -| [GitLab Pages](project/pages/index.md):<br>Manage | | | | ✓ | ✓ | -| [GitLab Pages](project/pages/index.md):<br>Manage GitLab Pages domains and certificates | | | | ✓ | ✓ | -| [GitLab Pages](project/pages/index.md):<br>Remove GitLab Pages | | | | ✓ | ✓ | -| [Incident Management](../operations/incident_management/index.md):<br>View [alerts](../operations/incident_management/alerts.md) | | ✓ | ✓ | ✓ | ✓ | -| [Incident Management](../operations/incident_management/index.md):<br>Assign an alert | ✓| ✓ | ✓ | ✓ | ✓ | -| [Incident Management](../operations/incident_management/index.md):<br>View [incident](../operations/incident_management/incidents.md) | ✓| ✓ | ✓ | ✓ | ✓ | -| [Incident Management](../operations/incident_management/index.md):<br>Create [incident](../operations/incident_management/incidents.md) | (*17*) | ✓ | ✓ | ✓ | ✓ | -| [Incident Management](../operations/incident_management/index.md):<br>View [on-call schedules](../operations/incident_management/oncall_schedules.md) | | ✓ | ✓ | ✓ | ✓ | -| [Incident Management](../operations/incident_management/index.md):<br>Participate in on-call rotation | ✓| ✓ | ✓ | ✓ | ✓ | -| [Incident Management](../operations/incident_management/index.md):<br>View [escalation policies](../operations/incident_management/escalation_policies.md) | | ✓ | ✓ | ✓ | ✓ | -| [Incident Management](../operations/incident_management/index.md):<br>Manage [on-call schedules](../operations/incident_management/oncall_schedules.md) | | | | ✓ | ✓ | -| [Incident Management](../operations/incident_management/index.md):<br>Manage [escalation policies](../operations/incident_management/escalation_policies.md)| | | | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Add Labels | ✓ (*16*) | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Assign | ✓ (*16*) | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Create | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Create [confidential issues](project/issues/confidential_issues.md) | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>View [Design Management](project/issues/design_management.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>View related issues | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Set weight | ✓ (*16*) | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>View [confidential issues](project/issues/confidential_issues.md) | (*2*) | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Close / reopen | | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Lock threads | | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Manage related issues | | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Manage tracker | | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Move issues (*15*) | | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Set issue [time tracking](project/time_tracking.md) estimate and time spent | | ✓ | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Upload [Design Management](project/issues/design_management.md) files | | | ✓ | ✓ | ✓ | -| [Issues](project/issues/index.md):<br>Delete | | | | | ✓ | -| [License Compliance](compliance/license_compliance/index.md):<br>View allowed and denied licenses **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | -| [License Compliance](compliance/license_compliance/index.md):<br>View License Compliance reports **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | -| [License Compliance](compliance/license_compliance/index.md):<br>View License list **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | -| [License Compliance](compliance/license_compliance/index.md):<br>Manage license policy **(ULTIMATE)** | | | | ✓ | ✓ | -| [Merge requests](project/merge_requests/index.md):<br>Assign reviewer | | ✓ | ✓ | ✓ | ✓ | -| [Merge requests](project/merge_requests/index.md):<br>See list | | ✓ | ✓ | ✓ | ✓ | -| [Merge requests](project/merge_requests/index.md):<br>Apply code change suggestions | | | ✓ | ✓ | ✓ | -| [Merge requests](project/merge_requests/index.md):<br>Approve (*9*) | | | ✓ | ✓ | ✓ | -| [Merge requests](project/merge_requests/index.md):<br>Assign | | | ✓ | ✓ | ✓ | -| [Merge requests](project/merge_requests/index.md):<br>Create (*18*) | | | ✓ | ✓ | ✓ | -| [Merge requests](project/merge_requests/index.md):<br>Add labels | | | ✓ | ✓ | ✓ | -| [Merge requests](project/merge_requests/index.md):<br>Lock threads | | | ✓ | ✓ | ✓ | -| [Merge requests](project/merge_requests/index.md):<br>Manage or accept | | | ✓ | ✓ | ✓ | -| [Merge requests](project/merge_requests/index.md):<br>Manage merge approval rules (project settings) | | | | ✓ | ✓ | -| [Merge requests](project/merge_requests/index.md):<br>Delete | | | | | ✓ | -| [Metrics dashboards](../operations/metrics/dashboards/index.md):<br>Manage user-starred metrics dashboards (*7*) | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Metrics dashboards](../operations/metrics/dashboards/index.md):<br>View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ | -| [Metrics dashboards](../operations/metrics/dashboards/index.md):<br>Create/edit/delete metrics dashboard annotations | | | ✓ | ✓ | ✓ | -| [Package registry](packages/index.md):<br>Pull package | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | -| [Package registry](packages/index.md):<br>Publish package | | | ✓ | ✓ | ✓ | -| [Package registry](packages/index.md):<br>Delete package | | | | ✓ | ✓ | -| [Project operations](../operations/index.md):<br>View [Error Tracking](../operations/error_tracking.md) list | | ✓ | ✓ | ✓ | ✓ | -| [Project operations](../operations/index.md):<br>Manage [Feature Flags](../operations/feature_flags.md) **(PREMIUM)** | | | ✓ | ✓ | ✓ | -| [Project operations](../operations/index.md):<br>Manage [Error Tracking](../operations/error_tracking.md) | | | | ✓ | ✓ | -| [Projects](project/index.md):<br>Download project | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>Reposition comments on images (posted by any user) | ✓ (*10*) | ✓ (*10*) | ✓ (*10*) | ✓ | ✓ | -| [Projects](project/index.md):<br>View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>View [releases](project/releases/index.md) | ✓ (*6*) | ✓ | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>View Requirements **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>View [time tracking](project/time_tracking.md) reports | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>View [wiki](project/wiki/index.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>Create [snippets](snippets.md) | | ✓ | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>Manage labels | | ✓ | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>View [project traffic statistics](../api/project_statistics.md) | | ✓ | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>Create, edit, delete [milestones](project/milestones/index.md). | | | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>Create, edit, delete [releases](project/releases/index.md) | | | ✓ (*13*) | ✓ (*13*) | ✓ (*13*) | -| [Projects](project/index.md):<br>Create, edit [wiki](project/wiki/index.md) pages | | | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>Enable Review Apps | | | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>View project [Audit Events](../administration/audit_events.md) | | | ✓ (*11*) | ✓ | ✓ | -| [Projects](project/index.md):<br>Add deploy keys | | | | ✓ | ✓ | -| [Projects](project/index.md):<br>Add new team members | | | | ✓ | ✓ | -| [Projects](project/index.md):<br>Change [project features visibility](../public_access/public_access.md) level | | | | ✓ (14) | ✓ | -| [Projects](project/index.md):<br>Configure [webhooks](project/integrations/webhooks.md) | | | | ✓ | ✓ | -| [Projects](project/index.md):<br>Delete [wiki](project/wiki/index.md) pages | | | ✓ | ✓ | ✓ | -| [Projects](project/index.md):<br>Edit comments (posted by any user) | | | | ✓ | ✓ | -| [Projects](project/index.md):<br>Edit project badges | | | | ✓ | ✓ | -| [Projects](project/index.md):<br>Edit project settings | | | | ✓ | ✓ | -| [Projects](project/index.md):<br>Export project | | | | ✓ | ✓ | -| [Projects](project/index.md):<br>Manage [project access tokens](project/settings/project_access_tokens.md) **(FREE SELF)** **(PREMIUM SAAS)** (*12*) | | | | ✓ | ✓ | -| [Projects](project/index.md):<br>Manage [Project Operations](../operations/index.md) | | | | ✓ | ✓ | -| [Projects](project/index.md):<br>Share (invite) projects with groups | | | | ✓ (*8*) | ✓ (*8*) | -| [Projects](project/index.md):<br>View 2FA status of members | | | | ✓ | ✓ | -| [Projects](project/index.md):<br>Administer project compliance frameworks | | | | | ✓ | -| [Projects](project/index.md):<br>Archive project | | | | | ✓ | -| [Projects](project/index.md):<br>Change project visibility level | | | | | ✓ | -| [Projects](project/index.md):<br>Delete project | | | | | ✓ | -| [Projects](project/index.md):<br>Disable notification emails | | | | | ✓ | -| [Projects](project/index.md):<br>Rename project | | | | | ✓ | -| [Projects](project/index.md):<br>Transfer project to another namespace | | | | | ✓ | -| [Repository](project/repository/index.md):<br>Pull project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>View project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>View a commit status | | ✓ | ✓ | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Add tags | | | ✓ | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Create new branches | | | ✓ | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Create or update commit status | | | ✓ (*5*) | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Force push to non-protected branches | | | ✓ | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Push to non-protected branches | | | ✓ | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Remove non-protected branches | | | ✓ | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Rewrite or remove Git tags | | | ✓ | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Enable or disable branch protection | | | | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Enable or disable tag protection | | | | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Manage [push rules](../push_rules/push_rules.md) | | | | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Push to protected branches (*5*) | | | | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Turn on or off protected branch push for developers | | | | ✓ | ✓ | -| [Repository](project/repository/index.md):<br>Remove fork relationship | | | | | ✓ | -| [Repository](project/repository/index.md):<br>Force push to protected branches (*4*) | | | | | | -| [Repository](project/repository/index.md):<br>Remove protected branches (*4*) | | | | | | -| [Requirements Management](project/requirements/index.md):<br>Archive / reopen **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | -| [Requirements Management](project/requirements/index.md):<br>Create / edit **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | -| [Requirements Management](project/requirements/index.md):<br>Import / export **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | -| [Security dashboard](application_security/security_dashboard/index.md):<br>View Security reports **(ULTIMATE)** | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | -| [Security dashboard](application_security/security_dashboard/index.md):<br>Create issue from vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Security dashboard](application_security/security_dashboard/index.md):<br>Create vulnerability from vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Security dashboard](application_security/security_dashboard/index.md):<br>Dismiss vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Security dashboard](application_security/security_dashboard/index.md):<br>Dismiss vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Security dashboard](application_security/security_dashboard/index.md):<br>Resolve vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Security dashboard](application_security/security_dashboard/index.md):<br>Revert vulnerability to detected state **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Security dashboard](application_security/security_dashboard/index.md):<br>Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Security dashboard](application_security/security_dashboard/index.md):<br>View vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Security dashboard](application_security/security_dashboard/index.md):<br>View vulnerability findings in [dependency list](application_security/dependency_list/index.md) **(ULTIMATE)** | | | ✓ | ✓ | ✓ | -| [Terraform](infrastructure/index.md):<br>Read Terraform state | | | ✓ | ✓ | ✓ | -| [Terraform](infrastructure/index.md):<br>Manage Terraform state | | | | ✓ | ✓ | -| [Test cases](../ci/test_cases/index.md):<br>Archive | | ✓ | ✓ | ✓ | ✓ | -| [Test cases](../ci/test_cases/index.md):<br>Create | | ✓ | ✓ | ✓ | ✓ | -| [Test cases](../ci/test_cases/index.md):<br>Move | | ✓ | ✓ | ✓ | ✓ | -| [Test cases](../ci/test_cases/index.md):<br>Reopen | | ✓ | ✓ | ✓ | ✓ | +| Action | Guest | Reporter | Developer | Maintainer | Owner | +|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|----------|----------|-----------|------------|-------| +| [Analytics](analytics/index.md):<br>View issue analytics **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ | +| [Analytics](analytics/index.md):<br>View [merge request analytics](analytics/merge_request_analytics.md) **(PREMIUM)** | ✓ | ✓ | ✓ | ✓ | ✓ | +| [Analytics](analytics/index.md):<br>View value stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ | +| [Analytics](analytics/index.md):<br>View [DORA metrics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ | +| [Analytics](analytics/index.md):<br>View [CI/CD analytics](analytics/ci_cd_analytics.md) | | ✓ | ✓ | ✓ | ✓ | +| [Analytics](analytics/index.md):<br>View [code review analytics](analytics/code_review_analytics.md) **(PREMIUM)** | | ✓ | ✓ | ✓ | ✓ | +| [Analytics](analytics/index.md):<br>View [repository analytics](analytics/repository_analytics.md) | | ✓ | ✓ | ✓ | ✓ | +| [Application security](application_security/index.md):<br>View licenses in [dependency list](application_security/dependency_list/index.md) **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| [Application security](application_security/index.md):<br>Create and run [on-demand DAST scans](application_security/dast/index.md#on-demand-scans) **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Application security](application_security/index.md):<br>Manage [security policy](application_security/policies/index.md) **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Application security](application_security/index.md):<br>View [dependency list](application_security/dependency_list/index.md) **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Application security](application_security/index.md):<br>View [threats list](application_security/threat_monitoring/index.md#threat-monitoring) **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Application security](application_security/index.md):<br>Create a [CVE ID Request](application_security/cve_id_request.md) **(FREE SAAS)** | | | | ✓ | ✓ | +| [Application security](application_security/index.md):<br>Create or assign [security policy project](application_security/policies/index.md) **(ULTIMATE)** | | | | | ✓ | +| [CI/CD](../ci/index.md):<br>Download and browse job artifacts | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>View a job log | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>View list of jobs | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>View [environments](../ci/environments/index.md) | | ✓ | ✓ | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>Cancel and retry jobs | | | ✓ | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>Create new [environments](../ci/environments/index.md) | | | ✓ | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>Run CI/CD pipeline against a protected branch | | | ✓ (*5*) | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>Stop [environments](../ci/environments/index.md) | | | ✓ | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>View a job with [debug logging](../ci/variables/index.md#debug-logging) | | | ✓ | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>Manage CI/CD variables | | | | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>Manage job triggers | | | | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>Manage group runners | | | | | ✓ | +| [CI/CD](../ci/index.md):<br>Manage project runners | | | | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>Run Web IDE's Interactive Web Terminals **(ULTIMATE ONLY)** | | | | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>Use [environment terminals](../ci/environments/index.md#web-terminals-deprecated) | | | | ✓ | ✓ | +| [CI/CD](../ci/index.md):<br>Delete pipelines | | | | | ✓ | +| [Clusters](infrastructure/clusters/index.md):<br>View [pod logs](project/clusters/kubernetes_pod_logs.md) | | | ✓ | ✓ | ✓ | +| [Clusters](infrastructure/clusters/index.md):<br>Manage clusters | | | | ✓ | ✓ | +| [Container Registry](packages/container_registry/index.md):<br>Create, edit, delete cleanup policies | | | ✓ | ✓ | ✓ | +| [Container Registry](packages/container_registry/index.md):<br>Remove a container registry image | | | ✓ | ✓ | ✓ | +| [Container Registry](packages/container_registry/index.md):<br>Update container registry | | | ✓ | ✓ | ✓ | +| [GitLab Pages](project/pages/index.md):<br>View Pages protected by [access control](project/pages/introduction.md#gitlab-pages-access-control) | ✓ | ✓ | ✓ | ✓ | ✓ | +| [GitLab Pages](project/pages/index.md):<br>Manage | | | | ✓ | ✓ | +| [GitLab Pages](project/pages/index.md):<br>Manage GitLab Pages domains and certificates | | | | ✓ | ✓ | +| [GitLab Pages](project/pages/index.md):<br>Remove GitLab Pages | | | | ✓ | ✓ | +| [Incident Management](../operations/incident_management/index.md):<br>View [alerts](../operations/incident_management/alerts.md) | | ✓ | ✓ | ✓ | ✓ | +| [Incident Management](../operations/incident_management/index.md):<br>Assign an alert | ✓| ✓ | ✓ | ✓ | ✓ | +| [Incident Management](../operations/incident_management/index.md):<br>View [incident](../operations/incident_management/incidents.md) | ✓| ✓ | ✓ | ✓ | ✓ | +| [Incident Management](../operations/incident_management/index.md):<br>Create [incident](../operations/incident_management/incidents.md) | (*17*) | ✓ | ✓ | ✓ | ✓ | +| [Incident Management](../operations/incident_management/index.md):<br>View [on-call schedules](../operations/incident_management/oncall_schedules.md) | | ✓ | ✓ | ✓ | ✓ | +| [Incident Management](../operations/incident_management/index.md):<br>Participate in on-call rotation | ✓| ✓ | ✓ | ✓ | ✓ | +| [Incident Management](../operations/incident_management/index.md):<br>View [escalation policies](../operations/incident_management/escalation_policies.md) | | ✓ | ✓ | ✓ | ✓ | +| [Incident Management](../operations/incident_management/index.md):<br>Manage [on-call schedules](../operations/incident_management/oncall_schedules.md) | | | | ✓ | ✓ | +| [Incident Management](../operations/incident_management/index.md):<br>Manage [escalation policies](../operations/incident_management/escalation_policies.md) | | | | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Add Labels | ✓ (*16*) | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Assign | ✓ (*16*) | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Create | ✓ | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Create [confidential issues](project/issues/confidential_issues.md) | ✓ | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>View [Design Management](project/issues/design_management.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>View related issues | ✓ | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Set weight | ✓ (*16*) | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>View [confidential issues](project/issues/confidential_issues.md) | (*2*) | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Close / reopen | | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Lock threads | | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Manage related issues | | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Manage tracker | | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Move issues (*15*) | | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Set issue [time tracking](project/time_tracking.md) estimate and time spent | | ✓ | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Upload [Design Management](project/issues/design_management.md) files | | | ✓ | ✓ | ✓ | +| [Issues](project/issues/index.md):<br>Delete | | | | | ✓ | +| [License Compliance](compliance/license_compliance/index.md):<br>View allowed and denied licenses **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| [License Compliance](compliance/license_compliance/index.md):<br>View License Compliance reports **(ULTIMATE)** | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| [License Compliance](compliance/license_compliance/index.md):<br>View License list **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | +| [License Compliance](compliance/license_compliance/index.md):<br>Manage license policy **(ULTIMATE)** | | | | ✓ | ✓ | +| [Merge requests](project/merge_requests/index.md):<br>Assign reviewer | | ✓ | ✓ | ✓ | ✓ | +| [Merge requests](project/merge_requests/index.md):<br>See list | | ✓ | ✓ | ✓ | ✓ | +| [Merge requests](project/merge_requests/index.md):<br>Apply code change suggestions | | | ✓ | ✓ | ✓ | +| [Merge requests](project/merge_requests/index.md):<br>Approve (*9*) | | | ✓ | ✓ | ✓ | +| [Merge requests](project/merge_requests/index.md):<br>Assign | | | ✓ | ✓ | ✓ | +| [Merge requests](project/merge_requests/index.md):<br>Create (*18*) | | | ✓ | ✓ | ✓ | +| [Merge requests](project/merge_requests/index.md):<br>Add labels | | | ✓ | ✓ | ✓ | +| [Merge requests](project/merge_requests/index.md):<br>Lock threads | | | ✓ | ✓ | ✓ | +| [Merge requests](project/merge_requests/index.md):<br>Manage or accept | | | ✓ | ✓ | ✓ | +| [Merge requests](project/merge_requests/index.md):<br>Manage merge approval rules (project settings) | | | | ✓ | ✓ | +| [Merge requests](project/merge_requests/index.md):<br>Delete | | | | | ✓ | +| [Metrics dashboards](../operations/metrics/dashboards/index.md):<br>Manage user-starred metrics dashboards (*7*) | ✓ | ✓ | ✓ | ✓ | ✓ | +| [Metrics dashboards](../operations/metrics/dashboards/index.md):<br>View metrics dashboard annotations | | ✓ | ✓ | ✓ | ✓ | +| [Metrics dashboards](../operations/metrics/dashboards/index.md):<br>Create/edit/delete metrics dashboard annotations | | | ✓ | ✓ | ✓ | +| [Package registry](packages/index.md):<br>Pull package | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| [Package registry](packages/index.md):<br>Publish package | | | ✓ | ✓ | ✓ | +| [Package registry](packages/index.md):<br>Delete package | | | | ✓ | ✓ | +| [Project operations](../operations/index.md):<br>View [Error Tracking](../operations/error_tracking.md) list | | ✓ | ✓ | ✓ | ✓ | +| [Project operations](../operations/index.md):<br>Manage [Feature Flags](../operations/feature_flags.md) **(PREMIUM)** | | | ✓ | ✓ | ✓ | +| [Project operations](../operations/index.md):<br>Manage [Error Tracking](../operations/error_tracking.md) | | | | ✓ | ✓ | +| [Projects](project/index.md):<br>Download project | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>Leave comments | ✓ | ✓ | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>Reposition comments on images (posted by any user) | ✓ (*10*) | ✓ (*10*) | ✓ (*10*) | ✓ | ✓ | +| [Projects](project/index.md):<br>View Insights **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>View [releases](project/releases/index.md) | ✓ (*6*) | ✓ | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>View Requirements **(ULTIMATE)** | ✓ | ✓ | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>View [time tracking](project/time_tracking.md) reports | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>View [wiki](project/wiki/index.md) pages | ✓ | ✓ | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>Create [snippets](snippets.md) | | ✓ | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>Manage labels | | ✓ | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>View [project traffic statistics](../api/project_statistics.md) | | ✓ | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>Create, edit, delete [milestones](project/milestones/index.md). | | | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>Create, edit, delete [releases](project/releases/index.md) | | | ✓ (*13*) | ✓ (*13*) | ✓ (*13*) | +| [Projects](project/index.md):<br>Create, edit [wiki](project/wiki/index.md) pages | | | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>Enable Review Apps | | | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>View project [Audit Events](../administration/audit_events.md) | | | ✓ (*11*) | ✓ | ✓ | +| [Projects](project/index.md):<br>Add deploy keys | | | | ✓ | ✓ | +| [Projects](project/index.md):<br>Add new team members | | | | ✓ | ✓ | +| [Projects](project/index.md):<br>Change [project features visibility](../public_access/public_access.md) level | | | | ✓ (14) | ✓ | +| [Projects](project/index.md):<br>Configure [webhooks](project/integrations/webhooks.md) | | | | ✓ | ✓ | +| [Projects](project/index.md):<br>Delete [wiki](project/wiki/index.md) pages | | | ✓ | ✓ | ✓ | +| [Projects](project/index.md):<br>Edit comments (posted by any user) | | | | ✓ | ✓ | +| [Projects](project/index.md):<br>Edit project badges | | | | ✓ | ✓ | +| [Projects](project/index.md):<br>Edit project settings | | | | ✓ | ✓ | +| [Projects](project/index.md):<br>Export project | | | | ✓ | ✓ | +| [Projects](project/index.md):<br>Manage [project access tokens](project/settings/project_access_tokens.md) **(FREE SELF)** **(PREMIUM SAAS)** (*12*) | | | | ✓ | ✓ | +| [Projects](project/index.md):<br>Manage [Project Operations](../operations/index.md) | | | | ✓ | ✓ | +| [Projects](project/index.md):<br>Share (invite) projects with groups | | | | ✓ (*8*) | ✓ (*8*) | +| [Projects](project/index.md):<br>View 2FA status of members | | | | ✓ | ✓ | +| [Projects](project/index.md):<br>Administer project compliance frameworks | | | | | ✓ | +| [Projects](project/index.md):<br>Archive project | | | | | ✓ | +| [Projects](project/index.md):<br>Change project visibility level | | | | | ✓ | +| [Projects](project/index.md):<br>Delete project | | | | | ✓ | +| [Projects](project/index.md):<br>Disable notification emails | | | | | ✓ | +| [Projects](project/index.md):<br>Rename project | | | | | ✓ | +| [Projects](project/index.md):<br>Transfer project to another namespace | | | | | ✓ | +| [Repository](project/repository/index.md):<br>Pull project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>View project code | ✓ (*1*) | ✓ | ✓ | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>View a commit status | | ✓ | ✓ | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Add tags | | | ✓ | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Create new branches | | | ✓ | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Create or update commit status | | | ✓ (*5*) | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Force push to non-protected branches | | | ✓ | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Push to non-protected branches | | | ✓ | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Remove non-protected branches | | | ✓ | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Rewrite or remove Git tags | | | ✓ | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Enable or disable branch protection | | | | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Enable or disable tag protection | | | | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Manage [push rules](../push_rules/push_rules.md) | | | | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Push to protected branches (*5*) | | | | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Turn on or off protected branch push for developers | | | | ✓ | ✓ | +| [Repository](project/repository/index.md):<br>Remove fork relationship | | | | | ✓ | +| [Repository](project/repository/index.md):<br>Force push to protected branches (*4*) | | | | | | +| [Repository](project/repository/index.md):<br>Remove protected branches (*4*) | | | | | | +| [Requirements Management](project/requirements/index.md):<br>Archive / reopen **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | +| [Requirements Management](project/requirements/index.md):<br>Create / edit **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | +| [Requirements Management](project/requirements/index.md):<br>Import / export **(ULTIMATE)** | | ✓ | ✓ | ✓ | ✓ | +| [Security dashboard](application_security/security_dashboard/index.md):<br>View Security reports **(ULTIMATE)** | ✓ (*3*) | ✓ | ✓ | ✓ | ✓ | +| [Security dashboard](application_security/security_dashboard/index.md):<br>Create issue from vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Security dashboard](application_security/security_dashboard/index.md):<br>Create vulnerability from vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Security dashboard](application_security/security_dashboard/index.md):<br>Dismiss vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Security dashboard](application_security/security_dashboard/index.md):<br>Dismiss vulnerability finding **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Security dashboard](application_security/security_dashboard/index.md):<br>Resolve vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Security dashboard](application_security/security_dashboard/index.md):<br>Revert vulnerability to detected state **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Security dashboard](application_security/security_dashboard/index.md):<br>Use security dashboard **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Security dashboard](application_security/security_dashboard/index.md):<br>View vulnerability **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Security dashboard](application_security/security_dashboard/index.md):<br>View vulnerability findings in [dependency list](application_security/dependency_list/index.md) **(ULTIMATE)** | | | ✓ | ✓ | ✓ | +| [Terraform](infrastructure/index.md):<br>Read Terraform state | | | ✓ | ✓ | ✓ | +| [Terraform](infrastructure/index.md):<br>Manage Terraform state | | | | ✓ | ✓ | +| [Test cases](../ci/test_cases/index.md):<br>Archive | | ✓ | ✓ | ✓ | ✓ | +| [Test cases](../ci/test_cases/index.md):<br>Create | | ✓ | ✓ | ✓ | ✓ | +| [Test cases](../ci/test_cases/index.md):<br>Move | | ✓ | ✓ | ✓ | ✓ | +| [Test cases](../ci/test_cases/index.md):<br>Reopen | | ✓ | ✓ | ✓ | ✓ | 1. On self-managed GitLab instances, guest users are able to perform this action only on public and internal projects (not on private projects). [External users](#external-users) diff --git a/lib/sidebars/groups/menus/ci_cd_menu.rb b/lib/sidebars/groups/menus/ci_cd_menu.rb index f5bce57f496..a1f98b918e6 100644 --- a/lib/sidebars/groups/menus/ci_cd_menu.rb +++ b/lib/sidebars/groups/menus/ci_cd_menu.rb @@ -34,10 +34,8 @@ module Sidebars ) end - # TODO Proper policies, such as `read_group_runners`, should be implemented per - # See https://gitlab.com/gitlab-org/gitlab/-/issues/334802 def show_runners? - can?(context.current_user, :admin_group, context.group) && + can?(context.current_user, :read_group_runners, context.group) && Feature.enabled?(:runner_list_group_view_vue_ui, context.group, default_enabled: :yaml) end end diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 1840f630ada..98356de7376 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -4793,7 +4793,7 @@ msgstr "" msgid "Ask someone with write access to resolve it." msgstr "" -msgid "Ask your group maintainer to set up a group runner." +msgid "Ask your group owner to set up a group runner." msgstr "" msgid "Assertion consumer service URL" @@ -16754,9 +16754,6 @@ msgstr "" msgid "Group jobs by" msgstr "" -msgid "Group maintainers can register group runners in the %{link}" -msgstr "" - msgid "Group members" msgstr "" @@ -16781,6 +16778,9 @@ msgstr "" msgid "Group overview content" msgstr "" +msgid "Group owners can register group runners in the %{link}" +msgstr "" + msgid "Group path is already taken. We've suggested one that is available." msgstr "" @@ -42052,6 +42052,9 @@ msgstr "" msgid "failed to dismiss associated finding(id=%{finding_id}): %{message}" msgstr "" +msgid "failed to dismiss finding: %{message}" +msgstr "" + msgid "failed to revert associated finding(id=%{finding_id}) to detected" msgstr "" diff --git a/spec/features/runners_spec.rb b/spec/features/runners_spec.rb index 22de77f7cd0..49c468976b9 100644 --- a/spec/features/runners_spec.rb +++ b/spec/features/runners_spec.rb @@ -268,10 +268,27 @@ RSpec.describe 'Runners' do it 'group runners are not available' do visit project_runners_path(project) + expect(page).not_to have_content 'Group owners can register group runners in the group\'s CI/CD settings.' + expect(page).to have_content 'Ask your group owner to set up a group runner' + end + end + end + + context 'as project maintainer and group owner' do + before do + group.add_owner(user) + end + + context 'project with a group but no group runner' do + let(:project) { create :project, group: group } + + it 'group runners are available' do + visit project_runners_path(project) + expect(page).to have_content 'This group does not have any group runners yet.' - expect(page).to have_content 'Group maintainers can register group runners in the group\'s CI/CD settings.' - expect(page).not_to have_content 'Ask your group maintainer to set up a group runner' + expect(page).to have_content 'Group owners can register group runners in the group\'s CI/CD settings.' + expect(page).not_to have_content 'Ask your group owner to set up a group runner' end end end @@ -296,8 +313,8 @@ RSpec.describe 'Runners' do expect(page).to have_content 'This group does not have any group runners yet.' - expect(page).not_to have_content 'Group maintainers can register group runners in the group\'s CI/CD settings.' - expect(page).to have_content 'Ask your group maintainer to set up a group runner.' + expect(page).not_to have_content 'Group owners can register group runners in the group\'s CI/CD settings.' + expect(page).to have_content 'Ask your group owner to set up a group runner.' end end diff --git a/spec/frontend/diffs/components/image_diff_overlay_spec.js b/spec/frontend/diffs/components/image_diff_overlay_spec.js index 47b144b2387..8c1a8041f6c 100644 --- a/spec/frontend/diffs/components/image_diff_overlay_spec.js +++ b/spec/frontend/diffs/components/image_diff_overlay_spec.js @@ -6,8 +6,8 @@ import { imageDiffDiscussions } from '../mock_data/diff_discussions'; describe('Diffs image diff overlay component', () => { const dimensions = { - width: 100, - height: 200, + width: 99.9, + height: 199.5, }; let wrapper; let dispatch; @@ -38,7 +38,6 @@ describe('Diffs image diff overlay component', () => { afterEach(() => { wrapper.destroy(); - wrapper = null; }); it('renders comment badges', () => { @@ -81,17 +80,21 @@ describe('Diffs image diff overlay component', () => { it('dispatches openDiffFileCommentForm when clicking overlay', () => { createComponent({ canComment: true }); - wrapper.find('.js-add-image-diff-note-button').trigger('click', { offsetX: 0, offsetY: 0 }); + wrapper.find('.js-add-image-diff-note-button').trigger('click', { offsetX: 1.2, offsetY: 3.8 }); expect(dispatch).toHaveBeenCalledWith('diffs/openDiffFileCommentForm', { fileHash: 'ABC', - x: 0, - y: 0, + x: 1, + y: 4, width: 100, height: 200, - xPercent: 0, - yPercent: 0, + xPercent: expect.any(Number), + yPercent: expect.any(Number), }); + + const { xPercent, yPercent } = dispatch.mock.calls[0][1]; + expect(xPercent).toBeCloseTo(0.6); + expect(yPercent).toBeCloseTo(1.9); }); describe('toggle discussion', () => { diff --git a/spec/graphql/types/mutation_type_spec.rb b/spec/graphql/types/mutation_type_spec.rb index 95d835c88cf..1fc46f2d511 100644 --- a/spec/graphql/types/mutation_type_spec.rb +++ b/spec/graphql/types/mutation_type_spec.rb @@ -7,6 +7,14 @@ RSpec.describe Types::MutationType do expect(described_class).to have_graphql_mutation(Mutations::MergeRequests::SetDraft) end + describe 'deprecated mutations' do + describe 'clusterAgentTokenDelete' do + let(:field) { get_field('clusterAgentTokenDelete') } + + it { expect(field.deprecation_reason).to eq('Tokens must be revoked with ClusterAgentTokenRevoke. Deprecated in 14.7.') } + end + end + def get_field(name) described_class.fields[GraphqlHelpers.fieldnamerize(name)] end diff --git a/spec/policies/group_policy_spec.rb b/spec/policies/group_policy_spec.rb index 08fc8d2e77c..d2dee3b781c 100644 --- a/spec/policies/group_policy_spec.rb +++ b/spec/policies/group_policy_spec.rb @@ -36,6 +36,7 @@ RSpec.describe GroupPolicy do it { expect_disallowed(:read_crm_organization) } it { expect_disallowed(:read_crm_contact) } it { expect_disallowed(:read_counts) } + it { expect_disallowed(:read_group_runners) } it { expect_disallowed(*read_group_permissions) } end @@ -51,6 +52,7 @@ RSpec.describe GroupPolicy do it { expect_disallowed(:read_crm_organization) } it { expect_disallowed(:read_crm_contact) } it { expect_disallowed(:read_counts) } + it { expect_disallowed(:read_group_runners) } it { expect_disallowed(*read_group_permissions) } end @@ -1126,9 +1128,7 @@ RSpec.describe GroupPolicy do context 'with maintainer' do let(:current_user) { maintainer } - it { is_expected.to be_allowed(:register_group_runners) } - - it_behaves_like 'expected outcome based on runner registration control' + it { is_expected.to be_disallowed(:register_group_runners) } end context 'with reporter' do diff --git a/spec/support/shared_contexts/policies/group_policy_shared_context.rb b/spec/support/shared_contexts/policies/group_policy_shared_context.rb index 88b0d997a80..db778086692 100644 --- a/spec/support/shared_contexts/policies/group_policy_shared_context.rb +++ b/spec/support/shared_contexts/policies/group_policy_shared_context.rb @@ -48,22 +48,24 @@ RSpec.shared_context 'GroupPolicy context' do destroy_package create_projects read_cluster create_cluster update_cluster admin_cluster add_cluster - admin_group_runners ] end let(:owner_permissions) do - [ - :owner_access, - :admin_group, - :admin_namespace, - :admin_group_member, - :change_visibility_level, - :set_note_created_at, - :create_subgroup, - :read_statistics, - :update_default_branch_protection - ].compact + %i[ + owner_access + admin_group + admin_namespace + admin_group_member + change_visibility_level + set_note_created_at + create_subgroup + read_statistics + update_default_branch_protection + read_group_runners + admin_group_runners + register_group_runners + ] end let(:admin_permissions) { %i[read_confidential_issues] } |