diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-23 06:08:35 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2023-05-23 06:08:35 +0300 |
commit | 571bbefbd4e15c5462a35a1f041a6caa8d236c08 (patch) | |
tree | 358a6099fb18d3514b935a84e8169b66dd2b51f0 | |
parent | 82f96a9ae2529898de0e91ccfad1d6457f3c1975 (diff) |
Add latest changes from gitlab-org/gitlab@master
-rw-r--r-- | .gitlab/ci/rules.gitlab-ci.yml | 72 | ||||
-rw-r--r-- | app/graphql/mutations/environments/update.rb | 17 | ||||
-rw-r--r-- | app/graphql/types/permission_types/work_item.rb | 3 | ||||
-rw-r--r-- | app/services/environments/update_service.rb | 21 | ||||
-rw-r--r-- | app/services/merge_requests/close_service.rb | 2 | ||||
-rw-r--r-- | app/services/merge_requests/reopen_service.rb | 2 | ||||
-rw-r--r-- | doc/api/graphql/reference/index.md | 26 | ||||
-rw-r--r-- | locale/gitlab.pot | 14 | ||||
-rw-r--r-- | spec/graphql/mutations/environments/update_spec.rb | 48 | ||||
-rw-r--r-- | spec/graphql/types/permission_types/work_item_spec.rb | 2 | ||||
-rw-r--r-- | spec/requests/api/graphql/work_item_spec.rb | 3 | ||||
-rw-r--r-- | spec/services/environments/update_service_spec.rb | 56 |
12 files changed, 239 insertions, 27 deletions
diff --git a/.gitlab/ci/rules.gitlab-ci.yml b/.gitlab/ci/rules.gitlab-ci.yml index f49b2e2e459..9390d89212c 100644 --- a/.gitlab/ci/rules.gitlab-ci.yml +++ b/.gitlab/ci/rules.gitlab-ci.yml @@ -860,15 +860,22 @@ variables: ARCH: amd64,arm64 -# We want to rebuild the base image when the full e2e test pipeline runs. Currently this happens on a 2 hour schedule. +# We use a multi-stage image to: +# - (re)build the first stage in master pipelines (including scheduled pipelines), and +# - build the final stage in code-change pipelines (including MRs), and scheduled pipelines +# This has to match ".qa:rules:e2e:test-on-gdk" otherwise there won't be an image available to run GDK in the test jobs. +# Unfortunately, we can't just include ".qa:rules:e2e:test-on-gdk" because some of the conditions are manual .build-images:rules:build-gdk-image: rules: - if: '$QA_RUN_TESTS_ON_GDK !~ /true|yes|1/i' when: never - - <<: *if-not-canonical-namespace - when: never - - <<: *if-not-ee + - !reference [".qa:rules:package-and-test-never-run", rules] + - <<: *if-default-branch-schedule-nightly # already executed in the 2-hourly schedule when: never + - <<: *if-default-branch-refs # Includes scheduled pipelines + variables: + BUILD_GDK_BASE: "true" + allow_failure: true # We want to also rebuild the base image if MRs change certain components. - <<: *if-merge-request variables: @@ -882,10 +889,36 @@ - GITLAB_METRICS_EXPORTER_VERSION - GITLAB_SHELL_VERSION - GITALY_SERVER_VERSION + allow_failure: true + # The rest are included to be consistent with .qa:rules:e2e:test-on-gdk + - <<: *if-merge-request-targeting-stable-branch + allow_failure: true + - <<: *if-ruby2-branch + allow_failure: true + # We include the job under the matching conditions below, but unlike in .qa:rules:e2e:test-on-gdk we don't need to + # set OMNIBUS_GITLAB_BUILD_ON_ALL_OS when testing against GDK - <<: *if-merge-request - - <<: *if-default-branch-refs - variables: - BUILD_GDK_BASE: "true" + changes: *dependency-patterns + allow_failure: true + - <<: *if-merge-request-labels-run-all-e2e + allow_failure: true + - <<: *if-merge-request + changes: *feature-flag-development-config-patterns + allow_failure: true + - <<: *if-merge-request + changes: *initializers-patterns + allow_failure: true + - <<: *if-merge-request + changes: *nodejs-patterns + allow_failure: true + - <<: *if-merge-request + changes: *ci-qa-patterns + allow_failure: true + - <<: *if-merge-request + changes: *code-qa-patterns + allow_failure: true + - <<: *if-force-ci + allow_failure: true .build-images:rules:build-assets-image: rules: @@ -1325,6 +1358,13 @@ ############ # QA rules # ############ +.qa:rules:code-merge-request-manual: + rules: + - <<: *if-merge-request + changes: *code-patterns + when: manual + allow_failure: true + .qa:rules:internal: rules: - <<: *if-default-refs @@ -1395,7 +1435,7 @@ .qa:rules:package-and-test-common: rules: - - !reference [.qa:rules:package-and-test-never-run, rules] + - !reference [".qa:rules:package-and-test-never-run", rules] - <<: *if-merge-request-targeting-stable-branch allow_failure: true - <<: *if-ruby2-branch @@ -1436,10 +1476,9 @@ - <<: *if-force-ci when: manual allow_failure: true - - <<: *if-merge-request - changes: *code-patterns - when: manual - allow_failure: true + # We used to have a rule at the end here that would catch any remaining code MRs and allow the job to be run + # manually. That rule is now in ".qa:rules:code-merge-request-manual" so it can be included when needed and we can + # still use ".qa:rules:package-and-test-common" in jobs we don't want to be manual. .qa:rules:package-and-test-schedule: rules: @@ -1459,10 +1498,11 @@ when: never - !reference [".qa:rules:package-and-test-common", rules] - !reference [".qa:rules:package-and-test-schedule", rules] + - !reference [".qa:rules:code-merge-request-manual", rules] .qa:rules:package-and-test-ce: rules: - - !reference [.qa:rules:package-and-test-never-run, rules] + - !reference [".qa:rules:package-and-test-never-run", rules] - <<: *if-dot-com-gitlab-org-and-security-merge-request changes: *ci-build-images-patterns when: manual @@ -1487,10 +1527,14 @@ when: never - !reference [".qa:rules:package-and-test-common", rules] - !reference [".qa:rules:package-and-test-schedule", rules] + # Run automatically in all other code MRs that weren't included in ".qa:rules:package-and-test-common". + - <<: *if-merge-request + changes: *code-patterns + allow_failure: true .qa:rules:package-and-test-old-nav: rules: - - !reference [.qa:rules:package-and-test-never-run, rules] + - !reference [".qa:rules:package-and-test-never-run", rules] - <<: *if-merge-request changes: *code-patterns when: manual diff --git a/app/graphql/mutations/environments/update.rb b/app/graphql/mutations/environments/update.rb index dc1fb9b23af..431a7add00e 100644 --- a/app/graphql/mutations/environments/update.rb +++ b/app/graphql/mutations/environments/update.rb @@ -23,6 +23,11 @@ module Mutations required: false, description: 'Tier of the environment.' + argument :cluster_agent_id, + ::Types::GlobalIDType[::Clusters::Agent], + required: false, + description: 'Cluster agent of the environment.' + field :environment, Types::EnvironmentType, null: true, @@ -31,6 +36,8 @@ module Mutations def resolve(id:, **kwargs) environment = authorized_find!(id: id) + convert_cluster_agent_id(kwargs) + response = ::Environments::UpdateService.new(environment.project, current_user, kwargs).execute(environment) if response.success? @@ -39,6 +46,16 @@ module Mutations { environment: response.payload[:environment], errors: response.errors } end end + + private + + def convert_cluster_agent_id(kwargs) + return unless kwargs.key?(:cluster_agent_id) + + kwargs[:cluster_agent] = if kwargs[:cluster_agent_id] + ::Clusters::Agent.find_by_id(kwargs[:cluster_agent_id].model_id) + end + end end end end diff --git a/app/graphql/types/permission_types/work_item.rb b/app/graphql/types/permission_types/work_item.rb index 0b6a384ec0e..d9946fc4ea6 100644 --- a/app/graphql/types/permission_types/work_item.rb +++ b/app/graphql/types/permission_types/work_item.rb @@ -7,7 +7,8 @@ module Types description 'Check permissions for the current user on a work item' abilities :read_work_item, :update_work_item, :delete_work_item, - :admin_work_item, :admin_parent_link, :set_work_item_metadata + :admin_work_item, :admin_parent_link, :set_work_item_metadata, + :create_note end end end diff --git a/app/services/environments/update_service.rb b/app/services/environments/update_service.rb index e02b2398426..5eb4880ec4b 100644 --- a/app/services/environments/update_service.rb +++ b/app/services/environments/update_service.rb @@ -2,6 +2,8 @@ module Environments class UpdateService < BaseService + ALLOWED_ATTRIBUTES = %i[external_url tier cluster_agent].freeze + def execute(environment) unless can?(current_user, :update_environment, environment) return ServiceResponse.error( @@ -10,7 +12,13 @@ module Environments ) end - if environment.update(**params) + if unauthorized_cluster_agent? + return ServiceResponse.error( + message: _('Unauthorized to access the cluster agent in this project'), + payload: { environment: environment }) + end + + if environment.update(**params.slice(*ALLOWED_ATTRIBUTES)) ServiceResponse.success(payload: { environment: environment }) else ServiceResponse.error( @@ -19,5 +27,16 @@ module Environments ) end end + + private + + def unauthorized_cluster_agent? + return false unless params[:cluster_agent] + + ::Clusters::Agents::Authorizations::UserAccess::Finder + .new(current_user, agent: params[:cluster_agent], project: project) + .execute + .empty? + end end end diff --git a/app/services/merge_requests/close_service.rb b/app/services/merge_requests/close_service.rb index 867e8221e5e..62928e05a89 100644 --- a/app/services/merge_requests/close_service.rb +++ b/app/services/merge_requests/close_service.rb @@ -51,4 +51,4 @@ module MergeRequests end end -MergeRequests::CloseService.prepend_mod_with('MergeRequests::CloseService') +MergeRequests::CloseService.prepend_mod diff --git a/app/services/merge_requests/reopen_service.rb b/app/services/merge_requests/reopen_service.rb index d2247a6d4c1..b2e15cc7c7e 100644 --- a/app/services/merge_requests/reopen_service.rb +++ b/app/services/merge_requests/reopen_service.rb @@ -37,3 +37,5 @@ module MergeRequests end end end + +MergeRequests::ReopenService.prepend_mod diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 23d914eee12..6384d896292 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -3141,6 +3141,7 @@ Input type: `EnvironmentUpdateInput` | Name | Type | Description | | ---- | ---- | ----------- | | <a id="mutationenvironmentupdateclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| <a id="mutationenvironmentupdateclusteragentid"></a>`clusterAgentId` | [`ClustersAgentID`](#clustersagentid) | Cluster agent of the environment. | | <a id="mutationenvironmentupdateexternalurl"></a>`externalUrl` | [`String`](#string) | External URL of the environment. | | <a id="mutationenvironmentupdateid"></a>`id` | [`EnvironmentID!`](#environmentid) | Global ID of the environment to update. | | <a id="mutationenvironmentupdatetier"></a>`tier` | [`DeploymentTier`](#deploymenttier) | Tier of the environment. | @@ -3569,6 +3570,24 @@ Input type: `GoogleCloudLoggingConfigurationCreateInput` | <a id="mutationgooglecloudloggingconfigurationcreateerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | | <a id="mutationgooglecloudloggingconfigurationcreategooglecloudloggingconfiguration"></a>`googleCloudLoggingConfiguration` | [`GoogleCloudLoggingConfigurationType`](#googlecloudloggingconfigurationtype) | configuration created. | +### `Mutation.googleCloudLoggingConfigurationDestroy` + +Input type: `GoogleCloudLoggingConfigurationDestroyInput` + +#### Arguments + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="mutationgooglecloudloggingconfigurationdestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| <a id="mutationgooglecloudloggingconfigurationdestroyid"></a>`id` | [`AuditEventsGoogleCloudLoggingConfigurationID!`](#auditeventsgooglecloudloggingconfigurationid) | ID of the google cloud logging configuration to destroy. | + +#### Fields + +| Name | Type | Description | +| ---- | ---- | ----------- | +| <a id="mutationgooglecloudloggingconfigurationdestroyclientmutationid"></a>`clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | +| <a id="mutationgooglecloudloggingconfigurationdestroyerrors"></a>`errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | + ### `Mutation.groupMemberBulkUpdate` Input type: `GroupMemberBulkUpdateInput` @@ -23457,6 +23476,7 @@ Check permissions for the current user on a work item. | ---- | ---- | ----------- | | <a id="workitempermissionsadminparentlink"></a>`adminParentLink` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_parent_link` on this resource. | | <a id="workitempermissionsadminworkitem"></a>`adminWorkItem` | [`Boolean!`](#boolean) | Indicates the user can perform `admin_work_item` on this resource. | +| <a id="workitempermissionscreatenote"></a>`createNote` | [`Boolean!`](#boolean) | Indicates the user can perform `create_note` on this resource. | | <a id="workitempermissionsdeleteworkitem"></a>`deleteWorkItem` | [`Boolean!`](#boolean) | Indicates the user can perform `delete_work_item` on this resource. | | <a id="workitempermissionsreadworkitem"></a>`readWorkItem` | [`Boolean!`](#boolean) | Indicates the user can perform `read_work_item` on this resource. | | <a id="workitempermissionssetworkitemmetadata"></a>`setWorkItemMetadata` | [`Boolean!`](#boolean) | Indicates the user can perform `set_work_item_metadata` on this resource. | @@ -26214,6 +26234,12 @@ A `AuditEventsExternalAuditEventDestinationID` is a global ID. It is encoded as An example `AuditEventsExternalAuditEventDestinationID` is: `"gid://gitlab/AuditEvents::ExternalAuditEventDestination/1"`. +### `AuditEventsGoogleCloudLoggingConfigurationID` + +A `AuditEventsGoogleCloudLoggingConfigurationID` is a global ID. It is encoded as a string. + +An example `AuditEventsGoogleCloudLoggingConfigurationID` is: `"gid://gitlab/AuditEvents::GoogleCloudLoggingConfiguration/1"`. + ### `AuditEventsInstanceExternalAuditEventDestinationID` A `AuditEventsInstanceExternalAuditEventDestinationID` is a global ID. It is encoded as a string. diff --git a/locale/gitlab.pot b/locale/gitlab.pot index de1f98d3638..e687b6a7456 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -39811,10 +39811,10 @@ msgstr "" msgid "ScanExecutionPolicy|%{period} %{days} at %{time}" msgstr "" -msgid "ScanExecutionPolicy|%{rules} actions for the %{scopes} %{branches} %{agents} %{namespaces}" +msgid "ScanExecutionPolicy|%{rules} %{period} for %{scopes} %{branches} %{agents} %{namespaces}" msgstr "" -msgid "ScanExecutionPolicy|A pipeline is run" +msgid "ScanExecutionPolicy|%{rules} every time a pipeline runs for %{scopes} %{branches} %{agents} %{namespaces}" msgstr "" msgid "ScanExecutionPolicy|Add condition" @@ -39835,10 +39835,10 @@ msgstr "" msgid "ScanExecutionPolicy|Scanner profile" msgstr "" -msgid "ScanExecutionPolicy|Schedule" +msgid "ScanExecutionPolicy|Schedule rule component" msgstr "" -msgid "ScanExecutionPolicy|Schedule rule component" +msgid "ScanExecutionPolicy|Schedules:" msgstr "" msgid "ScanExecutionPolicy|Select agent" @@ -39862,6 +39862,9 @@ msgstr "" msgid "ScanExecutionPolicy|Tags" msgstr "" +msgid "ScanExecutionPolicy|Triggers:" +msgstr "" + msgid "ScanExecutionPolicy|agent" msgstr "" @@ -48003,6 +48006,9 @@ msgstr "" msgid "Unauthenticated web rate limit period in seconds" msgstr "" +msgid "Unauthorized to access the cluster agent in this project" +msgstr "" + msgid "Unauthorized to create an environment" msgstr "" diff --git a/spec/graphql/mutations/environments/update_spec.rb b/spec/graphql/mutations/environments/update_spec.rb index 87c1bd5a44b..5c61b3c5dbe 100644 --- a/spec/graphql/mutations/environments/update_spec.rb +++ b/spec/graphql/mutations/environments/update_spec.rb @@ -18,10 +18,10 @@ RSpec.describe Mutations::Environments::Update, feature_category: :environment_m end describe '#resolve' do - subject { mutation.resolve(id: environment_id, external_url: external_url) } + subject { mutation.resolve(id: environment_id, **kwargs) } let(:environment_id) { environment.to_global_id } - let(:external_url) { 'https://gitlab.com/' } + let(:kwargs) { { external_url: 'https://gitlab.com/' } } context 'when service execution succeeded' do it 'returns no errors' do @@ -29,12 +29,12 @@ RSpec.describe Mutations::Environments::Update, feature_category: :environment_m end it 'updates the environment' do - expect(subject[:environment][:external_url]).to eq(external_url) + expect(subject[:environment][:external_url]).to eq('https://gitlab.com/') end end context 'when service cannot update the attribute' do - let(:external_url) { 'http://${URL}' } + let(:kwargs) { { external_url: 'http://${URL}' } } it 'returns an error' do expect(subject) @@ -45,6 +45,46 @@ RSpec.describe Mutations::Environments::Update, feature_category: :environment_m end end + context 'when setting cluster agent ID to the environment' do + let_it_be(:cluster_agent) { create(:cluster_agent, project: project) } + + let!(:authorization) { create(:agent_user_access_project_authorization, project: project, agent: cluster_agent) } + + let(:kwargs) { { cluster_agent_id: cluster_agent.to_global_id } } + + it 'sets the cluster agent to the environment' do + expect(subject[:environment].cluster_agent).to eq(cluster_agent) + end + end + + context 'when unsetting cluster agent ID to the environment' do + let_it_be(:cluster_agent) { create(:cluster_agent, project: project) } + + let(:kwargs) { { cluster_agent_id: nil } } + + before do + environment.update!(cluster_agent: cluster_agent) + end + + it 'removes the cluster agent from the environment' do + expect(subject[:environment].cluster_agent).to be_nil + end + end + + context 'when the cluster agent is not updated' do + let_it_be(:cluster_agent) { create(:cluster_agent, project: project) } + + let(:kwargs) { { external_url: 'https://dev.gitlab.com/' } } + + before do + environment.update!(cluster_agent: cluster_agent) + end + + it 'does not change the environment cluster agent' do + expect(subject[:environment].cluster_agent).to eq(cluster_agent) + end + end + context 'when user is reporter who does not have permission to access the environment' do let(:user) { reporter } diff --git a/spec/graphql/types/permission_types/work_item_spec.rb b/spec/graphql/types/permission_types/work_item_spec.rb index 7e16b43a12f..3ee42e2e3ad 100644 --- a/spec/graphql/types/permission_types/work_item_spec.rb +++ b/spec/graphql/types/permission_types/work_item_spec.rb @@ -6,7 +6,7 @@ RSpec.describe Types::PermissionTypes::WorkItem do it do expected_permissions = [ :read_work_item, :update_work_item, :delete_work_item, :admin_work_item, - :admin_parent_link, :set_work_item_metadata + :admin_parent_link, :set_work_item_metadata, :create_note ] expected_permissions.each do |permission| diff --git a/spec/requests/api/graphql/work_item_spec.rb b/spec/requests/api/graphql/work_item_spec.rb index dc5004a121b..f315501f0fa 100644 --- a/spec/requests/api/graphql/work_item_spec.rb +++ b/spec/requests/api/graphql/work_item_spec.rb @@ -69,7 +69,8 @@ RSpec.describe 'Query.work_item(id)', feature_category: :team_planning do 'deleteWorkItem' => false, 'adminWorkItem' => true, 'adminParentLink' => true, - 'setWorkItemMetadata' => true + 'setWorkItemMetadata' => true, + 'createNote' => true }, 'project' => hash_including('id' => project.to_gid.to_s, 'fullPath' => project.full_path) ) diff --git a/spec/services/environments/update_service_spec.rb b/spec/services/environments/update_service_spec.rb index 72ace3b050e..84220c0930b 100644 --- a/spec/services/environments/update_service_spec.rb +++ b/spec/services/environments/update_service_spec.rb @@ -28,6 +28,50 @@ RSpec.describe Environments::UpdateService, feature_category: :environment_manag expect(response.payload[:environment]).to eq(environment) end + context 'when setting a cluster agent to the environment' do + let_it_be(:agent_management_project) { create(:project) } + let_it_be(:cluster_agent) { create(:cluster_agent, project: agent_management_project) } + + let!(:authorization) { create(:agent_user_access_project_authorization, project: project, agent: cluster_agent) } + let(:params) { { cluster_agent: cluster_agent } } + + it 'returns successful response' do + response = subject + + expect(response).to be_success + expect(response.payload[:environment].cluster_agent).to eq(cluster_agent) + end + + context 'when user does not have permission to read the agent' do + let!(:authorization) { nil } + + it 'returns an error' do + response = subject + + expect(response).to be_error + expect(response.message).to eq('Unauthorized to access the cluster agent in this project') + expect(response.payload[:environment]).to eq(environment) + end + end + end + + context 'when unsetting a cluster agent of the environment' do + let_it_be(:cluster_agent) { create(:cluster_agent, project: project) } + + let(:params) { { cluster_agent: nil } } + + before do + environment.update!(cluster_agent: cluster_agent) + end + + it 'returns successful response' do + response = subject + + expect(response).to be_success + expect(response.payload[:environment].cluster_agent).to be_nil + end + end + context 'when params contain invalid value' do let(:params) { { external_url: 'http://${URL}' } } @@ -40,6 +84,18 @@ RSpec.describe Environments::UpdateService, feature_category: :environment_manag end end + context 'when disallowed parameter is passed' do + let(:params) { { external_url: 'https://gitlab.com/', slug: 'prod' } } + + it 'ignores the parameter' do + response = subject + + expect(response).to be_success + expect(response.payload[:environment].external_url).to eq('https://gitlab.com/') + expect(response.payload[:environment].slug).not_to eq('prod') + end + end + context 'when user is reporter' do let(:current_user) { reporter } |