diff options
56 files changed, 436 insertions, 239 deletions
diff --git a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue index 16f3749ecab..5d9513e5b53 100644 --- a/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue +++ b/app/assets/javascripts/alerts_settings/components/alerts_settings_form.vue @@ -16,7 +16,6 @@ import { import * as Sentry from '@sentry/browser'; import { isEmpty, omit } from 'lodash'; import ClipboardButton from '~/vue_shared/components/clipboard_button.vue'; -import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin'; import { integrationTypes, integrationSteps, @@ -60,7 +59,6 @@ export default { directives: { GlModal: GlModalDirective, }, - mixins: [glFeatureFlagsMixin()], inject: { generic: { default: {}, @@ -163,12 +161,7 @@ export default { }; }, showMappingBuilder() { - return ( - this.multiIntegrations && - this.glFeatures.multipleHttpIntegrationsCustomMapping && - this.isHttp && - this.alertFields?.length - ); + return this.multiIntegrations && this.isHttp && this.alertFields?.length; }, hasSamplePayload() { return this.isValidNonEmptyJSON(this.currentIntegration?.payloadExample); @@ -234,12 +227,10 @@ export default { }, submit() { const { name, apiUrl } = this.integrationForm; - const customMappingVariables = this.glFeatures.multipleHttpIntegrationsCustomMapping - ? { - payloadAttributeMappings: this.mapping, - payloadExample: this.samplePayload.json || '{}', - } - : {}; + const customMappingVariables = { + payloadAttributeMappings: this.mapping, + payloadExample: this.samplePayload.json || '{}', + }; const variables = this.selectedIntegration === typeSet.http diff --git a/app/assets/javascripts/alerts_settings/index.js b/app/assets/javascripts/alerts_settings/index.js index 8506b3fda01..321af9fedb6 100644 --- a/app/assets/javascripts/alerts_settings/index.js +++ b/app/assets/javascripts/alerts_settings/index.js @@ -63,10 +63,7 @@ export default (el) => { render(createElement) { return createElement('alert-settings-wrapper', { props: { - alertFields: - gon.features?.multipleHttpIntegrationsCustomMapping && parseBoolean(multiIntegrations) - ? JSON.parse(alertFields) - : null, + alertFields: parseBoolean(multiIntegrations) ? JSON.parse(alertFields) : null, }, }); }, diff --git a/app/assets/javascripts/api/groups_api.js b/app/assets/javascripts/api/groups_api.js index 99802b0437d..d4ba46656e6 100644 --- a/app/assets/javascripts/api/groups_api.js +++ b/app/assets/javascripts/api/groups_api.js @@ -3,7 +3,6 @@ import { buildApiUrl } from './api_utils'; import { DEFAULT_PER_PAGE } from './constants'; const GROUPS_PATH = '/api/:version/groups.json'; -const GROUPS_MEMBERS_SINGLE_PATH = '/api/:version/groups/:group_id/members/:id'; export function getGroups(query, options, callback = () => {}) { const url = buildApiUrl(GROUPS_PATH); @@ -21,11 +20,3 @@ export function getGroups(query, options, callback = () => {}) { return data; }); } - -export function removeMemberFromGroup(groupId, memberId, options) { - const url = buildApiUrl(GROUPS_MEMBERS_SINGLE_PATH) - .replace(':group_id', groupId) - .replace(':id', memberId); - - return axios.delete(url, { params: { ...options } }); -} diff --git a/app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue b/app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue index e43bded408b..d4f51b83e1e 100644 --- a/app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue +++ b/app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue @@ -79,12 +79,12 @@ export default { <form> <div class="gl-display-flex"> <gl-toggle - data-qa-selector="allow_duplicates_checkbox" + data-qa-selector="allow_duplicates_toggle" :value="mavenDuplicatesAllowed" @change="update($options.modelNames.MAVEN_DUPLICATES_ALLOWED, $event)" /> <div class="gl-ml-5"> - <div data-testid="toggle-label"> + <div data-testid="toggle-label" data-qa-selector="allow_duplicates_label"> <gl-sprintf :message="enabledButtonLabel"> <template #bold="{ content }"> <strong>{{ content }}</strong> diff --git a/app/controllers/admin/application_settings_controller.rb b/app/controllers/admin/application_settings_controller.rb index 7f7d38a09c5..7c6a444ce7a 100644 --- a/app/controllers/admin/application_settings_controller.rb +++ b/app/controllers/admin/application_settings_controller.rb @@ -237,7 +237,6 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController [ *::ApplicationSettingsHelper.visible_attributes, *::ApplicationSettingsHelper.external_authorization_service_attributes, - *ApplicationSetting.repository_storages_weighted_attributes, *ApplicationSetting.kroki_formats_attributes.keys.map { |key| "kroki_formats_#{key}".to_sym }, :lets_encrypt_notification_email, :lets_encrypt_terms_of_service_accepted, @@ -248,8 +247,8 @@ class Admin::ApplicationSettingsController < Admin::ApplicationController :default_branch_name, disabled_oauth_sign_in_sources: [], import_sources: [], - repository_storages: [], - restricted_visibility_levels: [] + restricted_visibility_levels: [], + repository_storages_weighted: {} ] end diff --git a/app/controllers/projects/settings/operations_controller.rb b/app/controllers/projects/settings/operations_controller.rb index f8155b77e60..c407b15e29f 100644 --- a/app/controllers/projects/settings/operations_controller.rb +++ b/app/controllers/projects/settings/operations_controller.rb @@ -6,10 +6,6 @@ module Projects before_action :authorize_admin_operations! before_action :authorize_read_prometheus_alerts!, only: [:reset_alerting_token] - before_action do - push_frontend_feature_flag(:multiple_http_integrations_custom_mapping, @project) - end - respond_to :json, only: [:reset_alerting_token, :reset_pagerduty_token] helper_method :error_tracking_setting diff --git a/app/helpers/application_settings_helper.rb b/app/helpers/application_settings_helper.rb index 244238e246d..551e08d1e31 100644 --- a/app/helpers/application_settings_helper.rb +++ b/app/helpers/application_settings_helper.rb @@ -37,13 +37,8 @@ module ApplicationSettingsHelper end def storage_weights - ApplicationSetting.repository_storages_weighted_attributes.map do |attribute| - storage = attribute.to_s.delete_prefix('repository_storages_weighted_') - { - name: attribute, - label: storage, - value: @application_setting.repository_storages_weighted[storage] || 0 - } + Gitlab.config.repositories.storages.keys.each_with_object(OpenStruct.new) do |storage, weights| + weights[storage.to_sym] = @application_setting.repository_storages_weighted[storage] || 0 end end diff --git a/app/helpers/diff_helper.rb b/app/helpers/diff_helper.rb index aa65ba95c2e..10c7b4032cf 100644 --- a/app/helpers/diff_helper.rb +++ b/app/helpers/diff_helper.rb @@ -4,8 +4,8 @@ module DiffHelper def mark_inline_diffs(old_line, new_line) old_diffs, new_diffs = Gitlab::Diff::InlineDiff.new(old_line, new_line).inline_diffs - marked_old_line = Gitlab::Diff::InlineDiffMarker.new(old_line).mark(old_diffs, mode: :deletion) - marked_new_line = Gitlab::Diff::InlineDiffMarker.new(new_line).mark(new_diffs, mode: :addition) + marked_old_line = Gitlab::Diff::InlineDiffMarker.new(old_line).mark(old_diffs) + marked_new_line = Gitlab::Diff::InlineDiffMarker.new(new_line).mark(new_diffs) [marked_old_line, marked_new_line] end diff --git a/app/models/application_setting.rb b/app/models/application_setting.rb index 4959401eb27..44eb2fefb3f 100644 --- a/app/models/application_setting.rb +++ b/app/models/application_setting.rb @@ -25,10 +25,6 @@ class ApplicationSetting < ApplicationRecord alias_attribute :instance_group_id, :instance_administrators_group_id alias_attribute :instance_administrators_group, :instance_group - def self.repository_storages_weighted_attributes - @repository_storages_weighted_atributes ||= Gitlab.config.repositories.storages.keys.map { |k| "repository_storages_weighted_#{k}".to_sym }.freeze - end - def self.kroki_formats_attributes { blockdiag: { @@ -44,7 +40,6 @@ class ApplicationSetting < ApplicationRecord end store_accessor :kroki_formats, *ApplicationSetting.kroki_formats_attributes.keys, prefix: true - store_accessor :repository_storages_weighted, *Gitlab.config.repositories.storages.keys, prefix: true # Include here so it can override methods from # `add_authentication_token_field` @@ -503,6 +498,7 @@ class ApplicationSetting < ApplicationRecord inclusion: { in: [true, false], message: _('must be a boolean value') } before_validation :ensure_uuid! + before_validation :coerce_repository_storages_weighted, if: :repository_storages_weighted_changed? before_save :ensure_runners_registration_token before_save :ensure_health_check_access_token @@ -583,12 +579,6 @@ class ApplicationSetting < ApplicationRecord recaptcha_enabled || login_recaptcha_protection_enabled end - repository_storages_weighted_attributes.each do |attribute| - define_method :"#{attribute}=" do |value| - super(value.to_i) - end - end - kroki_formats_attributes.keys.each do |key| define_method :"kroki_formats_#{key}=" do |value| super(::Gitlab::Utils.to_boolean(value)) diff --git a/app/models/application_setting_implementation.rb b/app/models/application_setting_implementation.rb index 08c16930b13..c067199b52c 100644 --- a/app/models/application_setting_implementation.rb +++ b/app/models/application_setting_implementation.rb @@ -123,7 +123,7 @@ module ApplicationSettingImplementation raw_blob_request_limit: 300, recaptcha_enabled: false, repository_checks_enabled: true, - repository_storages_weighted: { default: 100 }, + repository_storages_weighted: { 'default' => 100 }, repository_storages: ['default'], require_admin_approval_after_user_signup: true, require_two_factor_authentication: false, @@ -298,10 +298,6 @@ module ApplicationSettingImplementation Array(read_attribute(:repository_storages)) end - def repository_storages_weighted - read_attribute(:repository_storages_weighted) - end - def commit_email_hostname super.presence || self.class.default_commit_email_hostname end @@ -333,9 +329,10 @@ module ApplicationSettingImplementation def normalized_repository_storage_weights strong_memoize(:normalized_repository_storage_weights) do - weights_total = repository_storages_weighted.values.reduce(:+) + repository_storages_weights = repository_storages_weighted.slice(*Gitlab.config.repositories.storages.keys) + weights_total = repository_storages_weights.values.reduce(:+) - repository_storages_weighted.transform_values do |w| + repository_storages_weights.transform_values do |w| next w if weights_total == 0 w.to_f / weights_total @@ -473,16 +470,20 @@ module ApplicationSettingImplementation invalid.empty? end + def coerce_repository_storages_weighted + repository_storages_weighted.transform_values!(&:to_i) + end + def check_repository_storages_weighted invalid = repository_storages_weighted.keys - Gitlab.config.repositories.storages.keys - errors.add(:repository_storages_weighted, "can't include: %{invalid_storages}" % { invalid_storages: invalid.join(", ") }) unless + errors.add(:repository_storages_weighted, _("can't include: %{invalid_storages}") % { invalid_storages: invalid.join(", ") }) unless invalid.empty? repository_storages_weighted.each do |key, val| next unless val.present? - errors.add(:"repository_storages_weighted_#{key}", "value must be an integer") unless val.is_a?(Integer) - errors.add(:"repository_storages_weighted_#{key}", "value must be between 0 and 100") unless val.between?(0, 100) + errors.add(:repository_storages_weighted, _("value for '%{storage}' must be an integer") % { storage: key }) unless val.is_a?(Integer) + errors.add(:repository_storages_weighted, _("value for '%{storage}' must be between 0 and 100") % { storage: key }) unless val.between?(0, 100) end end diff --git a/app/serializers/pipeline_serializer.rb b/app/serializers/pipeline_serializer.rb index 807a90d7ca3..85887e64a8b 100644 --- a/app/serializers/pipeline_serializer.rb +++ b/app/serializers/pipeline_serializer.rb @@ -42,7 +42,6 @@ class PipelineSerializer < BaseSerializer [ :cancelable_statuses, :latest_statuses_ordered_by_stage, - :latest_builds_report_results, :retryable_builds, :stages, :latest_statuses, diff --git a/app/services/system_notes/issuables_service.rb b/app/services/system_notes/issuables_service.rb index 69008c702d5..60dd56e772a 100644 --- a/app/services/system_notes/issuables_service.rb +++ b/app/services/system_notes/issuables_service.rb @@ -125,8 +125,8 @@ module SystemNotes old_diffs, new_diffs = Gitlab::Diff::InlineDiff.new(old_title, new_title).inline_diffs - marked_old_title = Gitlab::Diff::InlineDiffMarkdownMarker.new(old_title).mark(old_diffs, mode: :deletion) - marked_new_title = Gitlab::Diff::InlineDiffMarkdownMarker.new(new_title).mark(new_diffs, mode: :addition) + marked_old_title = Gitlab::Diff::InlineDiffMarkdownMarker.new(old_title).mark(old_diffs) + marked_new_title = Gitlab::Diff::InlineDiffMarkdownMarker.new(new_title).mark(new_diffs) body = "changed title from **#{marked_old_title}** to **#{marked_new_title}**" diff --git a/app/validators/json_schemas/security_scan_info.json b/app/validators/json_schemas/security_scan_info.json new file mode 100644 index 00000000000..c8932c1870d --- /dev/null +++ b/app/validators/json_schemas/security_scan_info.json @@ -0,0 +1,28 @@ +{ + "$schema": "http://json-schema.org/draft-07/schema#", + "type": "object", + "title": "Security::Scan#info schema", + "description": "The schema validates the content of the Security::Scan#info attribute", + "additionalProperties": false, + "properties": { + "errors": { + "type": "array", + "items": { + "type": "object", + "additionalProperties": false, + "properties": { + "type": { + "type": "string" + }, + "message": { + "type": "string" + } + }, + "required": [ + "type", + "message" + ] + } + } + } +} diff --git a/app/views/admin/application_settings/_repository_storage.html.haml b/app/views/admin/application_settings/_repository_storage.html.haml index 68dfe35300b..ab1b2bab573 100644 --- a/app/views/admin/application_settings/_repository_storage.html.haml +++ b/app/views/admin/application_settings/_repository_storage.html.haml @@ -18,8 +18,9 @@ = _('Enter weights for storages for new repositories.') = link_to sprite_icon('question-o'), help_page_path('administration/repository_storage_paths') .form-check - - storage_weights.each do |attribute| - = f.text_field attribute[:name], class: 'form-text-input', value: attribute[:value] - = f.label attribute[:label], attribute[:label], class: 'label-bold form-check-label' - %br + = f.fields_for :repository_storages_weighted, storage_weights do |storage_form| + - Gitlab.config.repositories.storages.keys.each do |storage| + = storage_form.text_field storage, class: 'form-text-input' + = storage_form.label storage, storage, class: 'label-bold form-check-label' + %br = f.submit _('Save changes'), class: "gl-button btn btn-confirm" diff --git a/app/views/import/github/new.html.haml b/app/views/import/github/new.html.haml index 7e49cad7902..759dfa1e842 100644 --- a/app/views/import/github/new.html.haml +++ b/app/views/import/github/new.html.haml @@ -30,5 +30,5 @@ = render_if_exists 'import/github/ci_cd_only' .form-actions.d-flex.justify-content-end - = link_to _('Cancel'), new_project_path, class: 'btn' - = submit_tag _('Authenticate'), class: 'btn btn-success ml-2', data: { qa_selector: 'authenticate_button' } + = link_to _('Cancel'), new_project_path, class: 'gl-button btn btn-default' + = submit_tag _('Authenticate'), class: 'gl-button btn btn-confirm ml-2', data: { qa_selector: 'authenticate_button' } diff --git a/changelogs/unreleased/321917_introduce_info_column_for_the_security_scans_table.yml b/changelogs/unreleased/321917_introduce_info_column_for_the_security_scans_table.yml new file mode 100644 index 00000000000..761bd7970c4 --- /dev/null +++ b/changelogs/unreleased/321917_introduce_info_column_for_the_security_scans_table.yml @@ -0,0 +1,5 @@ +--- +title: "Introduce `info` column for the `security_scans` table" +merge_request: 55983 +author: +type: added diff --git a/changelogs/unreleased/fix_repo_storage_weights_admin.yml b/changelogs/unreleased/fix_repo_storage_weights_admin.yml new file mode 100644 index 00000000000..159c2f0903d --- /dev/null +++ b/changelogs/unreleased/fix_repo_storage_weights_admin.yml @@ -0,0 +1,5 @@ +--- +title: Allow saving repository weights after a storage has been removed +merge_request: 55689 +author: +type: fixed diff --git a/changelogs/unreleased/gl-button-gh-import.yml b/changelogs/unreleased/gl-button-gh-import.yml new file mode 100644 index 00000000000..c70acaaf8a9 --- /dev/null +++ b/changelogs/unreleased/gl-button-gh-import.yml @@ -0,0 +1,5 @@ +--- +title: Apply new GitLab UI for buttons on GitHub Import page +merge_request: 56096 +author: Yogi (@yo) +type: changed diff --git a/changelogs/unreleased/qmnguyen0711-remove-latest-report-results-preloading.yml b/changelogs/unreleased/qmnguyen0711-remove-latest-report-results-preloading.yml new file mode 100644 index 00000000000..19e5b039db2 --- /dev/null +++ b/changelogs/unreleased/qmnguyen0711-remove-latest-report-results-preloading.yml @@ -0,0 +1,5 @@ +--- +title: Remove latest_builds_report_results preloading in pipeline serializer +merge_request: 56181 +author: +type: performance diff --git a/config/feature_flags/development/multiple_http_integrations_custom_mapping.yml b/config/feature_flags/development/introduce_marker_ranges.yml index 6c04d08369f..de59cf0e906 100644 --- a/config/feature_flags/development/multiple_http_integrations_custom_mapping.yml +++ b/config/feature_flags/development/introduce_marker_ranges.yml @@ -1,8 +1,8 @@ --- -name: multiple_http_integrations_custom_mapping -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46437 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/273573 -milestone: '13.6' +name: introduce_marker_ranges +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55669 +rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/324068 +milestone: '13.10' type: development -group: group::monitor +group: group::source code default_enabled: false diff --git a/db/migrate/20210308125742_add_info_column_into_security_scans_table.rb b/db/migrate/20210308125742_add_info_column_into_security_scans_table.rb new file mode 100644 index 00000000000..d701fa98259 --- /dev/null +++ b/db/migrate/20210308125742_add_info_column_into_security_scans_table.rb @@ -0,0 +1,9 @@ +# frozen_string_literal: true + +class AddInfoColumnIntoSecurityScansTable < ActiveRecord::Migration[6.0] + DOWNTIME = false + + def change + add_column :security_scans, :info, :jsonb, null: false, default: {} + end +end diff --git a/db/schema_migrations/20210308125742 b/db/schema_migrations/20210308125742 new file mode 100644 index 00000000000..9090fa4dc5e --- /dev/null +++ b/db/schema_migrations/20210308125742 @@ -0,0 +1 @@ +a81f3555d0e1159569687d4967edcd2b5706cdafd5defb8dc725e295eb969861
\ No newline at end of file diff --git a/db/structure.sql b/db/structure.sql index a7e3a82899b..585bfda7350 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -17244,7 +17244,8 @@ CREATE TABLE security_scans ( created_at timestamp with time zone NOT NULL, updated_at timestamp with time zone NOT NULL, build_id bigint NOT NULL, - scan_type smallint NOT NULL + scan_type smallint NOT NULL, + info jsonb DEFAULT '{}'::jsonb NOT NULL ); CREATE SEQUENCE security_scans_id_seq diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md index f08285e74cd..2f6b6a2f629 100644 --- a/doc/administration/packages/container_registry.md +++ b/doc/administration/packages/container_registry.md @@ -71,7 +71,7 @@ Where: | `enabled` | `true` or `false`. Enables the Registry in GitLab. By default this is `false`. | | `host` | The host URL under which the Registry runs and users can use. | | `port` | The port the external Registry domain listens on. | -| `api_url` | The internal API URL under which the Registry is exposed. It defaults to `http://localhost:5000`. | +| `api_url` | The internal API URL under which the Registry is exposed. It defaults to `http://localhost:5000`. Do not change this unless you are setting up an [external Docker registry](#use-an-external-container-registry-with-gitlab-as-an-auth-endpoint). | | `key` | The private key location that is a pair of Registry's `rootcertbundle`. Read the [token auth configuration documentation](https://docs.docker.com/registry/configuration/#token). | | `path` | This should be the same directory like specified in Registry's `rootdirectory`. Read the [storage configuration documentation](https://docs.docker.com/registry/configuration/#storage). This path needs to be readable by the GitLab user, the web-server user and the Registry user. Read more in [#configure-storage-for-the-container-registry](#configure-storage-for-the-container-registry). | | `issuer` | This should be the same value as configured in Registry's `issuer`. Read the [token auth configuration documentation](https://docs.docker.com/registry/configuration/#token). | @@ -630,18 +630,18 @@ You can use GitLab as an auth endpoint with an external container registry. ```ruby gitlab_rails['registry_enabled'] = true - gitlab_rails['registry_api_url'] = "http://localhost:5000" + gitlab_rails['registry_api_url'] = "https://<external_registry_host>:5000" gitlab_rails['registry_issuer'] = "gitlab-issuer" ``` - `gitlab_rails['registry_enabled'] = true` is needed to enable GitLab - Container Registry features and authentication endpoint. The GitLab bundled - Container Registry service does not start, even with this enabled. - - `gitlab_rails['registry_api_url'] = "http://localhost:5000"` can - carry a different hostname and port depending on where the external registry - is hosted. It must also specify `https` if the external registry is - configured to use TLS. + - `gitlab_rails['registry_enabled'] = true` is needed to enable GitLab + Container Registry features and authentication endpoint. The GitLab bundled + Container Registry service does not start, even with this enabled. + - `gitlab_rails['registry_api_url'] = "http://<external_registry_host>:5000"` + must be changed to match the host where Registry is installed. + It must also specify `https` if the external registry is + configured to use TLS. Read more on the + [Docker registry documentation](https://docs.docker.com/registry/deploying/). 1. A certificate-key pair is required for GitLab and the external container registry to communicate securely. You need to create a certificate-key @@ -688,12 +688,14 @@ You can use GitLab as an auth endpoint with an external container registry. enabled: true host: "registry.gitlab.example.com" port: "5005" - api_url: "http://localhost:5000" - path: /var/opt/gitlab/gitlab-rails/shared/registry - key: /var/opt/gitlab/gitlab-rails/certificate.key + api_url: "https://<external_registry_host>:5000" + path: /var/lib/registry + key: /path/to/keyfile issuer: gitlab-issuer ``` + [Read more](#enable-the-container-registry) about what these parameters mean. + 1. Save the file and [restart GitLab](../restart_gitlab.md#installations-from-source) for the changes to take effect. ## Configure Container Registry notifications diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 1a0db78846e..df5d082df77 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -5190,6 +5190,7 @@ All possible ways to specify the API surface for an API fuzzing scan. | ----- | ----------- | | `HAR` | The API surface is specified by a HAR file. | | `OPENAPI` | The API surface is specified by a OPENAPI file. | +| `POSTMAN` | The API surface is specified by a POSTMAN file. | ### `AvailabilityEnum` diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md index 80756e31673..9af339b20c6 100644 --- a/doc/user/clusters/agent/index.md +++ b/doc/user/clusters/agent/index.md @@ -68,7 +68,7 @@ For more details, please refer to our [full architecture documentation](https:// The setup process involves a few steps to enable GitOps deployments: -1. [Install the Agent server](#install-the-kubernetes-agent-server). +1. [Install the Agent server](#install-the-kubernetes-agent-server) for your GitLab instance. 1. [Define a configuration repository](#define-a-configuration-repository). 1. [Create an Agent record in GitLab](#create-an-agent-record-in-gitlab). 1. [Generate and copy a Secret token used to connect to the Agent](#create-the-kubernetes-secret). @@ -91,14 +91,19 @@ Upgrade your agent installations together with GitLab upgrades. To decide which The available `agentk` and `kas` versions can be found in [the container registry](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/container_registry/). -### Install the Kubernetes Agent Server +### Install the Kubernetes Agent Server **(FREE SELF)** -The GitLab Kubernetes Agent Server (KAS) can be deployed using [Omnibus GitLab](https://docs.gitlab.com/omnibus/) or the -[GitLab chart](https://gitlab.com/gitlab-org/charts/gitlab). If you don't already have -GitLab installed, please refer to our [installation documentation](../../../install/index.md). +[Introduced](https://gitlab.com/groups/gitlab-org/-/epics/3834) in GitLab 13.10, +the GitLab Kubernetes Agent Server (KAS) is available on GitLab.com under `wss://kas.gitlab.com`. +If you are a GitLab.com user, skip this step and directly +[set up the configuration repository](#define-a-configuration-repository) +for your agent. -NOTE: -GitLab plans to include the KAS on [GitLab.com](https://gitlab.com/groups/gitlab-org/-/epics/3834). +The GitLab Kubernetes Agent Server (KAS) can be deployed using [Omnibus +GitLab](https://docs.gitlab.com/omnibus/) or the [GitLab +chart](https://gitlab.com/gitlab-org/charts/gitlab). If you don't already have +GitLab installed, please refer to our [installation +documentation](https://docs.gitlab.com/ee/install/README.html). #### Install with Omnibus @@ -230,6 +235,9 @@ the Agent in subsequent steps. You can create an Agent record either: Next, install the in-cluster component of the Agent. +NOTE: +For GitLab.com users, the KAS is available at `wss://kas.gitlab.com`. + #### One-liner installation Replace the value of `agent-token` below with the token received from the previous step. Also, replace `kas-address` with the configured access of the Kubernetes Agent Server: diff --git a/lib/api/helpers/projects_helpers.rb b/lib/api/helpers/projects_helpers.rb index a733f4aa548..cf2bcace33b 100644 --- a/lib/api/helpers/projects_helpers.rb +++ b/lib/api/helpers/projects_helpers.rb @@ -91,8 +91,6 @@ module API end params :optional_update_params_ee do - optional :issues_template, type: String, desc: 'Default description for Issues' - optional :merge_requests_template, type: String, desc: 'Default description for Merge Requests' end params :optional_update_params do @@ -130,10 +128,8 @@ module API :emails_disabled, :forking_access_level, :issues_access_level, - :issues_template, :lfs_enabled, :merge_requests_access_level, - :merge_requests_template, :merge_method, :name, :only_allow_merge_if_all_discussions_are_resolved, diff --git a/lib/banzai/filter/autolink_filter.rb b/lib/banzai/filter/autolink_filter.rb index 0aa1ee8f604..d569711431c 100644 --- a/lib/banzai/filter/autolink_filter.rb +++ b/lib/banzai/filter/autolink_filter.rb @@ -120,7 +120,7 @@ module Banzai end def autolink_filter(text) - Gitlab::StringRegexMarker.new(CGI.unescapeHTML(text), text.html_safe).mark(LINK_PATTERN) do |link, left:, right:| + Gitlab::StringRegexMarker.new(CGI.unescapeHTML(text), text.html_safe).mark(LINK_PATTERN) do |link, left:, right:, mode:| autolink_match(link).html_safe end end diff --git a/lib/banzai/filter/spaced_link_filter.rb b/lib/banzai/filter/spaced_link_filter.rb index 101b55a49e4..f52ffe117d9 100644 --- a/lib/banzai/filter/spaced_link_filter.rb +++ b/lib/banzai/filter/spaced_link_filter.rb @@ -76,7 +76,7 @@ module Banzai end def spaced_link_filter(text) - Gitlab::StringRegexMarker.new(CGI.unescapeHTML(text), text.html_safe).mark(LINK_OR_IMAGE_PATTERN) do |link, left:, right:| + Gitlab::StringRegexMarker.new(CGI.unescapeHTML(text), text.html_safe).mark(LINK_OR_IMAGE_PATTERN) do |link, left:, right:, mode:| spaced_link_match(link).html_safe end end diff --git a/lib/gitlab/dependency_linker/base_linker.rb b/lib/gitlab/dependency_linker/base_linker.rb index d735fb55652..36a840372c5 100644 --- a/lib/gitlab/dependency_linker/base_linker.rb +++ b/lib/gitlab/dependency_linker/base_linker.rb @@ -80,7 +80,7 @@ module Gitlab highlighted_lines.map!.with_index do |rich_line, i| marker = StringRegexMarker.new((plain_lines[i].chomp! || plain_lines[i]), rich_line.html_safe) - marker.mark(regex, group: :name) do |text, left:, right:| + marker.mark(regex, group: :name) do |text, left:, right:, mode:| url = yield(text) url ? link_tag(text, url) : text end diff --git a/lib/gitlab/dependency_linker/go_mod_linker.rb b/lib/gitlab/dependency_linker/go_mod_linker.rb index 4d6fe366333..fae4ee23383 100644 --- a/lib/gitlab/dependency_linker/go_mod_linker.rb +++ b/lib/gitlab/dependency_linker/go_mod_linker.rb @@ -22,7 +22,7 @@ module Gitlab i, j = match.offset(:name) marker = StringRangeMarker.new(plain_line, rich_line.html_safe) - marker.mark([i..(j - 1)]) do |text, left:, right:| + marker.mark([i..(j - 1)]) do |text, left:, right:, mode:| url = package_url(text, match[:version]) url ? link_tag(text, url) : text end diff --git a/lib/gitlab/dependency_linker/go_sum_linker.rb b/lib/gitlab/dependency_linker/go_sum_linker.rb index 20dc82ede9f..44826332f66 100644 --- a/lib/gitlab/dependency_linker/go_sum_linker.rb +++ b/lib/gitlab/dependency_linker/go_sum_linker.rb @@ -21,7 +21,7 @@ module Gitlab i2, j2 = match.offset(:checksum) marker = StringRangeMarker.new(plain_line, rich_line.html_safe) - marker.mark([i0..(j0 - 1), i2..(j2 - 1)]) do |text, left:, right:| + marker.mark([i0..(j0 - 1), i2..(j2 - 1)]) do |text, left:, right:, mode:| if left url = package_url(text, match[:version]) url ? link_tag(text, url) : text diff --git a/lib/gitlab/diff/char_diff.rb b/lib/gitlab/diff/char_diff.rb index c8bb39e9f5d..1b3af8f75ca 100644 --- a/lib/gitlab/diff/char_diff.rb +++ b/lib/gitlab/diff/char_diff.rb @@ -32,12 +32,12 @@ module Gitlab end if action == :delete - old_diffs << (old_pointer..(old_pointer + content_size - 1)) + old_diffs << MarkerRange.new(old_pointer, old_pointer + content_size - 1, mode: MarkerRange::DELETION) old_pointer += content_size end if action == :insert - new_diffs << (new_pointer..(new_pointer + content_size - 1)) + new_diffs << MarkerRange.new(new_pointer, new_pointer + content_size - 1, mode: MarkerRange::ADDITION) new_pointer += content_size end end diff --git a/lib/gitlab/diff/highlight.rb b/lib/gitlab/diff/highlight.rb index a5259079345..baa46e7e306 100644 --- a/lib/gitlab/diff/highlight.rb +++ b/lib/gitlab/diff/highlight.rb @@ -3,12 +3,13 @@ module Gitlab module Diff class Highlight - attr_reader :diff_file, :diff_lines, :raw_lines, :repository + attr_reader :diff_file, :diff_lines, :raw_lines, :repository, :project delegate :old_path, :new_path, :old_sha, :new_sha, to: :diff_file, prefix: :diff def initialize(diff_lines, repository: nil) @repository = repository + @project = repository&.project if diff_lines.is_a?(Gitlab::Diff::File) @diff_file = diff_lines @@ -30,6 +31,12 @@ module Gitlab if line_inline_diffs = inline_diffs[i] begin + # MarkerRange objects are converted to Ranges to keep the previous behavior + # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/324068 + if Feature.disabled?(:introduce_marker_ranges, project, default_enabled: :yaml) + line_inline_diffs = line_inline_diffs.map { |marker_range| marker_range.to_range } + end + rich_line = InlineDiffMarker.new(diff_line.text, rich_line).mark(line_inline_diffs) # This should only happen when the encoding of the diff doesn't # match the blob, which is a bug. But we shouldn't fail to render diff --git a/lib/gitlab/diff/highlight_cache.rb b/lib/gitlab/diff/highlight_cache.rb index e0f1f8a1e58..c5e9bfdc321 100644 --- a/lib/gitlab/diff/highlight_cache.rb +++ b/lib/gitlab/diff/highlight_cache.rb @@ -69,7 +69,12 @@ module Gitlab def key strong_memoize(:redis_key) do - ['highlighted-diff-files', diffable.cache_key, VERSION, diff_options].join(":") + [ + 'highlighted-diff-files', + diffable.cache_key, VERSION, + diff_options, + Feature.enabled?(:introduce_marker_ranges, diffable.project, default_enabled: :yaml) + ].join(":") end end diff --git a/lib/gitlab/diff/inline_diff_markdown_marker.rb b/lib/gitlab/diff/inline_diff_markdown_marker.rb index 3c536c43a9e..d8d596ebce7 100644 --- a/lib/gitlab/diff/inline_diff_markdown_marker.rb +++ b/lib/gitlab/diff/inline_diff_markdown_marker.rb @@ -8,8 +8,8 @@ module Gitlab deletion: "-" }.freeze - def mark(line_inline_diffs, mode: nil) - super(line_inline_diffs) do |text, left:, right:| + def mark(line_inline_diffs) + super(line_inline_diffs) do |text, left:, right:, mode:| symbol = MARKDOWN_SYMBOLS[mode] "{#{symbol}#{text}#{symbol}}" end diff --git a/lib/gitlab/diff/inline_diff_marker.rb b/lib/gitlab/diff/inline_diff_marker.rb index 29dff699ba5..c8cc1c0e649 100644 --- a/lib/gitlab/diff/inline_diff_marker.rb +++ b/lib/gitlab/diff/inline_diff_marker.rb @@ -7,8 +7,8 @@ module Gitlab super(line, rich_line || line) end - def mark(line_inline_diffs, mode: nil) - super(line_inline_diffs) do |text, left:, right:| + def mark(line_inline_diffs) + super(line_inline_diffs) do |text, left:, right:, mode:| %{<span class="#{html_class_names(left, right, mode)}">#{text}</span>}.html_safe end end diff --git a/lib/gitlab/marker_range.rb b/lib/gitlab/marker_range.rb new file mode 100644 index 00000000000..50a59adebdf --- /dev/null +++ b/lib/gitlab/marker_range.rb @@ -0,0 +1,29 @@ +# frozen_string_literal: true + +# It is a Range object extended with `mode` attribute +# MarkerRange not only keeps information about changed characters, but also +# the type of changes +module Gitlab + class MarkerRange < Range + DELETION = :deletion + ADDITION = :addition + + # Converts Range object to MarkerRange class + def self.from_range(range) + return range if range.is_a?(self) + + new(range.begin, range.end, exclude_end: range.exclude_end?) + end + + def initialize(first, last, exclude_end: false, mode: nil) + super(first, last, exclude_end) + @mode = mode + end + + def to_range + Range.new(self.begin, self.end, self.exclude_end?) + end + + attr_reader :mode + end +end diff --git a/lib/gitlab/string_range_marker.rb b/lib/gitlab/string_range_marker.rb index 780fe4c7725..5ddc88edf50 100644 --- a/lib/gitlab/string_range_marker.rb +++ b/lib/gitlab/string_range_marker.rb @@ -15,8 +15,10 @@ module Gitlab end end - def mark(marker_ranges) - return rich_line unless marker_ranges&.any? + def mark(ranges) + return rich_line unless ranges&.any? + + marker_ranges = ranges.map { |range| Gitlab::MarkerRange.from_range(range) } if html_escaped rich_marker_ranges = [] @@ -24,7 +26,7 @@ module Gitlab # Map the inline-diff range based on the raw line to character positions in the rich line rich_positions = position_mapping[range].flatten # Turn the array of character positions into ranges - rich_marker_ranges.concat(collapse_ranges(rich_positions)) + rich_marker_ranges.concat(collapse_ranges(rich_positions, range.mode)) end else rich_marker_ranges = marker_ranges @@ -36,7 +38,7 @@ module Gitlab offset_range = (range.begin + offset)..(range.end + offset) original_text = rich_line[offset_range] - text = yield(original_text, left: i == 0, right: i == rich_marker_ranges.length - 1) + text = yield(original_text, left: i == 0, right: i == rich_marker_ranges.length - 1, mode: range.mode) rich_line[offset_range] = text @@ -90,21 +92,21 @@ module Gitlab end # Takes an array of integers, and returns an array of ranges covering the same integers - def collapse_ranges(positions) + def collapse_ranges(positions, mode) return [] if positions.empty? ranges = [] start = prev = positions[0] - range = start..prev + range = MarkerRange.new(start, prev, mode: mode) positions[1..-1].each do |pos| if pos == prev + 1 - range = start..pos + range = MarkerRange.new(start, pos, mode: mode) prev = pos else ranges << range start = prev = pos - range = start..prev + range = MarkerRange.new(start, prev, mode: mode) end end ranges << range diff --git a/locale/gitlab.pot b/locale/gitlab.pot index 83113ca541e..2a933520c56 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -1483,6 +1483,9 @@ msgstr "" msgid "APIFuzzing|Ex: $TestUsername" msgstr "" +msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz" +msgstr "" + msgid "APIFuzzing|Ex: Project_Test/File/example_fuzz.har" msgstr "" @@ -1507,6 +1510,9 @@ msgstr "" msgid "APIFuzzing|Password for basic authentication" msgstr "" +msgid "APIFuzzing|Postman collections are a group of saved requests you can organize into folders." +msgstr "" + msgid "APIFuzzing|Scan mode" msgstr "" @@ -3224,6 +3230,9 @@ msgstr "" msgid "An application called %{link_to_client} is requesting access to your GitLab account." msgstr "" +msgid "An assignee list displays issues assigned to the selected user" +msgstr "" + msgid "An email notification was recently sent from the admin panel. Please wait %{wait_time_in_words} before attempting to send another message." msgstr "" @@ -9413,6 +9422,9 @@ msgstr "" msgid "DastProfiles|Authentication URL" msgstr "" +msgid "DastProfiles|Branch missing" +msgstr "" + msgid "DastProfiles|Could not create the scanner profile. Please try again." msgstr "" @@ -9584,6 +9596,9 @@ msgstr "" msgid "DastProfiles|Scanner name" msgstr "" +msgid "DastProfiles|Select branch" +msgstr "" + msgid "DastProfiles|Show debug messages" msgstr "" @@ -12629,6 +12644,9 @@ msgstr "" msgid "Failed to install." msgstr "" +msgid "Failed to load assignees." +msgstr "" + msgid "Failed to load assignees. Please try again." msgstr "" @@ -22817,6 +22835,9 @@ msgstr "" msgid "Policy project doesn't exists" msgstr "" +msgid "Postman collection" +msgstr "" + msgid "Pre-defined push rules." msgstr "" @@ -26413,6 +26434,9 @@ msgstr "" msgid "Search an environment spec" msgstr "" +msgid "Search assignees" +msgstr "" + msgid "Search authors" msgstr "" @@ -35100,6 +35124,9 @@ msgstr "" msgid "can't be enabled because signed commits are required for this project" msgstr "" +msgid "can't include: %{invalid_storages}" +msgstr "" + msgid "cannot be a date in the past" msgstr "" @@ -36506,6 +36533,12 @@ msgstr "" msgid "v%{version} published %{timeAgo}" msgstr "" +msgid "value for '%{storage}' must be an integer" +msgstr "" + +msgid "value for '%{storage}' must be between 0 and 100" +msgstr "" + msgid "verify ownership" msgstr "" diff --git a/qa/qa/page/group/settings/package_registries.rb b/qa/qa/page/group/settings/package_registries.rb index 0a606f9a61a..ee5ca849a47 100644 --- a/qa/qa/page/group/settings/package_registries.rb +++ b/qa/qa/page/group/settings/package_registries.rb @@ -12,18 +12,28 @@ module QA end view 'app/assets/javascripts/packages_and_registries/settings/group/components/maven_settings.vue' do - element :allow_duplicates_checkbox + element :allow_duplicates_toggle + element :allow_duplicates_label end def set_allow_duplicates_disabled expand_content :package_registry_settings_content do - uncheck_element :allow_duplicates_checkbox + click_element(:allow_duplicates_toggle) if duplicates_enabled? end end - def has_allow_duplicates_enabled? - expand_content :package_registry_settings_content - !find_element(:allow_duplicates_checkbox).checked? + def set_allow_duplicates_enabled + expand_content :package_registry_settings_content do + click_element(:allow_duplicates_toggle) if duplicates_disabled? + end + end + + def duplicates_enabled? + has_element?(:allow_duplicates_label, text: 'Allow duplicates') + end + + def duplicates_disabled? + has_element?(:allow_duplicates_label, text: 'Do not allow duplicates') end end end diff --git a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb index b6577dfd17a..2f508d00790 100644 --- a/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb +++ b/qa/qa/specs/features/browser_ui/5_package/maven_repository_spec.rb @@ -223,9 +223,7 @@ module QA project.group.visit! Page::Group::Menu.perform(&:go_to_package_settings) - Page::Group::Settings::PackageRegistries.perform do |settings| - expect(settings).to have_allow_duplicates_enabled - end + Page::Group::Settings::PackageRegistries.perform(&:set_allow_duplicates_enabled) end it 'allows users to publish duplicate Maven packages at the group level', testcase: 'https://gitlab.com/gitlab-org/quality/testcases/-/issues/1722' do diff --git a/spec/controllers/admin/application_settings_controller_spec.rb b/spec/controllers/admin/application_settings_controller_spec.rb index 71abf3191b8..2b562e2dd64 100644 --- a/spec/controllers/admin/application_settings_controller_spec.rb +++ b/spec/controllers/admin/application_settings_controller_spec.rb @@ -144,10 +144,10 @@ RSpec.describe Admin::ApplicationSettingsController do end it 'updates repository_storages_weighted setting' do - put :update, params: { application_setting: { repository_storages_weighted_default: 75 } } + put :update, params: { application_setting: { repository_storages_weighted: { default: 75 } } } expect(response).to redirect_to(general_admin_application_settings_path) - expect(ApplicationSetting.current.repository_storages_weighted_default).to eq(75) + expect(ApplicationSetting.current.repository_storages_weighted).to eq('default' => 75) end it 'updates kroki_formats setting' do diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index 52f39f65bd0..249621f5835 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -384,7 +384,20 @@ RSpec.describe 'Admin updates settings' do click_button 'Save changes' end - expect(current_settings.repository_storages_weighted_default).to be 50 + expect(current_settings.repository_storages_weighted).to eq('default' => 50) + end + + it 'still saves when settings are outdated' do + current_settings.update_attribute :repository_storages_weighted, { 'default' => 100, 'outdated' => 100 } + + visit repository_admin_application_settings_path + + page.within('.as-repository-storage') do + fill_in 'application_setting_repository_storages_weighted_default', with: 50 + click_button 'Save changes' + end + + expect(current_settings.repository_storages_weighted).to eq('default' => 50) end end diff --git a/spec/features/alerts_settings/user_views_alerts_settings_spec.rb b/spec/features/alerts_settings/user_views_alerts_settings_spec.rb index e4c39276418..60f2f776595 100644 --- a/spec/features/alerts_settings/user_views_alerts_settings_spec.rb +++ b/spec/features/alerts_settings/user_views_alerts_settings_spec.rb @@ -19,7 +19,6 @@ RSpec.describe 'Alert integrations settings form', :js do describe 'when viewing alert integrations as a maintainer' do context 'with the default page permissions' do before do - stub_feature_flags(multiple_http_integrations_custom_mapping: false) visit project_settings_operations_path(project, anchor: 'js-alert-management-settings') wait_for_requests end diff --git a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js index 68a39b73eff..d2dcff14432 100644 --- a/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js +++ b/spec/frontend/alerts_settings/components/alerts_settings_form_spec.js @@ -12,12 +12,7 @@ describe('AlertsSettingsForm', () => { let wrapper; const mockToastShow = jest.fn(); - const createComponent = ({ - data = {}, - props = {}, - multipleHttpIntegrationsCustomMapping = false, - multiIntegrations = true, - } = {}) => { + const createComponent = ({ data = {}, props = {}, multiIntegrations = true } = {}) => { wrapper = mount(AlertsSettingsForm, { data() { return { ...data }; @@ -29,7 +24,6 @@ describe('AlertsSettingsForm', () => { }, provide: { ...defaultAlertSettingsConfig, - glFeatures: { multipleHttpIntegrationsCustomMapping }, multiIntegrations, }, mocks: { @@ -142,27 +136,8 @@ describe('AlertsSettingsForm', () => { describe('submitting integration form', () => { describe('HTTP', () => { - it('create', async () => { - createComponent(); - - const integrationName = 'Test integration'; - await selectOptionAtIndex(1); - enableIntegration(0, integrationName); - - const submitBtn = findSubmitButton(); - expect(submitBtn.exists()).toBe(true); - expect(submitBtn.text()).toBe('Save integration'); - - findForm().trigger('submit'); - - expect(wrapper.emitted('create-new-integration')[0]).toEqual([ - { type: typeSet.http, variables: { name: integrationName, active: true } }, - ]); - }); - it('create with custom mapping', async () => { createComponent({ - multipleHttpIntegrationsCustomMapping: true, multiIntegrations: true, props: { alertFields }, }); @@ -208,9 +183,19 @@ describe('AlertsSettingsForm', () => { findForm().trigger('submit'); - expect(wrapper.emitted('update-integration')[0]).toEqual([ - { type: typeSet.http, variables: { name: updatedIntegrationName, active: true } }, - ]); + expect(wrapper.emitted('update-integration')[0]).toEqual( + expect.arrayContaining([ + { + type: typeSet.http, + variables: { + name: updatedIntegrationName, + active: true, + payloadAttributeMappings: [], + payloadExample: '{}', + }, + }, + ]), + ); }); }); @@ -301,7 +286,6 @@ describe('AlertsSettingsForm', () => { beforeEach(() => { createComponent({ - multipleHttpIntegrationsCustomMapping: true, data: { currentIntegration: { type: typeSet.http, @@ -408,22 +392,18 @@ describe('AlertsSettingsForm', () => { describe('Mapping builder section', () => { describe.each` - alertFieldsProvided | multiIntegrations | featureFlag | integrationOption | visible - ${true} | ${true} | ${true} | ${1} | ${true} - ${true} | ${true} | ${true} | ${2} | ${false} - ${true} | ${true} | ${false} | ${1} | ${false} - ${true} | ${true} | ${false} | ${2} | ${false} - ${true} | ${false} | ${true} | ${1} | ${false} - ${false} | ${true} | ${true} | ${1} | ${false} - `('', ({ alertFieldsProvided, multiIntegrations, featureFlag, integrationOption, visible }) => { + alertFieldsProvided | multiIntegrations | integrationOption | visible + ${true} | ${true} | ${1} | ${true} + ${true} | ${true} | ${2} | ${false} + ${true} | ${false} | ${1} | ${false} + ${false} | ${true} | ${1} | ${false} + `('', ({ alertFieldsProvided, multiIntegrations, integrationOption, visible }) => { const visibleMsg = visible ? 'is rendered' : 'is not rendered'; - const featureFlagMsg = featureFlag ? 'is enabled' : 'is disabled'; const alertFieldsMsg = alertFieldsProvided ? 'are provided' : 'are not provided'; const integrationType = integrationOption === 1 ? typeSet.http : typeSet.prometheus; - it(`${visibleMsg} when multipleHttpIntegrationsCustomMapping feature flag ${featureFlagMsg} and integration type is ${integrationType} and alert fields ${alertFieldsMsg}`, async () => { + it(`${visibleMsg} when integration type is ${integrationType} and alert fields ${alertFieldsMsg}`, async () => { createComponent({ - multipleHttpIntegrationsCustomMapping: featureFlag, multiIntegrations, props: { alertFields: alertFieldsProvided ? alertFields : [], diff --git a/spec/helpers/application_settings_helper_spec.rb b/spec/helpers/application_settings_helper_spec.rb index 2cd01451e0d..c74ee3ce0ec 100644 --- a/spec/helpers/application_settings_helper_spec.rb +++ b/spec/helpers/application_settings_helper_spec.rb @@ -130,20 +130,15 @@ RSpec.describe ApplicationSettingsHelper do before do helper.instance_variable_set(:@application_setting, application_setting) stub_storage_settings({ 'default': {}, 'storage_1': {}, 'storage_2': {} }) - allow(ApplicationSetting).to receive(:repository_storages_weighted_attributes).and_return( - [:repository_storages_weighted_default, - :repository_storages_weighted_storage_1, - :repository_storages_weighted_storage_2]) - stub_application_setting(repository_storages_weighted: { 'default' => 100, 'storage_1' => 50, 'storage_2' => nil }) end it 'returns storages correctly' do - expect(helper.storage_weights).to eq([ - { name: :repository_storages_weighted_default, label: 'default', value: 100 }, - { name: :repository_storages_weighted_storage_1, label: 'storage_1', value: 50 }, - { name: :repository_storages_weighted_storage_2, label: 'storage_2', value: 0 } - ]) + expect(helper.storage_weights).to eq(OpenStruct.new( + default: 100, + storage_1: 50, + storage_2: 0 + )) end end diff --git a/spec/lib/gitlab/diff/highlight_cache_spec.rb b/spec/lib/gitlab/diff/highlight_cache_spec.rb index efe8535ba3c..d26bc5fc9a8 100644 --- a/spec/lib/gitlab/diff/highlight_cache_spec.rb +++ b/spec/lib/gitlab/diff/highlight_cache_spec.rb @@ -238,7 +238,17 @@ RSpec.describe Gitlab::Diff::HighlightCache, :clean_gitlab_redis_cache do subject { cache.key } it 'returns cache key' do - is_expected.to start_with("highlighted-diff-files:#{cache.diffable.cache_key}:2") + is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:true") + end + + context 'when feature flag is disabled' do + before do + stub_feature_flags(introduce_marker_ranges: false) + end + + it 'returns the original version of the cache' do + is_expected.to eq("highlighted-diff-files:#{cache.diffable.cache_key}:2:#{cache.diff_options}:false") + end end end end diff --git a/spec/lib/gitlab/diff/highlight_spec.rb b/spec/lib/gitlab/diff/highlight_spec.rb index 283437e7fbd..e613674af3a 100644 --- a/spec/lib/gitlab/diff/highlight_spec.rb +++ b/spec/lib/gitlab/diff/highlight_spec.rb @@ -50,11 +50,23 @@ RSpec.describe Gitlab::Diff::Highlight do end it 'highlights and marks added lines' do - code = %Q{+<span id="LC9" class="line" lang="ruby"> <span class="k">raise</span> <span class="no"><span class="idiff left">RuntimeError</span></span><span class="p"><span class="idiff">,</span></span><span class="idiff right"> </span><span class="s2">"System commands must be given as an array of strings"</span></span>\n} + code = %Q{+<span id="LC9" class="line" lang="ruby"> <span class="k">raise</span> <span class="no"><span class="idiff left addition">RuntimeError</span></span><span class="p"><span class="idiff addition">,</span></span><span class="idiff right addition"> </span><span class="s2">"System commands must be given as an array of strings"</span></span>\n} expect(subject[5].rich_text).to eq(code) end + context 'when introduce_marker_ranges is false' do + before do + stub_feature_flags(introduce_marker_ranges: false) + end + + it 'keeps the old bevavior (without mode classes)' do + code = %Q{+<span id="LC9" class="line" lang="ruby"> <span class="k">raise</span> <span class="no"><span class="idiff left">RuntimeError</span></span><span class="p"><span class="idiff">,</span></span><span class="idiff right"> </span><span class="s2">"System commands must be given as an array of strings"</span></span>\n} + + expect(subject[5].rich_text).to eq(code) + end + end + context 'when no diff_refs' do before do allow(diff_file).to receive(:diff_refs).and_return(nil) @@ -93,7 +105,7 @@ RSpec.describe Gitlab::Diff::Highlight do end it 'marks added lines' do - code = %q{+ raise <span class="idiff left right">RuntimeError, </span>"System commands must be given as an array of strings"} + code = %q{+ raise <span class="idiff left right addition">RuntimeError, </span>"System commands must be given as an array of strings"} expect(subject[5].rich_text).to eq(code) expect(subject[5].rich_text).to be_html_safe diff --git a/spec/lib/gitlab/diff/inline_diff_markdown_marker_spec.rb b/spec/lib/gitlab/diff/inline_diff_markdown_marker_spec.rb index 60f7f3a103f..3670074cc21 100644 --- a/spec/lib/gitlab/diff/inline_diff_markdown_marker_spec.rb +++ b/spec/lib/gitlab/diff/inline_diff_markdown_marker_spec.rb @@ -5,8 +5,8 @@ require 'spec_helper' RSpec.describe Gitlab::Diff::InlineDiffMarkdownMarker do describe '#mark' do let(:raw) { "abc 'def'" } - let(:inline_diffs) { [2..5] } - let(:subject) { described_class.new(raw).mark(inline_diffs, mode: :deletion) } + let(:inline_diffs) { [Gitlab::MarkerRange.new(2, 5, mode: Gitlab::MarkerRange::DELETION)] } + let(:subject) { described_class.new(raw).mark(inline_diffs) } it 'does not escape html etities and marks the range' do expect(subject).to eq("ab{-c 'd-}ef'") diff --git a/spec/lib/gitlab/marker_range_spec.rb b/spec/lib/gitlab/marker_range_spec.rb new file mode 100644 index 00000000000..5f73d2a5048 --- /dev/null +++ b/spec/lib/gitlab/marker_range_spec.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +require 'fast_spec_helper' + +RSpec.describe Gitlab::MarkerRange do + subject(:marker_range) { described_class.new(first, last, mode: mode) } + + let(:first) { 1 } + let(:last) { 10 } + let(:mode) { nil } + + it { is_expected.to eq(first..last) } + + it 'behaves like a Range' do + is_expected.to be_kind_of(Range) + end + + describe '#mode' do + subject { marker_range.mode } + + it { is_expected.to be_nil } + + context 'when mode is provided' do + let(:mode) { :deletion } + + it { is_expected.to eq(mode) } + end + end + + describe '#to_range' do + subject { marker_range.to_range } + + it { is_expected.to eq(first..last) } + + context 'when mode is provided' do + let(:mode) { :deletion } + + it 'is omitted during transformation' do + is_expected.not_to respond_to(:mode) + end + end + end + + describe '.from_range' do + subject { described_class.from_range(range) } + + let(:range) { 1..3 } + + it 'converts Range to MarkerRange object' do + is_expected.to be_a(described_class) + end + + it 'keeps correct range' do + is_expected.to eq(range) + end + + context 'when range excludes end' do + let(:range) { 1...3 } + + it 'keeps correct range' do + is_expected.to eq(range) + end + end + + context 'when range is already a MarkerRange' do + let(:range) { marker_range } + + it { is_expected.to be(marker_range) } + end + end +end diff --git a/spec/lib/gitlab/string_range_marker_spec.rb b/spec/lib/gitlab/string_range_marker_spec.rb index 52fab6e3109..6f63c8e2df4 100644 --- a/spec/lib/gitlab/string_range_marker_spec.rb +++ b/spec/lib/gitlab/string_range_marker_spec.rb @@ -8,7 +8,7 @@ RSpec.describe Gitlab::StringRangeMarker do raw = 'abc <def>' inline_diffs = [2..5] - described_class.new(raw, rich).mark(inline_diffs) do |text, left:, right:| + described_class.new(raw, rich).mark(inline_diffs) do |text, left:, right:, mode:| "LEFT#{text}RIGHT".html_safe end end diff --git a/spec/lib/gitlab/string_regex_marker_spec.rb b/spec/lib/gitlab/string_regex_marker_spec.rb index 2dadd222820..a02be83558c 100644 --- a/spec/lib/gitlab/string_regex_marker_spec.rb +++ b/spec/lib/gitlab/string_regex_marker_spec.rb @@ -9,7 +9,7 @@ RSpec.describe Gitlab::StringRegexMarker do let(:rich) { %{<span class="key">"name"</span><span class="punctuation">: </span><span class="value">"AFNetworking"</span>}.html_safe } subject do - described_class.new(raw, rich).mark(/"[^"]+":\s*"(?<name>[^"]+)"/, group: :name) do |text, left:, right:| + described_class.new(raw, rich).mark(/"[^"]+":\s*"(?<name>[^"]+)"/, group: :name) do |text, left:, right:, mode:| %{<a href="#">#{text}</a>}.html_safe end end @@ -25,7 +25,7 @@ RSpec.describe Gitlab::StringRegexMarker do let(:rich) { %{a <b> <c> d}.html_safe } subject do - described_class.new(raw, rich).mark(/<[a-z]>/) do |text, left:, right:| + described_class.new(raw, rich).mark(/<[a-z]>/) do |text, left:, right:, mode:| %{<strong>#{text}</strong>}.html_safe end end diff --git a/spec/models/application_setting_spec.rb b/spec/models/application_setting_spec.rb index 22bdaabce23..808932ce7e4 100644 --- a/spec/models/application_setting_spec.rb +++ b/spec/models/application_setting_spec.rb @@ -105,14 +105,14 @@ RSpec.describe ApplicationSetting do it { is_expected.not_to allow_value(false).for(:hashed_storage_enabled) } - it { is_expected.not_to allow_value(101).for(:repository_storages_weighted_default) } - it { is_expected.to allow_value('90').for(:repository_storages_weighted_default) } - it { is_expected.not_to allow_value(-1).for(:repository_storages_weighted_default) } - it { is_expected.to allow_value(100).for(:repository_storages_weighted_default) } - it { is_expected.to allow_value(0).for(:repository_storages_weighted_default) } - it { is_expected.to allow_value(50).for(:repository_storages_weighted_default) } - it { is_expected.to allow_value(nil).for(:repository_storages_weighted_default) } - it { is_expected.not_to allow_value({ default: 100, shouldntexist: 50 }).for(:repository_storages_weighted) } + it { is_expected.to allow_value('default' => 0).for(:repository_storages_weighted) } + it { is_expected.to allow_value('default' => 50).for(:repository_storages_weighted) } + it { is_expected.to allow_value('default' => 100).for(:repository_storages_weighted) } + it { is_expected.to allow_value('default' => '90').for(:repository_storages_weighted) } + it { is_expected.to allow_value('default' => nil).for(:repository_storages_weighted) } + it { is_expected.not_to allow_value('default' => -1).for(:repository_storages_weighted).with_message("value for 'default' must be between 0 and 100") } + it { is_expected.not_to allow_value('default' => 101).for(:repository_storages_weighted).with_message("value for 'default' must be between 0 and 100") } + it { is_expected.not_to allow_value('default' => 100, shouldntexist: 50).for(:repository_storages_weighted).with_message("can't include: shouldntexist") } it { is_expected.to allow_value(400).for(:notes_create_limit) } it { is_expected.not_to allow_value('two').for(:notes_create_limit) } @@ -984,12 +984,6 @@ RSpec.describe ApplicationSetting do it_behaves_like 'application settings examples' - describe 'repository_storages_weighted_attributes' do - it 'returns the keys for repository_storages_weighted' do - expect(subject.class.repository_storages_weighted_attributes).to eq([:repository_storages_weighted_default]) - end - end - describe 'kroki_format_supported?' do it 'returns true when Excalidraw is enabled' do subject.kroki_formats_excalidraw = true @@ -1033,11 +1027,4 @@ RSpec.describe ApplicationSetting do expect(subject.kroki_formats_excalidraw).to eq(true) end end - - it 'does not allow to set weight for non existing storage' do - setting.repository_storages_weighted = { invalid_storage: 100 } - - expect(setting).not_to be_valid - expect(setting.errors.messages[:repository_storages_weighted]).to match_array(["can't include: invalid_storage"]) - end end diff --git a/spec/support/shared_examples/models/application_setting_shared_examples.rb b/spec/support/shared_examples/models/application_setting_shared_examples.rb index 92fd4363134..60a02d85a1e 100644 --- a/spec/support/shared_examples/models/application_setting_shared_examples.rb +++ b/spec/support/shared_examples/models/application_setting_shared_examples.rb @@ -289,6 +289,7 @@ RSpec.shared_examples 'application settings examples' do describe '#pick_repository_storage' do before do + allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(%w(default backup)) allow(setting).to receive(:repository_storages_weighted).and_return({ 'default' => 20, 'backup' => 80 }) end @@ -304,15 +305,19 @@ RSpec.shared_examples 'application settings examples' do describe '#normalized_repository_storage_weights' do using RSpec::Parameterized::TableSyntax - where(:storages, :normalized) do - { 'default' => 0, 'backup' => 100 } | { 'default' => 0.0, 'backup' => 1.0 } - { 'default' => 100, 'backup' => 100 } | { 'default' => 0.5, 'backup' => 0.5 } - { 'default' => 20, 'backup' => 80 } | { 'default' => 0.2, 'backup' => 0.8 } - { 'default' => 0, 'backup' => 0 } | { 'default' => 0.0, 'backup' => 0.0 } + where(:config_storages, :storages, :normalized) do + %w(default backup) | { 'default' => 0, 'backup' => 100 } | { 'default' => 0.0, 'backup' => 1.0 } + %w(default backup) | { 'default' => 100, 'backup' => 100 } | { 'default' => 0.5, 'backup' => 0.5 } + %w(default backup) | { 'default' => 20, 'backup' => 80 } | { 'default' => 0.2, 'backup' => 0.8 } + %w(default backup) | { 'default' => 0, 'backup' => 0 } | { 'default' => 0.0, 'backup' => 0.0 } + %w(default) | { 'default' => 0, 'backup' => 100 } | { 'default' => 0.0 } + %w(default) | { 'default' => 100, 'backup' => 100 } | { 'default' => 1.0 } + %w(default) | { 'default' => 20, 'backup' => 80 } | { 'default' => 1.0 } end with_them do before do + allow(Gitlab.config.repositories.storages).to receive(:keys).and_return(config_storages) allow(setting).to receive(:repository_storages_weighted).and_return(storages) end diff --git a/spec/views/admin/application_settings/_repository_storage.html.haml_spec.rb b/spec/views/admin/application_settings/_repository_storage.html.haml_spec.rb index 2915fe1964f..dc8f259eb56 100644 --- a/spec/views/admin/application_settings/_repository_storage.html.haml_spec.rb +++ b/spec/views/admin/application_settings/_repository_storage.html.haml_spec.rb @@ -3,34 +3,49 @@ require 'spec_helper' RSpec.describe 'admin/application_settings/_repository_storage.html.haml' do - let(:app_settings) { create(:application_setting) } - let(:repository_storages_weighted_attributes) { [:repository_storages_weighted_default, :repository_storages_weighted_mepmep, :repository_storages_weighted_foobar]} - let(:repository_storages_weighted) do - { - "default" => 100, - "mepmep" => 50 - } - end + let(:app_settings) { build(:application_setting, repository_storages_weighted: repository_storages_weighted) } before do - allow(app_settings).to receive(:repository_storages_weighted).and_return(repository_storages_weighted) - allow(app_settings).to receive(:repository_storages_weighted_mepmep).and_return(100) - allow(app_settings).to receive(:repository_storages_weighted_foobar).and_return(50) + stub_storage_settings({ 'default': {}, 'mepmep': {}, 'foobar': {} }) assign(:application_setting, app_settings) - allow(ApplicationSetting).to receive(:repository_storages_weighted_attributes).and_return(repository_storages_weighted_attributes) end - context 'when multiple storages are available' do + context 'additional storage config' do + let(:repository_storages_weighted) do + { + 'default' => 100, + 'mepmep' => 50 + } + end + it 'lists them all' do render - # lists storages that are saved with weights - repository_storages_weighted.each do |storage_name, storage_weight| + Gitlab.config.repositories.storages.keys.each do |storage_name| expect(rendered).to have_content(storage_name) end - # lists storage not saved with weight expect(rendered).to have_content('foobar') end end + + context 'fewer storage configs' do + let(:repository_storages_weighted) do + { + 'default' => 100, + 'mepmep' => 50, + 'something_old' => 100 + } + end + + it 'lists only configured storages' do + render + + Gitlab.config.repositories.storages.keys.each do |storage_name| + expect(rendered).to have_content(storage_name) + end + + expect(rendered).not_to have_content('something_old') + end + end end |