From 20bd3b7d4ebb1d7ebef305656b156313d09a6674 Mon Sep 17 00:00:00 2001 From: GitLab Bot Date: Wed, 12 Aug 2020 09:09:44 +0000 Subject: [PATCH] Add latest changes from gitlab-org/gitlab@master --- GITALY_SERVER_VERSION | 2 +- ...e_cluster_applications_artifact_service.rb | 2 - ...ove_cluster_applications_artifact_flag.yml | 5 + .../graphql/reference/gitlab_schema.graphql | 51 ++++++ doc/api/graphql/reference/gitlab_schema.json | 167 ++++++++++++++++++ doc/api/graphql/reference/index.md | 10 ++ doc/ci/pipelines/index.md | 5 +- doc/ci/yaml/README.md | 4 + doc/user/clusters/applications.md | 5 + .../project/merge_requests/code_quality.md | 61 +++++++ lib/gitlab/sidekiq_logger.rb | 9 - ...ster_applications_artifact_service_spec.rb | 144 +++++++-------- 12 files changed, 372 insertions(+), 93 deletions(-) create mode 100644 changelogs/unreleased/remove_cluster_applications_artifact_flag.yml delete mode 100644 lib/gitlab/sidekiq_logger.rb diff --git a/GITALY_SERVER_VERSION b/GITALY_SERVER_VERSION index dfee4c122f3..a78697498ca 100644 --- a/GITALY_SERVER_VERSION +++ b/GITALY_SERVER_VERSION @@ -1 +1 @@ -6730c101d0be2db5155b6e2c4de689dc906337f4 +187f550dce577f1fb39503976a30a73a58b2b8e1 diff --git a/app/services/clusters/parse_cluster_applications_artifact_service.rb b/app/services/clusters/parse_cluster_applications_artifact_service.rb index e9a23b7c5f2..b9b2953b6bd 100644 --- a/app/services/clusters/parse_cluster_applications_artifact_service.rb +++ b/app/services/clusters/parse_cluster_applications_artifact_service.rb @@ -14,8 +14,6 @@ module Clusters end def execute(artifact) - return success unless Feature.enabled?(:cluster_applications_artifact, project) - raise ArgumentError, 'Artifact is not cluster_applications file type' unless artifact&.cluster_applications? return error(too_big_error_message, :bad_request) unless artifact.file.size < MAX_ACCEPTABLE_ARTIFACT_SIZE diff --git a/changelogs/unreleased/remove_cluster_applications_artifact_flag.yml b/changelogs/unreleased/remove_cluster_applications_artifact_flag.yml new file mode 100644 index 00000000000..91d0ee244d4 --- /dev/null +++ b/changelogs/unreleased/remove_cluster_applications_artifact_flag.yml @@ -0,0 +1,5 @@ +--- +title: Enable state tracking for managed applications installed via the management project +merge_request: 38759 +author: +type: added diff --git a/doc/api/graphql/reference/gitlab_schema.graphql b/doc/api/graphql/reference/gitlab_schema.graphql index 3ffd76840b0..56cf71b6d6d 100644 --- a/doc/api/graphql/reference/gitlab_schema.graphql +++ b/doc/api/graphql/reference/gitlab_schema.graphql @@ -2907,6 +2907,56 @@ type DastSiteProfilePermissions { createOnDemandDastScan: Boolean! } +""" +Autogenerated input type of DastSiteProfileUpdate +""" +input DastSiteProfileUpdateInput { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + The project the site profile belongs to. + """ + fullPath: ID! + + """ + ID of the site profile to be updated. + """ + id: DastSiteProfileID! + + """ + The name of the site profile. + """ + profileName: String! + + """ + The URL of the target to be scanned. + """ + targetUrl: String +} + +""" +Autogenerated return type of DastSiteProfileUpdate +""" +type DastSiteProfileUpdatePayload { + """ + A unique identifier for the client performing the mutation. + """ + clientMutationId: String + + """ + Errors encountered during execution of the mutation. + """ + errors: [String!]! + + """ + ID of the site profile. + """ + id: DastSiteProfileID +} + enum DastSiteProfileValidationStatusEnum { """ Site validation process finished but failed @@ -9349,6 +9399,7 @@ type Mutation { dastScannerProfileCreate(input: DastScannerProfileCreateInput!): DastScannerProfileCreatePayload dastSiteProfileCreate(input: DastSiteProfileCreateInput!): DastSiteProfileCreatePayload dastSiteProfileDelete(input: DastSiteProfileDeleteInput!): DastSiteProfileDeletePayload + dastSiteProfileUpdate(input: DastSiteProfileUpdateInput!): DastSiteProfileUpdatePayload deleteAnnotation(input: DeleteAnnotationInput!): DeleteAnnotationPayload designManagementDelete(input: DesignManagementDeleteInput!): DesignManagementDeletePayload designManagementMove(input: DesignManagementMoveInput!): DesignManagementMovePayload diff --git a/doc/api/graphql/reference/gitlab_schema.json b/doc/api/graphql/reference/gitlab_schema.json index 17c01b227a5..b37573dc54e 100644 --- a/doc/api/graphql/reference/gitlab_schema.json +++ b/doc/api/graphql/reference/gitlab_schema.json @@ -7876,6 +7876,146 @@ "enumValues": null, "possibleTypes": null }, + { + "kind": "INPUT_OBJECT", + "name": "DastSiteProfileUpdateInput", + "description": "Autogenerated input type of DastSiteProfileUpdate", + "fields": null, + "inputFields": [ + { + "name": "fullPath", + "description": "The project the site profile belongs to.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "ID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "id", + "description": "ID of the site profile to be updated.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "DastSiteProfileID", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "profileName", + "description": "The name of the site profile.", + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + }, + "defaultValue": null + }, + { + "name": "targetUrl", + "description": "The URL of the target to be scanned.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + }, + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "defaultValue": null + } + ], + "interfaces": null, + "enumValues": null, + "possibleTypes": null + }, + { + "kind": "OBJECT", + "name": "DastSiteProfileUpdatePayload", + "description": "Autogenerated return type of DastSiteProfileUpdate", + "fields": [ + { + "name": "clientMutationId", + "description": "A unique identifier for the client performing the mutation.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "String", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "errors", + "description": "Errors encountered during execution of the mutation.", + "args": [ + + ], + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "LIST", + "name": null, + "ofType": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "SCALAR", + "name": "String", + "ofType": null + } + } + } + }, + "isDeprecated": false, + "deprecationReason": null + }, + { + "name": "id", + "description": "ID of the site profile.", + "args": [ + + ], + "type": { + "kind": "SCALAR", + "name": "DastSiteProfileID", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + } + ], + "inputFields": null, + "interfaces": [ + + ], + "enumValues": null, + "possibleTypes": null + }, { "kind": "ENUM", "name": "DastSiteProfileValidationStatusEnum", @@ -26800,6 +26940,33 @@ "isDeprecated": false, "deprecationReason": null }, + { + "name": "dastSiteProfileUpdate", + "description": null, + "args": [ + { + "name": "input", + "description": null, + "type": { + "kind": "NON_NULL", + "name": null, + "ofType": { + "kind": "INPUT_OBJECT", + "name": "DastSiteProfileUpdateInput", + "ofType": null + } + }, + "defaultValue": null + } + ], + "type": { + "kind": "OBJECT", + "name": "DastSiteProfileUpdatePayload", + "ofType": null + }, + "isDeprecated": false, + "deprecationReason": null + }, { "name": "deleteAnnotation", "description": null, diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index b92f4c1c61d..386a87b60a2 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -487,6 +487,16 @@ Check permissions for the current user on site profile | --- | ---- | ---------- | | `createOnDemandDastScan` | Boolean! | Indicates the user can perform `create_on_demand_dast_scan` on this resource | +## DastSiteProfileUpdatePayload + +Autogenerated return type of DastSiteProfileUpdate + +| Name | Type | Description | +| --- | ---- | ---------- | +| `clientMutationId` | String | A unique identifier for the client performing the mutation. | +| `errors` | String! => Array | Errors encountered during execution of the mutation. | +| `id` | DastSiteProfileID | ID of the site profile. | + ## DeleteAnnotationPayload Autogenerated return type of DeleteAnnotation diff --git a/doc/ci/pipelines/index.md b/doc/ci/pipelines/index.md index 8b62bf2e9e0..8419b474d54 100644 --- a/doc/ci/pipelines/index.md +++ b/doc/ci/pipelines/index.md @@ -423,7 +423,10 @@ In the following example: #### Custom collapsible sections -You can create collapsible sections in job logs by manually outputting special codes +> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/14664) in GitLab 12.0. + +You can create [collapsible sections in job logs](../pipelines/index.md#expand-and-collapse-job-log-sections) +by manually outputting special codes that GitLab uses to determine what sections to collapse: - Section start marker: `section_start:UNIX_TIMESTAMP:SECTION_NAME\r\e[0K` + `TEXT_OF_SECTION_HEADER` diff --git a/doc/ci/yaml/README.md b/doc/ci/yaml/README.md index 3f8fcbf659b..660e5782cf2 100644 --- a/doc/ci/yaml/README.md +++ b/doc/ci/yaml/README.md @@ -828,6 +828,10 @@ $ tr a-z A-Z << END_TEXT # collapsed multi-line command FOUR FIVE SIX ``` +#### Custom collapsible sections + +See [custom collapsible sections](../pipelines/index.md#custom-collapsible-sections). + ### `stage` `stage` is defined per-job and relies on [`stages`](#stages) which is defined diff --git a/doc/user/clusters/applications.md b/doc/user/clusters/applications.md index 96d05fdc455..74b858a4b1e 100644 --- a/doc/user/clusters/applications.md +++ b/doc/user/clusters/applications.md @@ -946,6 +946,11 @@ management project. Refer to the [Cilium chart](https://github.com/cilium/cilium/tree/master/install/kubernetes/cilium) for the available configuration options. +You can check Cilium's installation status on the cluster management page: + +- [Project-level cluster](../project/clusters/index.md): Navigate to your project's **Operations > Kubernetes** page. +- [Group-level cluster](../group/clusters/index.md): Navigate to your group's **Kubernetes** page. + CAUTION: **Caution:** Installation and removal of the Cilium requires a **manual** [restart](https://docs.cilium.io/en/stable/gettingstarted/k8s-install-gke/#restart-unmanaged-pods) diff --git a/doc/user/project/merge_requests/code_quality.md b/doc/user/project/merge_requests/code_quality.md index a0be8075d06..3c697e22cf5 100644 --- a/doc/user/project/merge_requests/code_quality.md +++ b/doc/user/project/merge_requests/code_quality.md @@ -130,6 +130,67 @@ definition they will be able to execute privileged Docker commands on the Runner host. Having proper access control policies mitigates this attack vector by allowing access only to trusted actors. +### Disabling the code quality job + +The `code_quality` job will not run if the `$CODE_QUALITY_DISABLED` environment +variable is present. Please refer to the environment variables [documentation](../../../ci/variables/README.md) +to learn more about how to define one. + +To disable the `code_quality` job, add `CODE_QUALITY_DISABLED` as a custom environment +variable. This can be done: + +- For the whole project, [in the project settings](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui) + or [CI/CD configuration](../../../ci/variables/README.md#create-a-custom-variable-in-the-ui). +- For a single pipeline run: + + 1. Go to **CI/CD > Pipelines** + 1. Click **Run Pipeline** + 1. Add `CODE_QUALITY_DISABLED` as the variable key, with any value. + +### Using with merge request pipelines + +The configuration provided by the Code Quality template does not let the `code_quality` job +run on [pipelines for merge requests](../../../ci/merge_request_pipelines/index.md). + +If pipelines for merge requests is enabled, the `code_quality:rules` must be redefined. + +The template has these [`rules`](../../../ci/yaml/README.md#rules) for the `code quality` job: + +```yaml +code_quality: + rules: + - if: '$CODE_QUALITY_DISABLED' + when: never + - if: '$CI_COMMIT_TAG || $CI_COMMIT_BRANCH' +``` + +If you are using merge request pipelines, your `rules` (or [`workflow: rules`](../../../ci/yaml/README.md#workflowrules)) +might look like this example: + +```yaml +job1: + rules: + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' # Run job1 in merge request pipelines + - if: '$CI_COMMIT_BRANCH == "master"' # Run job1 in pipelines on the master branch (but not in other branch pipelines) + - if: '$CI_COMMIT_TAG' # Run job1 in pipelines for tags +``` + +To make these work together, you will need to overwrite the code quality `rules` +so that they match your current `rules`. From the example above, it could look like: + +```yaml +include: + - template: Code-Quality.gitlab-ci.yml + +code_quality: + rules: + - if: '$CODE_QUALITY_DISABLED' + when: never + - if: '$CI_PIPELINE_SOURCE == "merge_request_event"' # Run code quality job in merge request pipelines + - if: '$CI_COMMIT_BRANCH == $CI_DEFAULT_BRANCH' # Run code quality job in pipelines on the master branch (but not in other branch pipelines) + - if: '$CI_COMMIT_TAG' # Run code quality job in pipelines for tags +``` + ## Configuring jobs using variables The Code Quality job supports environment variables that users can set to diff --git a/lib/gitlab/sidekiq_logger.rb b/lib/gitlab/sidekiq_logger.rb deleted file mode 100644 index ce82a6f04bb..00000000000 --- a/lib/gitlab/sidekiq_logger.rb +++ /dev/null @@ -1,9 +0,0 @@ -# frozen_string_literal: true - -module Gitlab - class SidekiqLogger < Gitlab::Logger - def self.file_name_noext - 'sidekiq' - end - end -end diff --git a/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb b/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb index e669e73ccb8..1f6ad218927 100644 --- a/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb +++ b/spec/services/clusters/parse_cluster_applications_artifact_service_spec.rb @@ -36,105 +36,89 @@ RSpec.describe Clusters::ParseClusterApplicationsArtifactService do let(:job) { deployment.deployable } let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job) } - context 'when cluster_applications_artifact feature flag is disabled' do - before do - stub_feature_flags(cluster_applications_artifact: false) + it 'calls Gitlab::Kubernetes::Helm::Parsers::ListV2' do + expect(Gitlab::Kubernetes::Helm::Parsers::ListV2).to receive(:new).and_call_original + + result = described_class.new(job, user).execute(artifact) + + expect(result[:status]).to eq(:success) + end + + context 'artifact is not of cluster_applications type' do + let(:artifact) { create(:ci_job_artifact, :archive) } + let(:job) { artifact.job } + + it 'raise ArgumentError' do + expect do + described_class.new(job, user).execute(artifact) + end.to raise_error(ArgumentError, 'Artifact is not cluster_applications file type') end + end - it 'does not call Gitlab::Kubernetes::Helm::Parsers::ListV2 and returns success immediately' do - expect(Gitlab::Kubernetes::Helm::Parsers::ListV2).not_to receive(:new) + context 'artifact exceeds acceptable size' do + it 'returns an error' do + stub_const("#{described_class}::MAX_ACCEPTABLE_ARTIFACT_SIZE", 1.byte) result = described_class.new(job, user).execute(artifact) + expect(result[:status]).to eq(:error) + expect(result[:message]).to eq('Cluster_applications artifact too big. Maximum allowable size: 1 Byte') + end + end + + context 'job has no deployment' do + let(:job) { build(:ci_build) } + + it 'returns an error' do + result = described_class.new(job, user).execute(artifact) + + expect(result[:status]).to eq(:error) + expect(result[:message]).to eq('No deployment found for this job') + end + end + + context 'job has no deployment cluster' do + let(:deployment) { create(:deployment) } + let(:job) { deployment.deployable } + + it 'returns an error' do + result = described_class.new(job, user).execute(artifact) + + expect(result[:status]).to eq(:error) + expect(result[:message]).to eq('No deployment cluster found for this job') + end + end + + context 'blob is empty' do + let(:file) { fixture_file_upload(Rails.root.join("spec/fixtures/helm/helm_list_v2_empty_blob.json.gz")) } + let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job, file: file) } + + it 'returns success' do + result = described_class.new(job, user).execute(artifact) + expect(result[:status]).to eq(:success) end end - context 'when cluster_applications_artifact feature flag is enabled for project' do - before do - stub_feature_flags(cluster_applications_artifact: job.project) - end - - it 'calls Gitlab::Kubernetes::Helm::Parsers::ListV2' do - expect(Gitlab::Kubernetes::Helm::Parsers::ListV2).to receive(:new).and_call_original - - result = described_class.new(job, user).execute(artifact) - - expect(result[:status]).to eq(:success) - end - - context 'artifact is not of cluster_applications type' do - let(:artifact) { create(:ci_job_artifact, :archive) } - let(:job) { artifact.job } - - it 'raise ArgumentError' do - expect do - described_class.new(job, user).execute(artifact) - end.to raise_error(ArgumentError, 'Artifact is not cluster_applications file type') - end - end - - context 'artifact exceeds acceptable size' do - it 'returns an error' do - stub_const("#{described_class}::MAX_ACCEPTABLE_ARTIFACT_SIZE", 1.byte) - - result = described_class.new(job, user).execute(artifact) - - expect(result[:status]).to eq(:error) - expect(result[:message]).to eq('Cluster_applications artifact too big. Maximum allowable size: 1 Byte') - end - end - - context 'job has no deployment' do - let(:job) { build(:ci_build) } + context 'job has deployment cluster' do + context 'current user does not have access to deployment cluster' do + let(:other_user) { create(:user) } it 'returns an error' do - result = described_class.new(job, user).execute(artifact) - - expect(result[:status]).to eq(:error) - expect(result[:message]).to eq('No deployment found for this job') - end - end - - context 'job has no deployment cluster' do - let(:deployment) { create(:deployment) } - let(:job) { deployment.deployable } - - it 'returns an error' do - result = described_class.new(job, user).execute(artifact) + result = described_class.new(job, other_user).execute(artifact) expect(result[:status]).to eq(:error) expect(result[:message]).to eq('No deployment cluster found for this job') end end - context 'blob is empty' do - let(:file) { fixture_file_upload(Rails.root.join("spec/fixtures/helm/helm_list_v2_empty_blob.json.gz")) } - let(:artifact) { create(:ci_job_artifact, :cluster_applications, job: job, file: file) } - - it 'returns success' do - result = described_class.new(job, user).execute(artifact) - - expect(result[:status]).to eq(:success) - end + it 'does not affect unpermitted cluster applications' do + expect(Clusters::ParseClusterApplicationsArtifactService::RELEASE_NAMES).to contain_exactly('cilium') end - context 'job has deployment cluster' do - context 'current user does not have access to deployment cluster' do - let(:other_user) { create(:user) } - - it 'returns an error' do - result = described_class.new(job, other_user).execute(artifact) - - expect(result[:status]).to eq(:error) - expect(result[:message]).to eq('No deployment cluster found for this job') - end - end - - Clusters::ParseClusterApplicationsArtifactService::RELEASE_NAMES.each do |release_name| - context release_name do - include_examples 'parse cluster applications artifact', release_name - end + Clusters::ParseClusterApplicationsArtifactService::RELEASE_NAMES.each do |release_name| + context release_name do + include_examples 'parse cluster applications artifact', release_name end end end