diff --git a/app/assets/stylesheets/pages/issuable.scss b/app/assets/stylesheets/pages/issuable.scss index 202e65bdeec..9413007e848 100644 --- a/app/assets/stylesheets/pages/issuable.scss +++ b/app/assets/stylesheets/pages/issuable.scss @@ -130,6 +130,7 @@ bottom: var(--review-bar-height, 0px); right: 0; transition: width $sidebar-transition-duration; + background-color: $white; z-index: 200; overflow: hidden; diff --git a/app/graphql/mutations/clusters/agent_tokens/delete.rb b/app/graphql/mutations/clusters/agent_tokens/delete.rb deleted file mode 100644 index 603b6b30910..00000000000 --- a/app/graphql/mutations/clusters/agent_tokens/delete.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -module Mutations - module Clusters - module AgentTokens - class Delete < BaseMutation - graphql_name 'ClusterAgentTokenDelete' - - authorize :admin_cluster - - TokenID = ::Types::GlobalIDType[::Clusters::AgentToken] - - argument :id, TokenID, - required: true, - description: 'Global ID of the cluster agent token that will be deleted.' - - def resolve(id:) - token = authorized_find!(id: id) - token.destroy - - { errors: errors_on_object(token) } - end - - private - - def find_object(id:) - # TODO: remove this line when the compatibility layer is removed - # See: https://gitlab.com/gitlab-org/gitlab/-/issues/257883 - id = TokenID.coerce_isolated_input(id) - GitlabSchema.find_by_gid(id) - end - end - end - end -end diff --git a/app/graphql/types/deprecated_mutations.rb b/app/graphql/types/deprecated_mutations.rb index 70d5fc31cd1..49bad56b6f9 100644 --- a/app/graphql/types/deprecated_mutations.rb +++ b/app/graphql/types/deprecated_mutations.rb @@ -5,8 +5,7 @@ module Types extend ActiveSupport::Concern prepended do - mount_mutation Mutations::Clusters::AgentTokens::Delete, - deprecated: { reason: 'Tokens must be revoked with ClusterAgentTokenRevoke', milestone: '14.7' } + # placeholder for any FOSS mutations to be deprecated end end end diff --git a/app/models/clusters/platforms/kubernetes.rb b/app/models/clusters/platforms/kubernetes.rb index 66bce755598..9d4f0a89403 100644 --- a/app/models/clusters/platforms/kubernetes.rb +++ b/app/models/clusters/platforms/kubernetes.rb @@ -322,7 +322,7 @@ module Clusters class: error.class.name, message: error.message }, - status_code: error.error_code, + status_code: error.try(:error_code), namespace: self.namespace, class_name: self.class.name, event: :kube_connection_error diff --git a/data/whats_new/202204210001_14_10.yml b/data/whats_new/202204210001_14_10.yml new file mode 100644 index 00000000000..a95e209a422 --- /dev/null +++ b/data/whats_new/202204210001_14_10.yml @@ -0,0 +1,46 @@ +- title: "Compliance report individual violation reporting" + body: | + The compliance report now reports every individual merge request violation for the projects within a group. This is a huge improvement over the previous version, which only showed the latest MR that had one or more violations. The new version allows you to see history and patterns of violations over time. + stage: manage + self-managed: true + gitlab-com: true + packages: [Ultimate] + url: 'https://docs.gitlab.com/ee/user/compliance/compliance_report/' + image_url: 'https://about.gitlab.com/images/14_10/manage_compliance_report_individual_violation.png' + published_at: 2022-04-22 + release: 14.10 +- title: "Improved pipeline variables inheritance" + body: | + Previously, it was possible to pass some CI/CD variables to a downstream pipeline through a trigger job, but variables added in manual pipeline runs or by using the API could not be forwarded. + + In this release we've added a new `trigger:forward` keyword to control what things you forward to downstream parent-child pipelines or multi-project pipelines, which provides a flexible way to handle variable inheritance in downstream pipelines. + stage: verify + self-managed: true + gitlab-com: true + packages: [Free, Premium, Ultimate] + url: 'https://docs.gitlab.com/ee/ci/yaml/#triggerforward' + image_url: 'https://about.gitlab.com/images/growth/verify.png' + published_at: 2022-04-22 + release: 14.10 +- title: "Escalating manually created incidents" + body: | + In GitLab 13.10, we [released](https://gitlab.com/gitlab-org/gl-openshift/gitlab-runner-operator/-/issues/6) the GitLab Runner Operator for the Red Hat OpenShift container platform for Kubernetes. That release provided OpenShift users with the automation and management capabilities of the Operator Framework and simplified the ongoing management of runners in an OpenShift Kubernetes cluster. Available starting in 14.10 is a GitLab Runner Operator v1.7.0 that you can use in non-OpenShift Kubernetes clusters. This GitLab Runner Operator is available on [OperatorHub.io](https://operatorhub.io/operator/gitlab-runner-operator). + stage: monitor + self-managed: true + gitlab-com: true + packages: [Premium, Ultimate] + url: 'https://docs.gitlab.com/ee/operations/incident_management/paging.html#escalating-an-incident' + image_url: 'https://about.gitlab.com/images/14_10/manually_escalated_incident.png' + published_at: 2022-04-22 + release: 14.10 +- title: "Expanded view of group runners" + body: | + Group runners are now displayed in an expanded view, where you can more easily administer and manage the runners associated with the namespace. To view the new UI, on the left sidebar, select **CI/CD**. This view includes the number of online, offline, and stale runners associated with the group and subgroups. + stage: verify + self-managed: true + gitlab-com: true + packages: [Free, Premium, Ultimate] + url: 'https://docs.gitlab.com/ee/ci/runners/runners_scope.html#group-runners' + image_url: 'https://about.gitlab.com/images/14_10/group-runners-view-new-3.pn' + published_at: 2022-04-22 + release: 14.10 diff --git a/db/fixtures/development/34_uploads.rb b/db/fixtures/development/34_uploads.rb new file mode 100644 index 00000000000..fc45c51e136 --- /dev/null +++ b/db/fixtures/development/34_uploads.rb @@ -0,0 +1,54 @@ +# frozen_string_literal: true + +# This seeder seeds comments as well, because uploads are not relevant by +# themselves +Gitlab::Seeder.quiet do + upload_seed_total_limit = 50 + upload_seed_individual_limit = upload_seed_total_limit / 10 + + Issue.limit(upload_seed_individual_limit).find_each do |issue| + project = issue.project + + project.team.users.limit(upload_seed_individual_limit).each do |user| + file = CarrierWaveStringFile.new_file( + file_content: "seeded upload file in project #{project.full_path}, issue #{issue.iid}", + filename: 'seeded_upload.txt', + content_type: 'text/plain' + ) + + uploader = UploadService.new(project, file, FileUploader).execute + + note_params = { + noteable_type: 'Issue', + noteable_id: issue.id, + note: "Seeded upload: #{uploader.to_h[:markdown]}", + } + + Notes::CreateService.new(project, user, note_params).execute + print '.' + end + end + + MergeRequest.limit(upload_seed_individual_limit).find_each do |mr| + project = mr.project + + project.team.users.limit(upload_seed_individual_limit).each do |user| + file = CarrierWaveStringFile.new_file( + file_content: "seeded upload file in project #{project.full_path}, MR #{mr.iid}", + filename: 'seeded_upload.txt', + content_type: 'text/plain' + ) + + uploader = UploadService.new(project, file, FileUploader).execute + + note_params = { + noteable_type: 'MergeRequest', + noteable_id: mr.id, + note: "Seeded upload: #{uploader.to_h[:markdown]}", + } + + Notes::CreateService.new(project, user, note_params).execute + print '.' + end + end +end diff --git a/db/migrate/20220406133049_add_delayed_group_deletion_to_application_settings.rb b/db/migrate/20220406133049_add_delayed_group_deletion_to_application_settings.rb new file mode 100644 index 00000000000..16ee7033021 --- /dev/null +++ b/db/migrate/20220406133049_add_delayed_group_deletion_to_application_settings.rb @@ -0,0 +1,11 @@ +# frozen_string_literal: true + +class AddDelayedGroupDeletionToApplicationSettings < Gitlab::Database::Migration[1.0] + def up + add_column :application_settings, :delayed_group_deletion, :boolean, default: true, null: false + end + + def down + remove_column :application_settings, :delayed_group_deletion + end +end diff --git a/db/migrate/20220413054910_backfill_delayed_group_deletion.rb b/db/migrate/20220413054910_backfill_delayed_group_deletion.rb new file mode 100644 index 00000000000..420f200be02 --- /dev/null +++ b/db/migrate/20220413054910_backfill_delayed_group_deletion.rb @@ -0,0 +1,21 @@ +# frozen_string_literal: true + +class BackfillDelayedGroupDeletion < Gitlab::Database::Migration[1.0] + class ApplicationSetting < ActiveRecord::Base + self.table_name = 'application_settings' + end + + def up + ApplicationSetting.reset_column_information + + ApplicationSetting.find_each do |application_setting| + application_setting.update!(delayed_group_deletion: application_setting.deletion_adjourned_period > 0) + end + end + + def down + ApplicationSetting.reset_column_information + + ApplicationSetting.update_all(delayed_group_deletion: true) + end +end diff --git a/db/schema_migrations/20220406133049 b/db/schema_migrations/20220406133049 new file mode 100644 index 00000000000..4c67d7fd780 --- /dev/null +++ b/db/schema_migrations/20220406133049 @@ -0,0 +1 @@ +bfd9afc3245a311f905548c18535a2d4216b3973b505b1e3217037e4c0a39a2e \ No newline at end of file diff --git a/db/schema_migrations/20220413054910 b/db/schema_migrations/20220413054910 new file mode 100644 index 00000000000..6f6c0321d53 --- /dev/null +++ b/db/schema_migrations/20220413054910 @@ -0,0 +1 @@ +5d386a9eb1602afcaf44442c5696e03721a265cf104564258f4adee60b70b0f2 \ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index f5d7e495943..971178bb754 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -11274,6 +11274,7 @@ CREATE TABLE application_settings ( inactive_projects_delete_after_months integer DEFAULT 2 NOT NULL, inactive_projects_min_size_mb integer DEFAULT 0 NOT NULL, inactive_projects_send_warning_email_after_months integer DEFAULT 1 NOT NULL, + delayed_group_deletion boolean DEFAULT true NOT NULL, CONSTRAINT app_settings_container_reg_cleanup_tags_max_list_size_positive CHECK ((container_registry_cleanup_tags_service_max_list_size >= 0)), CONSTRAINT app_settings_dep_proxy_ttl_policies_worker_capacity_positive CHECK ((dependency_proxy_ttl_group_policy_worker_capacity >= 0)), CONSTRAINT app_settings_ext_pipeline_validation_service_url_text_limit CHECK ((char_length(external_pipeline_validation_service_url) <= 255)), diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 5de48e19b31..164d678406d 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -973,28 +973,6 @@ Input type: `ClusterAgentTokenCreateInput` | `secret` | [`String`](#string) | Token secret value. Make sure you save it - you won't be able to access it again. | | `token` | [`ClusterAgentToken`](#clusteragenttoken) | Token created after mutation. | -### `Mutation.clusterAgentTokenDelete` - -WARNING: -**Deprecated** in 14.7. -Tokens must be revoked with ClusterAgentTokenRevoke. - -Input type: `ClusterAgentTokenDeleteInput` - -#### Arguments - -| Name | Type | Description | -| ---- | ---- | ----------- | -| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | -| `id` | [`ClustersAgentTokenID!`](#clustersagenttokenid) | Global ID of the cluster agent token that will be deleted. | - -#### Fields - -| Name | Type | Description | -| ---- | ---- | ----------- | -| `clientMutationId` | [`String`](#string) | A unique identifier for the client performing the mutation. | -| `errors` | [`[String!]!`](#string) | Errors encountered during execution of the mutation. | - ### `Mutation.clusterAgentTokenRevoke` Input type: `ClusterAgentTokenRevokeInput` diff --git a/doc/api/graphql/removed_items.md b/doc/api/graphql/removed_items.md index f70add0de45..7ef89f40e3c 100644 --- a/doc/api/graphql/removed_items.md +++ b/doc/api/graphql/removed_items.md @@ -10,6 +10,16 @@ GraphQL is a versionless API, unlike the REST API. Occasionally, items have to be updated or removed from the GraphQL API. According to our [process for removing items](index.md#deprecation-and-removal-process), here are the items that have been removed. +## GitLab 15.0 + +Fields [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/85382) in GitLab 15.0: + +### GraphQL Mutations + +| Argument name | Mutation | Deprecated in | Use instead | +| -------------------- | -------------------- | ------------- | -------------------------- | +| - | `clusterAgentTokenDelete`| 14.7 | `clusterAgentTokenRevoke` | + ## GitLab 14.0 Fields [removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/63293) in GitLab 14.0: diff --git a/doc/api/settings.md b/doc/api/settings.md index cc9df7917e2..a4e680151b4 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -103,7 +103,7 @@ Example response: ``` Users on [GitLab Premium or Ultimate](https://about.gitlab.com/pricing/) may also see -the `file_template_project_id`, `delayed_project_deletion`, `deletion_adjourned_period`, or the `geo_node_allowed_ips` parameters: +the `file_template_project_id`, `delayed_project_deletion`, `delayed_group_deletion`, `deletion_adjourned_period`, or the `geo_node_allowed_ips` parameters: ```json { @@ -112,6 +112,7 @@ the `file_template_project_id`, `delayed_project_deletion`, `deletion_adjourned_ "file_template_project_id": 1, "geo_node_allowed_ips": "0.0.0.0/0, ::/0", "delayed_project_deletion": false, + "delayed_group_deletion": false, "deletion_adjourned_period": 7, ... } @@ -216,7 +217,8 @@ these parameters: - `file_template_project_id` - `geo_node_allowed_ips` - `geo_status_timeout` -- `delayed_project_delection` +- `delayed_project_deletion` +- `delayed_group_deletion` - `deletion_adjourned_period` Example responses: **(PREMIUM SELF)** @@ -274,8 +276,9 @@ listed in the descriptions of the relevant settings. | `default_projects_limit` | integer | no | Project limit per user. Default is `100000`. | | `default_snippet_visibility` | string | no | What visibility level new snippets receive. Can take `private`, `internal` and `public` as a parameter. Default is `private`. | | `delayed_project_deletion` **(PREMIUM SELF)** | boolean | no | Enable delayed project deletion by default in new groups. Default is `false`. | +| `delayed_group_deletion` **(PREMIUM SELF)** | boolean | no | Enable delayed group deletion by default in new groups. Requires both `delayed_group_deletion` to be true and `deletion_adjourned_period` to be greater than 0. Default is `true`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/352959) in GitLab 15.0. | | `delete_inactive_projects` | boolean | no | Enable inactive project deletion feature. Default is `false`. [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/84519) in GitLab 14.10. | -| `deletion_adjourned_period` **(PREMIUM SELF)** | integer | no | The number of days to wait before deleting a project or group that is marked for deletion. Value must be between 0 and 90. +| `deletion_adjourned_period` **(PREMIUM SELF)** | integer | no | The number of days to wait before deleting a project or group that is marked for deletion. Value must be between 0 and 90. On every update, a hook on `deletion_adjourned_period` sets the value of `delayed_group_deletion` to `true` if `deletion_adjourned_period` is greater than 0 and `false` if `deletion_adjourned_period` is 0. | `diff_max_patch_bytes` | integer | no | Maximum [diff patch size](../user/admin_area/diff_limits.md), in bytes. | | `diff_max_files` | integer | no | Maximum [files in a diff](../user/admin_area/diff_limits.md). | | `diff_max_lines` | integer | no | Maximum [lines in a diff](../user/admin_area/diff_limits.md). | diff --git a/doc/user/clusters/agent/repository.md b/doc/user/clusters/agent/repository.md index 2087c804e26..f889dee41a6 100644 --- a/doc/user/clusters/agent/repository.md +++ b/doc/user/clusters/agent/repository.md @@ -128,7 +128,7 @@ To remove an agent from the UI: } ``` -1. Remove an agent record with GraphQL by deleting the `clusterAgentToken`. +1. Remove an agent record with GraphQL by deleting the `clusterAgent`. ```graphql mutation deleteAgent { @@ -136,12 +136,6 @@ To remove an agent from the UI: errors } } - - mutation deleteToken { - clusterAgentTokenDelete(input: { id: "" }) { - errors - } - } ``` 1. Verify whether the removal occurred successfully. If the output in the Pod logs includes `unauthenticated`, it means that the agent was successfully removed: diff --git a/spec/graphql/mutations/clusters/agent_tokens/delete_spec.rb b/spec/graphql/mutations/clusters/agent_tokens/delete_spec.rb deleted file mode 100644 index 5cdbc0f6d72..00000000000 --- a/spec/graphql/mutations/clusters/agent_tokens/delete_spec.rb +++ /dev/null @@ -1,52 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Mutations::Clusters::AgentTokens::Delete do - let(:token) { create(:cluster_agent_token) } - let(:user) { create(:user) } - - let(:mutation) do - described_class.new( - object: double, - context: { current_user: user }, - field: double - ) - end - - it { expect(described_class.graphql_name).to eq('ClusterAgentTokenDelete') } - it { expect(described_class).to require_graphql_authorizations(:admin_cluster) } - - describe '#resolve' do - let(:global_id) { token.to_global_id } - - subject { mutation.resolve(id: global_id) } - - context 'without user permissions' do - it 'fails to delete the cluster agent', :aggregate_failures do - expect { subject }.to raise_error(Gitlab::Graphql::Errors::ResourceNotAvailable) - expect { token.reload }.not_to raise_error - end - end - - context 'with user permissions' do - before do - token.agent.project.add_maintainer(user) - end - - it 'deletes a cluster agent', :aggregate_failures do - expect { subject }.to change { ::Clusters::AgentToken.count }.by(-1) - expect { token.reload }.to raise_error(ActiveRecord::RecordNotFound) - end - end - - context 'with invalid params' do - let(:global_id) { token.id } - - it 'raises an error if the cluster agent id is invalid', :aggregate_failures do - expect { subject }.to raise_error(::GraphQL::CoercionError) - expect { token.reload }.not_to raise_error - end - end - end -end diff --git a/spec/graphql/types/mutation_type_spec.rb b/spec/graphql/types/mutation_type_spec.rb index 1fc46f2d511..95d835c88cf 100644 --- a/spec/graphql/types/mutation_type_spec.rb +++ b/spec/graphql/types/mutation_type_spec.rb @@ -7,14 +7,6 @@ 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/models/clusters/platforms/kubernetes_spec.rb b/spec/models/clusters/platforms/kubernetes_spec.rb index 236bb2f0472..8c0f07047e4 100644 --- a/spec/models/clusters/platforms/kubernetes_spec.rb +++ b/spec/models/clusters/platforms/kubernetes_spec.rb @@ -450,6 +450,42 @@ RSpec.describe Clusters::Platforms::Kubernetes do it { is_expected.to be_nil } end + context 'when there are ignored K8s connections errors' do + described_class::IGNORED_CONNECTION_EXCEPTIONS.each do |exception| + context "#{exception}" do + before do + exception_args = ['arg1'] + exception_args.push('arg2', 'arg3') if exception.name == 'Kubeclient::HttpError' + exception_instance = exception.new(*exception_args) + + allow_next_instance_of(Gitlab::Kubernetes::KubeClient) do |kube_client| + allow(kube_client).to receive(:get_pods).with(namespace: namespace).and_raise(exception_instance) + allow(kube_client).to receive(:get_deployments).with(namespace: namespace).and_raise(exception_instance) + allow(kube_client).to receive(:get_ingresses).with(namespace: namespace).and_raise(exception_instance) + end + end + + it 'does not raise error' do + expect { subject }.not_to raise_error + end + + it 'returns empty array for the K8s component keys' do + expect(subject).to include({ pods: [], deployments: [], ingresses: [] }) + end + + it 'logs the error' do + expect_next_instance_of(Gitlab::Kubernetes::Logger) do |logger| + expect(logger).to receive(:error) + .with(hash_including(event: :kube_connection_error)) + .and_call_original + end + + subject + end + end + end + end + context 'when kubernetes responds with 500s' do before do stub_kubeclient_pods(namespace, status: 500) @@ -457,23 +493,9 @@ RSpec.describe Clusters::Platforms::Kubernetes do stub_kubeclient_ingresses(namespace, status: 500) end - it 'does not raise error' do + it 'does not raise kubeclient http error' do expect { subject }.not_to raise_error(Kubeclient::HttpError) end - - it 'logs the error' do - expect_next_instance_of(Gitlab::Kubernetes::Logger) do |logger| - expect(logger).to receive(:error) - .with(hash_including(event: :kube_connection_error)) - .and_call_original - end - - subject - end - - it 'returns empty array for the k8s component keys' do - expect(subject).to include({ pods: [], deployments: [], ingresses: [] }) - end end context 'when kubernetes responds with 404s' do