diff --git a/.rubocop.yml b/.rubocop.yml index e4b46121df6..4c7abe0dc89 100644 --- a/.rubocop.yml +++ b/.rubocop.yml @@ -13,8 +13,6 @@ inherit_from: <% end %> - '.rubocop_todo.yml' <% end %> - <%# See https://gitlab.com/gitlab-org/gitlab/-/issues/321982#rubymine-note for context on why namespaced_class has special handling here %> - - ./.rubocop_todo/gitlab/namespaced_class.yml - ./rubocop/rubocop-migrations.yml - ./rubocop/rubocop-usage-data.yml - ./rubocop/rubocop-code_reuse.yml diff --git a/app/assets/javascripts/notes/constants.js b/app/assets/javascripts/notes/constants.js index b8575016762..3317f4e2383 100644 --- a/app/assets/javascripts/notes/constants.js +++ b/app/assets/javascripts/notes/constants.js @@ -10,8 +10,8 @@ export const OPENED = 'opened'; export const REOPENED = 'reopened'; export const CLOSED = 'closed'; export const MERGED = 'merged'; -export const ISSUE_NOTEABLE_TYPE = 'issue'; -export const EPIC_NOTEABLE_TYPE = 'epic'; +export const ISSUE_NOTEABLE_TYPE = 'Issue'; +export const EPIC_NOTEABLE_TYPE = 'Epic'; export const MERGE_REQUEST_NOTEABLE_TYPE = 'MergeRequest'; export const UNRESOLVE_NOTE_METHOD_NAME = 'delete'; export const RESOLVE_NOTE_METHOD_NAME = 'post'; diff --git a/app/assets/javascripts/notes/stores/actions.js b/app/assets/javascripts/notes/stores/actions.js index 57bb9e295f9..82417c9134b 100644 --- a/app/assets/javascripts/notes/stores/actions.js +++ b/app/assets/javascripts/notes/stores/actions.js @@ -83,14 +83,17 @@ export const setExpandDiscussions = ({ commit }, { discussionIds, expanded }) => commit(types.SET_EXPAND_DISCUSSIONS, { discussionIds, expanded }); }; -export const fetchDiscussions = ({ commit, dispatch }, { path, filter, persistFilter }) => { +export const fetchDiscussions = ( + { commit, dispatch, getters }, + { path, filter, persistFilter }, +) => { const config = filter !== undefined ? { params: { notes_filter: filter, persist_filter: persistFilter } } : null; if ( - window.gon?.features?.paginatedIssueDiscussions || + getters.noteableType === constants.ISSUE_NOTEABLE_TYPE || window.gon?.features?.paginatedMrDiscussions ) { return dispatch('fetchDiscussionsBatch', { path, config, perPage: 20 }); @@ -114,7 +117,7 @@ export const fetchDiscussionsBatch = ({ commit, dispatch }, { path, config, curs return axios.get(path, { params }).then(({ data, headers }) => { commit(types.ADD_OR_UPDATE_DISCUSSIONS, data); - if (headers['x-next-page-cursor']) { + if (headers && headers['x-next-page-cursor']) { const nextConfig = { ...config }; if (config?.params?.persist_filter) { diff --git a/app/controllers/concerns/issuable_actions.rb b/app/controllers/concerns/issuable_actions.rb index 07850acd23d..a5e49b1b16a 100644 --- a/app/controllers/concerns/issuable_actions.rb +++ b/app/controllers/concerns/issuable_actions.rb @@ -184,7 +184,6 @@ module IssuableActions def paginated_discussions return if params[:per_page].blank? - return if issuable.instance_of?(Issue) && Feature.disabled?(:paginated_issue_discussions, project) return if issuable.instance_of?(MergeRequest) && Feature.disabled?(:paginated_mr_discussions, project) strong_memoize(:paginated_discussions) do diff --git a/app/controllers/projects/issues_controller.rb b/app/controllers/projects/issues_controller.rb index 255d77988f2..15b5d2aa241 100644 --- a/app/controllers/projects/issues_controller.rb +++ b/app/controllers/projects/issues_controller.rb @@ -47,7 +47,6 @@ class Projects::IssuesController < Projects::ApplicationController before_action only: :show do push_frontend_feature_flag(:confidential_notes, project&.group) push_frontend_feature_flag(:issue_assignees_widget, project) - push_frontend_feature_flag(:paginated_issue_discussions, project) push_frontend_feature_flag(:realtime_labels, project) push_force_frontend_feature_flag(:work_items, project&.work_items_feature_flag_enabled?) push_frontend_feature_flag(:work_items_mvc_2) diff --git a/app/models/concerns/notification_branch_selection.rb b/app/models/concerns/notification_branch_selection.rb index 18ec996c3df..f2df7579a65 100644 --- a/app/models/concerns/notification_branch_selection.rb +++ b/app/models/concerns/notification_branch_selection.rb @@ -6,13 +6,15 @@ module NotificationBranchSelection extend ActiveSupport::Concern - def branch_choices - [ - [_('All branches'), 'all'].freeze, - [_('Default branch'), 'default'].freeze, - [_('Protected branches'), 'protected'].freeze, - [_('Default branch and protected branches'), 'default_and_protected'].freeze - ].freeze + class_methods do + def branch_choices + [ + [_('All branches'), 'all'].freeze, + [_('Default branch'), 'default'].freeze, + [_('Protected branches'), 'protected'].freeze, + [_('Default branch and protected branches'), 'default_and_protected'].freeze + ].freeze + end end def notify_for_branch?(data) diff --git a/app/models/integrations/asana.rb b/app/models/integrations/asana.rb index d25bf8b1b1e..2cfd71c9eb2 100644 --- a/app/models/integrations/asana.rb +++ b/app/models/integrations/asana.rb @@ -4,9 +4,22 @@ require 'asana' module Integrations class Asana < Integration - prop_accessor :api_key, :restrict_to_branch validates :api_key, presence: true, if: :activated? + field :api_key, + type: 'password', + title: 'API key', + help: -> { s_('AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user.') }, + non_empty_password_title: -> { s_('ProjectService|Enter new API key') }, + non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current API key.') }, + # Example Personal Access Token from Asana docs + placeholder: '0/68a9e79b868c6789e79a124c30b0', + required: true + + field :restrict_to_branch, + title: -> { s_('Integrations|Restrict to branch (optional)') }, + help: -> { s_('AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches.') } + def title 'Asana' end @@ -24,28 +37,6 @@ module Integrations 'asana' end - def fields - [ - { - type: 'password', - name: 'api_key', - title: 'API key', - help: s_('AsanaService|User Personal Access Token. User must have access to the task. All comments are attributed to this user.'), - non_empty_password_title: s_('ProjectService|Enter new API key'), - non_empty_password_help: s_('ProjectService|Leave blank to use your current API key.'), - # Example Personal Access Token from Asana docs - placeholder: '0/68a9e79b868c6789e79a124c30b0', - required: true - }, - { - type: 'text', - name: 'restrict_to_branch', - title: 'Restrict to branch (optional)', - help: s_('AsanaService|Comma-separated list of branches to be automatically inspected. Leave blank to include all branches.') - } - ] - end - def self.supported_events %w(push) end diff --git a/app/models/integrations/assembla.rb b/app/models/integrations/assembla.rb index ccd24c1fb2c..88dbf2915ef 100644 --- a/app/models/integrations/assembla.rb +++ b/app/models/integrations/assembla.rb @@ -2,9 +2,18 @@ module Integrations class Assembla < Integration - prop_accessor :token, :subdomain validates :token, presence: true, if: :activated? + field :token, + type: 'password', + non_empty_password_title: -> { s_('ProjectService|Enter new token') }, + non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current token.') }, + placeholder: '', + required: true + + field :subdomain, + placeholder: '' + def title 'Assembla' end @@ -17,24 +26,6 @@ module Integrations 'assembla' end - def fields - [ - { - type: 'password', - name: 'token', - non_empty_password_title: s_('ProjectService|Enter new token'), - non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'), - placeholder: '', - required: true - }, - { - type: 'text', - name: 'subdomain', - placeholder: '' - } - ] - end - def self.supported_events %w(push) end diff --git a/app/models/integrations/base_chat_notification.rb b/app/models/integrations/base_chat_notification.rb index 0cfdcdbaf5f..51f238d5eb9 100644 --- a/app/models/integrations/base_chat_notification.rb +++ b/app/models/integrations/base_chat_notification.rb @@ -78,7 +78,7 @@ module Integrations type: 'select', name: 'branches_to_be_notified', title: s_('Integrations|Branches for which notifications are to be sent'), - choices: branch_choices + choices: self.class.branch_choices }.freeze, { type: 'text', @@ -118,7 +118,7 @@ module Integrations event_type = data[:event_type] || object_kind - channel_names = get_channel_field(event_type).presence || channel.presence + channel_names = event_channel_value(event_type).presence || channel.presence channels = channel_names&.split(',')&.map(&:strip) opts = {} @@ -161,7 +161,7 @@ module Integrations EVENT_CHANNEL[event] end - def get_channel_field(event) + def event_channel_value(event) field_name = event_channel_name(event) self.public_send(field_name) # rubocop:disable GitlabSecurity/PublicSend end diff --git a/app/models/integrations/confluence.rb b/app/models/integrations/confluence.rb index 4e1d1993d02..c1c43af99bf 100644 --- a/app/models/integrations/confluence.rb +++ b/app/models/integrations/confluence.rb @@ -6,11 +6,14 @@ module Integrations VALID_HOST_MATCH = %r{\A.+\.atlassian\.net\Z}.freeze VALID_PATH_MATCH = %r{\A/wiki(/|\Z)}.freeze - prop_accessor :confluence_url - validates :confluence_url, presence: true, if: :activated? validate :validate_confluence_url_is_cloud, if: :activated? + field :confluence_url, + title: -> { s_('Confluence Cloud Workspace URL') }, + placeholder: 'https://example.atlassian.net/wiki', + required: true + def self.to_param 'confluence' end @@ -38,18 +41,6 @@ module Integrations end end - def fields - [ - { - type: 'text', - name: 'confluence_url', - title: s_('Confluence Cloud Workspace URL'), - placeholder: 'https://example.atlassian.net/wiki', - required: true - } - ] - end - def testable? false end diff --git a/app/models/integrations/discord.rb b/app/models/integrations/discord.rb index 231d1c62340..ecabf23c90b 100644 --- a/app/models/integrations/discord.rb +++ b/app/models/integrations/discord.rb @@ -39,7 +39,7 @@ module Integrations type: 'select', name: 'branches_to_be_notified', title: s_('Integrations|Branches for which notifications are to be sent'), - choices: branch_choices + choices: self.class.branch_choices } ] end diff --git a/app/models/integrations/emails_on_push.rb b/app/models/integrations/emails_on_push.rb index ab458bb2c27..ed12a3a8d63 100644 --- a/app/models/integrations/emails_on_push.rb +++ b/app/models/integrations/emails_on_push.rb @@ -6,12 +6,35 @@ module Integrations RECIPIENTS_LIMIT = 750 - boolean_accessor :send_from_committer_email - boolean_accessor :disable_diffs - prop_accessor :recipients, :branches_to_be_notified validates :recipients, presence: true, if: :validate_recipients? validate :number_of_recipients_within_limit, if: :validate_recipients? + field :send_from_committer_email, + type: 'checkbox', + title: -> { s_("EmailsOnPushService|Send from committer") }, + help: -> do + @help ||= begin + domains = Notify.allowed_email_domains.map { |domain| "user@#{domain}" }.join(", ") + + s_("EmailsOnPushService|Send notifications from the committer's email address if the domain matches the domain used by your GitLab instance (such as %{domains}).") % { domains: domains } + end + end + + field :disable_diffs, + type: 'checkbox', + title: -> { s_("EmailsOnPushService|Disable code diffs") }, + help: -> { s_("EmailsOnPushService|Don't include possibly sensitive code diffs in notification body.") } + + field :branches_to_be_notified, + type: 'select', + title: -> { s_('Integrations|Branches for which notifications are to be sent') }, + choices: branch_choices + + field :recipients, + type: 'textarea', + placeholder: -> { s_('EmailsOnPushService|tanuki@example.com gitlab@example.com') }, + help: -> { s_('EmailsOnPushService|Emails separated by whitespace.') } + def self.valid_recipients(recipients) recipients.split.grep(Devise.email_regexp).uniq(&:downcase) end @@ -67,28 +90,6 @@ module Integrations Gitlab::Utils.to_boolean(self.disable_diffs) end - def fields - domains = Notify.allowed_email_domains.map { |domain| "user@#{domain}" }.join(", ") - [ - { type: 'checkbox', name: 'send_from_committer_email', title: s_("EmailsOnPushService|Send from committer"), - help: s_("EmailsOnPushService|Send notifications from the committer's email address if the domain matches the domain used by your GitLab instance (such as %{domains}).") % { domains: domains } }, - { type: 'checkbox', name: 'disable_diffs', title: s_("EmailsOnPushService|Disable code diffs"), - help: s_("EmailsOnPushService|Don't include possibly sensitive code diffs in notification body.") }, - { - type: 'select', - name: 'branches_to_be_notified', - title: s_('Integrations|Branches for which notifications are to be sent'), - choices: branch_choices - }, - { - type: 'textarea', - name: 'recipients', - placeholder: s_('EmailsOnPushService|tanuki@example.com gitlab@example.com'), - help: s_('EmailsOnPushService|Emails separated by whitespace.') - } - ] - end - private def number_of_recipients_within_limit diff --git a/app/models/integrations/external_wiki.rb b/app/models/integrations/external_wiki.rb index 18c48411e30..c16ae9926f1 100644 --- a/app/models/integrations/external_wiki.rb +++ b/app/models/integrations/external_wiki.rb @@ -2,9 +2,14 @@ module Integrations class ExternalWiki < Integration - prop_accessor :external_wiki_url validates :external_wiki_url, presence: true, public_url: true, if: :activated? + field :external_wiki_url, + title: -> { s_('ExternalWikiService|External wiki URL') }, + placeholder: -> { s_('ExternalWikiService|https://example.com/xxx/wiki/...') }, + help: -> { s_('ExternalWikiService|Enter the URL to the external wiki.') }, + required: true + def title s_('ExternalWikiService|External wiki') end @@ -17,19 +22,6 @@ module Integrations 'external_wiki' end - def fields - [ - { - type: 'text', - name: 'external_wiki_url', - title: s_('ExternalWikiService|External wiki URL'), - placeholder: s_('ExternalWikiService|https://example.com/xxx/wiki/...'), - help: 'Enter the URL to the external wiki.', - required: true - } - ] - end - def help docs_link = ActionController::Base.helpers.link_to _('Learn more.'), Rails.application.routes.url_helpers.help_page_url('user/project/wiki/index', anchor: 'link-an-external-wiki'), target: '_blank', rel: 'noopener noreferrer' diff --git a/app/models/integrations/flowdock.rb b/app/models/integrations/flowdock.rb index 703d8013bab..52efb29f2c1 100644 --- a/app/models/integrations/flowdock.rb +++ b/app/models/integrations/flowdock.rb @@ -2,9 +2,16 @@ module Integrations class Flowdock < Integration - prop_accessor :token validates :token, presence: true, if: :activated? + field :token, + type: 'password', + help: -> { s_('FlowdockService|Enter your Flowdock token.') }, + non_empty_password_title: -> { s_('ProjectService|Enter new token') }, + non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current token.') }, + placeholder: '1b609b52537...', + required: true + def title 'Flowdock' end @@ -22,20 +29,6 @@ module Integrations 'flowdock' end - def fields - [ - { - type: 'password', - name: 'token', - help: s_('FlowdockService|Enter your Flowdock token.'), - non_empty_password_title: s_('ProjectService|Enter new token'), - non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'), - placeholder: '1b609b52537...', - required: true - } - ] - end - def self.supported_events %w(push) end diff --git a/app/models/integrations/hangouts_chat.rb b/app/models/integrations/hangouts_chat.rb index 4667bbffa1b..df112ad6ca8 100644 --- a/app/models/integrations/hangouts_chat.rb +++ b/app/models/integrations/hangouts_chat.rb @@ -39,7 +39,7 @@ module Integrations type: 'select', name: 'branches_to_be_notified', title: s_('Integrations|Branches for which notifications are to be sent'), - choices: branch_choices + choices: self.class.branch_choices } ] end diff --git a/app/models/integrations/microsoft_teams.rb b/app/models/integrations/microsoft_teams.rb index 949b24ca03f..69863f164cd 100644 --- a/app/models/integrations/microsoft_teams.rb +++ b/app/models/integrations/microsoft_teams.rb @@ -44,7 +44,7 @@ module Integrations section: SECTION_TYPE_CONFIGURATION, name: 'branches_to_be_notified', title: s_('Integrations|Branches for which notifications are to be sent'), - choices: branch_choices + choices: self.class.branch_choices } ] end diff --git a/app/models/integrations/pipelines_email.rb b/app/models/integrations/pipelines_email.rb index f15482dc2e1..c08d1fe7f4a 100644 --- a/app/models/integrations/pipelines_email.rb +++ b/app/models/integrations/pipelines_email.rb @@ -76,7 +76,7 @@ module Integrations { type: 'select', name: 'branches_to_be_notified', title: s_('Integrations|Branches for which notifications are to be sent'), - choices: branch_choices } + choices: self.class.branch_choices } ] end diff --git a/app/models/integrations/pivotaltracker.rb b/app/models/integrations/pivotaltracker.rb index 931ccf46655..d32fb974339 100644 --- a/app/models/integrations/pivotaltracker.rb +++ b/app/models/integrations/pivotaltracker.rb @@ -4,9 +4,22 @@ module Integrations class Pivotaltracker < Integration API_ENDPOINT = 'https://www.pivotaltracker.com/services/v5/source_commits' - prop_accessor :token, :restrict_to_branch validates :token, presence: true, if: :activated? + field :token, + type: 'password', + help: -> { s_('PivotalTrackerService|Pivotal Tracker API token. User must have access to the story. All comments are attributed to this user.') }, + non_empty_password_title: -> { s_('ProjectService|Enter new token') }, + non_empty_password_help: -> { s_('ProjectService|Leave blank to use your current token.') }, + required: true + + field :restrict_to_branch, + title: -> { s_('Integrations|Restrict to branch (optional)') }, + help: -> do + s_('PivotalTrackerService|Comma-separated list of branches to ' \ + 'automatically inspect. Leave blank to include all branches.') + end + def title 'Pivotal Tracker' end @@ -24,26 +37,6 @@ module Integrations 'pivotaltracker' end - def fields - [ - { - type: 'password', - name: 'token', - help: s_('PivotalTrackerService|Pivotal Tracker API token. User must have access to the story. All comments are attributed to this user.'), - non_empty_password_title: s_('ProjectService|Enter new token'), - non_empty_password_help: s_('ProjectService|Leave blank to use your current token.'), - required: true - }, - { - type: 'text', - name: 'restrict_to_branch', - title: 'Restrict to branch (optional)', - help: s_('PivotalTrackerService|Comma-separated list of branches to ' \ - 'automatically inspect. Leave blank to include all branches.') - } - ] - end - def self.supported_events %w(push) end diff --git a/app/models/integrations/prometheus.rb b/app/models/integrations/prometheus.rb index 36060565317..e672a985810 100644 --- a/app/models/integrations/prometheus.rb +++ b/app/models/integrations/prometheus.rb @@ -4,11 +4,30 @@ module Integrations class Prometheus < BaseMonitoring include PrometheusAdapter - # Access to prometheus is directly through the API - prop_accessor :api_url - prop_accessor :google_iap_service_account_json - prop_accessor :google_iap_audience_client_id - boolean_accessor :manual_configuration + field :manual_configuration, + type: 'checkbox', + title: -> { s_('PrometheusService|Active') }, + help: -> { s_('PrometheusService|Select this checkbox to override the auto configuration settings with your own settings.') }, + required: true + + field :api_url, + title: 'API URL', + placeholder: -> { s_('PrometheusService|https://prometheus.example.com/') }, + help: -> { s_('PrometheusService|The Prometheus API base URL.') }, + required: true + + field :google_iap_audience_client_id, + title: 'Google IAP Audience Client ID', + placeholder: -> { s_('PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com') }, + help: -> { s_('PrometheusService|The ID of the IAP-secured resource.') }, + required: false + + field :google_iap_service_account_json, + type: 'textarea', + title: 'Google IAP Service Account JSON', + placeholder: -> { s_('PrometheusService|{ "type": "service_account", "project_id": ... }') }, + help: -> { s_('PrometheusService|The contents of the credentials.json file of your service account.') }, + required: false # We need to allow the self-monitoring project to connect to the internal # Prometheus instance. @@ -45,43 +64,6 @@ module Integrations 'prometheus' end - def fields - [ - { - type: 'checkbox', - name: 'manual_configuration', - title: s_('PrometheusService|Active'), - help: s_('PrometheusService|Select this checkbox to override the auto configuration settings with your own settings.'), - required: true - }, - { - type: 'text', - name: 'api_url', - title: 'API URL', - placeholder: s_('PrometheusService|https://prometheus.example.com/'), - help: s_('PrometheusService|The Prometheus API base URL.'), - required: true - }, - { - type: 'text', - name: 'google_iap_audience_client_id', - title: 'Google IAP Audience Client ID', - placeholder: s_('PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com'), - help: s_('PrometheusService|The ID of the IAP-secured resource.'), - autocomplete: 'off', - required: false - }, - { - type: 'textarea', - name: 'google_iap_service_account_json', - title: 'Google IAP Service Account JSON', - placeholder: s_('PrometheusService|{ "type": "service_account", "project_id": ... }'), - help: s_('PrometheusService|The contents of the credentials.json file of your service account.'), - required: false - } - ] - end - # Check we can connect to the Prometheus API def test(*args) return { success: false, result: 'Prometheus configuration error' } unless prometheus_client diff --git a/app/models/integrations/unify_circuit.rb b/app/models/integrations/unify_circuit.rb index 40570c098c2..646c2e75b03 100644 --- a/app/models/integrations/unify_circuit.rb +++ b/app/models/integrations/unify_circuit.rb @@ -35,7 +35,7 @@ module Integrations type: 'select', name: 'branches_to_be_notified', title: s_('Integrations|Branches for which notifications are to be sent'), - choices: branch_choices + choices: self.class.branch_choices } ] end diff --git a/app/models/integrations/webex_teams.rb b/app/models/integrations/webex_teams.rb index 7bf90259267..54d6f51ee17 100644 --- a/app/models/integrations/webex_teams.rb +++ b/app/models/integrations/webex_teams.rb @@ -35,7 +35,7 @@ module Integrations type: 'select', name: 'branches_to_be_notified', title: s_('Integrations|Branches for which notifications are to be sent'), - choices: branch_choices + choices: self.class.branch_choices } ] end diff --git a/app/serializers/integrations/event_entity.rb b/app/serializers/integrations/event_entity.rb index f603c0e035e..91bd91dd941 100644 --- a/app/serializers/integrations/event_entity.rb +++ b/app/serializers/integrations/event_entity.rb @@ -23,7 +23,7 @@ module Integrations integration.event_channel_name(event) end expose :value do |event| - integration.get_channel_field(event) + integration.event_channel_value(event) end end diff --git a/app/views/projects/issues/_discussion.html.haml b/app/views/projects/issues/_discussion.html.haml index a904b53515c..16b795ee3c9 100644 --- a/app/views/projects/issues/_discussion.html.haml +++ b/app/views/projects/issues/_discussion.html.haml @@ -1,4 +1,4 @@ -- add_page_startup_api_call Feature.enabled?(:paginated_issue_discussions, @project) ? discussions_path(@issue, per_page: 20) : discussions_path(@issue) +- add_page_startup_api_call discussions_path(@issue, per_page: 20) - @gfm_form = true diff --git a/config/feature_flags/development/paginated_issue_discussions.yml b/config/feature_flags/development/paginated_issue_discussions.yml deleted file mode 100644 index f4e765bd7f2..00000000000 --- a/config/feature_flags/development/paginated_issue_discussions.yml +++ /dev/null @@ -1,8 +0,0 @@ ---- -name: paginated_issue_discussions -introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/69933 -rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/345351 -milestone: '14.5' -type: development -group: group::project management -default_enabled: false diff --git a/db/docs/ci_job_token_project_scope_links.yml b/db/docs/ci_job_token_project_scope_links.yml index e073b63e924..993d392bb93 100644 --- a/db/docs/ci_job_token_project_scope_links.yml +++ b/db/docs/ci_job_token_project_scope_links.yml @@ -3,7 +3,7 @@ table_name: ci_job_token_project_scope_links classes: - Ci::JobToken::ProjectScopeLink feature_categories: -- pipeline_authoring -description: TODO +- continuous_integration +description: The connection between a source project, which defines the job token scope, and a target project, which is the one allowed to be accessed by the job token. introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/62733 milestone: '14.0' diff --git a/doc/development/api_graphql_styleguide.md b/doc/development/api_graphql_styleguide.md index de6840b2c6c..6c5d91af9ac 100644 --- a/doc/development/api_graphql_styleguide.md +++ b/doc/development/api_graphql_styleguide.md @@ -475,16 +475,16 @@ end Developers can add [feature flags](../development/feature_flags/index.md) to GraphQL fields in the following ways: -- Add the `feature_flag` property to a field. This allows the field to be _hidden_ +- Add the [`feature_flag` property](#feature_flag-property) to a field. This allows the field to be _hidden_ from the GraphQL schema when the flag is disabled. -- Toggle the return value when resolving the field. +- [Toggle the return value](#toggle-the-value-of-a-field) when resolving the field. You can refer to these guidelines to decide which approach to use: - If your field is experimental, and its name or type is subject to - change, use the `feature_flag` property. + change, use the [`feature_flag` property](#feature_flag-property). - If your field is stable and its definition doesn't change, even after the flag is - removed, toggle the return value of the field instead. Note that + removed, [toggle the return value](#toggle-the-value-of-a-field) of the field instead. Note that [all fields should be nullable](#nullable-fields) anyway. ### `feature_flag` property @@ -524,6 +524,12 @@ return value of the field. This can be done in the resolver, in the type, or even in a model method, depending on your preference and situation. +Consider also [marking the field as Alpha](#marking-schema-items-as-alpha) +while the value of the field can be toggled. You can +[change or remove Alpha fields at any time](#breaking-change-exemptions) without needing to deprecate them. +This also signals to consumers of the public GraphQL API that the field is not +meant to be used yet. + When applying a feature flag to toggle the value of a field, the `description` of the field must: @@ -537,6 +543,7 @@ Example: ```ruby field :foo, GraphQL::Types::String, null: true, + deprecated: { reason: :alpha, milestone: '10.0' }, description: 'Some test field. Returns `null`' \ 'if `my_feature_flag` feature flag is disabled.' @@ -2007,13 +2014,13 @@ end .to contain_exactly(a_graphql_entity_for(issue, :iid, :title, created_at: some_time)) ``` -- Use `GraphqlHelpers#empty_schema` to create an empty schema, rather than creating +- Use `GraphqlHelpers#empty_schema` to create an empty schema, rather than creating one by hand. For example: - + ```ruby # good let(:schema) { empty_schema } - + # bad let(:query_type) { GraphQL::ObjectType.new } let(:schema) { GraphQL::Schema.define(query: query_type, mutation: nil)} @@ -2024,7 +2031,7 @@ end ```ruby # good let(:query) { query_double(schema: GitlabSchema) } - + # bad let(:query) { double('Query', schema: GitlabSchema) } ``` @@ -2092,9 +2099,9 @@ end ```ruby type Types::IssueType.connection_type, null: true ``` - + However this might cause a cyclic definition, which can result in errors like: - + ```ruby NameError: uninitialized constant Resolvers::GroupIssuesResolver ``` @@ -2109,7 +2116,7 @@ end class IssueConnectionType < CountableConnectionType end end - + Types::IssueConnectionType.prepend_mod_with('Types::IssueConnectionType') ``` @@ -2120,22 +2127,22 @@ end ```ruby type "Types::IssueConnection", null: true ``` - + Only use this style if you are having spec failures. This is not intended to be a new pattern that we use. This issue may disappear after we've upgraded to `2.x`. -- There can be instances where a spec fails because the class is not loaded correctly. - It relates to the +- There can be instances where a spec fails because the class is not loaded correctly. + It relates to the [circular dependencies problem](https://github.com/rmosolgo/graphql-ruby/issues/1929) and [Adding field with resolver on a Type causes "Can't determine the return type " error on a different Type](https://github.com/rmosolgo/graphql-ruby/issues/3974). Unfortunately, the errors generated don't really indicate what the problem is. For example, - remove the quotes from the `Rspec.descrbe` in + remove the quotes from the `Rspec.descrbe` in [ee/spec/graphql/resolvers/compliance_management/merge_requests/compliance_violation_resolver_spec.rb](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/spec/graphql/resolvers/compliance_management/merge_requests/compliance_violation_resolver_spec.rb). Then run `rspec ee/spec/graphql/resolvers/compliance_management/merge_requests/compliance_violation_resolver_spec.rb`. - + This generates errors with the expectations. For example: - + ```ruby 1) Resolvers::ComplianceManagement::MergeRequests::ComplianceViolationResolver#resolve user is authorized filtering the results when given an array of project IDs finds the filtered compliance violations Failure/Error: expect(subject).to contain_exactly(compliance_violation) @@ -2145,10 +2152,10 @@ end the extra elements were: [#] # ./ee/spec/graphql/resolvers/compliance_management/merge_requests/compliance_violation_resolver_spec.rb:55:in `block (6 levels) in ' ``` - + However, this is not a case of the wrong result being generated, it's because of the loading order of the `ComplianceViolationResolver` class. - + The only way we've found to fix this is by quoting the class name in the spec. For example, changing ```ruby @@ -2198,7 +2205,7 @@ end [removed eventually](https://gitlab.com/gitlab-org/gitlab/-/issues/363121), and writing unit tests for resolvers/mutations is [already deprecated](#writing-unit-tests-deprecated) - + ## Notes about Query flow and GraphQL infrastructure The GitLab GraphQL infrastructure can be found in `lib/gitlab/graphql`. diff --git a/doc/development/documentation/restful_api_styleguide.md b/doc/development/documentation/restful_api_styleguide.md index b083f68e52d..92c34c01e5d 100644 --- a/doc/development/documentation/restful_api_styleguide.md +++ b/doc/development/documentation/restful_api_styleguide.md @@ -104,7 +104,10 @@ for the section. For example: > `widget_message` [introduced]() in GitLab 14.3. ``` -## Attribute deprecation +## Deprecations + +To document the deprecation of an API endpoint, follow the steps to +[deprecate a page or topic](versions.md#deprecate-a-page-or-topic). To deprecate an attribute: @@ -122,8 +125,8 @@ To deprecate an attribute: | `widget_name` | string | **{dotted-circle}** No | [Deprecated]() in GitLab 14.7 and is planned for removal in 15.4. Use `widget_id` instead. The name of the widget. | ``` -1. Optional. To widely announce the change, or if it's a breaking change, - [update the deprecations and removals documentation](../deprecation_guidelines/#update-the-deprecations-and-removals-documentation). +To widely announce a deprecation, or if it's a breaking change, +[update the deprecations and removals documentation](../deprecation_guidelines/#update-the-deprecations-and-removals-documentation). ## Method description diff --git a/locale/gitlab.pot b/locale/gitlab.pot index ec8a25a961c..e7f0fb07fa8 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -15520,6 +15520,9 @@ msgstr "" msgid "ExternalIssueIntegration|This issue is synchronized with %{trackerName}" msgstr "" +msgid "ExternalWikiService|Enter the URL to the external wiki." +msgstr "" + msgid "ExternalWikiService|External wiki" msgstr "" @@ -20767,6 +20770,9 @@ msgstr "" msgid "Integrations|Resetting this integration will clear the settings and deactivate this integration." msgstr "" +msgid "Integrations|Restrict to branch (optional)" +msgstr "" + msgid "Integrations|Return to GitLab for Jira" msgstr "" diff --git a/package.json b/package.json index 70dd0a3f3c8..1de50178951 100644 --- a/package.json +++ b/package.json @@ -151,7 +151,7 @@ "pikaday": "^1.8.0", "popper.js": "^1.16.1", "portal-vue": "^2.1.7", - "postcss": "8.4.5", + "postcss": "8.4.14", "prismjs": "^1.21.0", "prosemirror-markdown": "1.8.0", "prosemirror-model": "^1.16.1", @@ -201,7 +201,7 @@ }, "devDependencies": { "@gitlab/eslint-plugin": "12.1.0", - "@gitlab/stylelint-config": "4.0.0", + "@gitlab/stylelint-config": "4.1.0", "@graphql-eslint/eslint-plugin": "3.10.4", "@testing-library/dom": "^7.16.2", "@types/jest": "^26.0.24", @@ -248,7 +248,7 @@ "purgecss": "^4.0.3", "purgecss-from-html": "^4.0.3", "sass": "^1.49.9", - "stylelint": "^14.3.0", + "stylelint": "^14.9.1", "timezone-mock": "^1.0.8", "vue-jest": "4.0.1", "webpack-dev-server": "4.9.2", diff --git a/rubocop/cop/gitlab/namespaced_class.rb b/rubocop/cop/gitlab/namespaced_class.rb index ce46e055c21..07e3fb8975f 100644 --- a/rubocop/cop/gitlab/namespaced_class.rb +++ b/rubocop/cop/gitlab/namespaced_class.rb @@ -34,7 +34,7 @@ module RuboCop # # class Gitlab::MyDomain::MyClass # end - class NamespacedClass < RuboCop::Cop::Cop + class NamespacedClass < RuboCop::Cop::Base MSG = 'Classes must be declared inside a module indicating a product domain namespace. For more info: https://gitlab.com/gitlab-org/gitlab/-/issues/321982' # These namespaces are considered top-level semantically. @@ -51,7 +51,7 @@ module RuboCop # Remove class name because it's not a domain namespace. add_potential_domain_namespace(node) { _1.pop } - add_offense(node) if domain_namespaces.none? + add_offense(node.loc.name) if domain_namespaces.none? end private diff --git a/scripts/process_custom_semgrep_results.sh b/scripts/process_custom_semgrep_results.sh index 28fb5c79598..1fdd8e486f3 100755 --- a/scripts/process_custom_semgrep_results.sh +++ b/scripts/process_custom_semgrep_results.sh @@ -14,7 +14,7 @@ jq -crM '.vulnerabilities | ) | sort | if length > 0 then - { body: ("The findings below have been detected based on the [AppSec custom Semgrep rules](https://gitlab.com/gitlab-com/gl-security/appsec/sast-custom-rules/) and need attention:\n\n" + join("\n") + "\n\n/cc @gitlab-com/gl-security/appsec") } + { body: ("The findings below have been detected based on the AppSec custom SAST rules. For more information about this bot and what to do with this comment head over to the [README](https://gitlab.com/gitlab-com/gl-security/appsec/sast-custom-rules/-/tree/main/appsec-pings). The following lines of code possibly need attention:\n\n" + join("\n") + "\n\n/cc @gitlab-com/gl-security/appsec") } else empty end' gl-sast-report.json >findings.txt diff --git a/spec/frontend/notes/components/notes_app_spec.js b/spec/frontend/notes/components/notes_app_spec.js index f4eb69e0d49..acd27dab4eb 100644 --- a/spec/frontend/notes/components/notes_app_spec.js +++ b/spec/frontend/notes/components/notes_app_spec.js @@ -217,8 +217,7 @@ describe('note_app', () => { }); afterEach(() => { - waitForDiscussionsRequest(); - resetHTMLFixture(); + return waitForDiscussionsRequest().then(() => resetHTMLFixture()); }); it('renders skeleton notes', () => { @@ -471,7 +470,7 @@ describe('note_app', () => { wrapper = shallowMount(NotesApp, { propsData, store: createStore() }); await waitForPromises(); - expect(axiosMock.history.get[0].params).toBeUndefined(); + expect(axiosMock.history.get[0].params).toEqual({ per_page: 20 }); }); }); @@ -496,14 +495,14 @@ describe('note_app', () => { wrapper = mountWithNotesFilter(undefined); await waitForPromises(); - expect(axiosMock.history.get[0].params).toBeUndefined(); + expect(axiosMock.history.get[0].params).toEqual({ per_page: 20 }); }); it('does not include extra query params when filter is already set to default', async () => { wrapper = mountWithNotesFilter(constants.DISCUSSION_FILTERS_DEFAULT_VALUE); await waitForPromises(); - expect(axiosMock.history.get[0].params).toBeUndefined(); + expect(axiosMock.history.get[0].params).toEqual({ per_page: 20 }); }); it('includes extra query params when filter is not set to default', async () => { @@ -512,6 +511,7 @@ describe('note_app', () => { expect(axiosMock.history.get[0].params).toEqual({ notes_filter: constants.DISCUSSION_FILTERS_DEFAULT_VALUE, + per_page: 20, persist_filter: false, }); }); diff --git a/spec/frontend/notes/stores/actions_spec.js b/spec/frontend/notes/stores/actions_spec.js index 38f29ac2559..bf69d24bcb9 100644 --- a/spec/frontend/notes/stores/actions_spec.js +++ b/spec/frontend/notes/stores/actions_spec.js @@ -1351,7 +1351,7 @@ describe('Actions Notes Store', () => { return testAction( actions.fetchDiscussions, {}, - null, + { noteableType: notesConstants.MERGE_REQUEST_NOTEABLE_TYPE }, [ { type: mutationTypes.ADD_OR_UPDATE_DISCUSSIONS, payload: { discussion } }, { type: mutationTypes.SET_FETCHING_DISCUSSIONS, payload: false }, @@ -1360,13 +1360,11 @@ describe('Actions Notes Store', () => { ); }); - it('dispatches `fetchDiscussionsBatch` action if `paginatedIssueDiscussions` feature flag is enabled', () => { - window.gon = { features: { paginatedIssueDiscussions: true } }; - + it('dispatches `fetchDiscussionsBatch` action if noteable is an Issue', () => { return testAction( actions.fetchDiscussions, { path: 'test-path', filter: 'test-filter', persistFilter: 'test-persist-filter' }, - null, + { noteableType: notesConstants.ISSUE_NOTEABLE_TYPE }, [], [ { @@ -1389,7 +1387,7 @@ describe('Actions Notes Store', () => { return testAction( actions.fetchDiscussions, { path: 'test-path', filter: 'test-filter', persistFilter: 'test-persist-filter' }, - null, + { noteableType: notesConstants.MERGE_REQUEST_NOTEABLE_TYPE }, [], [ { diff --git a/spec/lib/gitlab/elasticsearch/logs/lines_spec.rb b/spec/lib/gitlab/elasticsearch/logs/lines_spec.rb deleted file mode 100644 index f93c1aa1974..00000000000 --- a/spec/lib/gitlab/elasticsearch/logs/lines_spec.rb +++ /dev/null @@ -1,97 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::Elasticsearch::Logs::Lines do - let(:client) { Elasticsearch::Transport::Client } - - let(:es_message_1) { { timestamp: "2019-12-13T14:35:34.034Z", pod: "production-6866bc8974-m4sk4", message: "10.8.2.1 - - [25/Oct/2019:08:03:22 UTC] \"GET / HTTP/1.1\" 200 13" } } - let(:es_message_2) { { timestamp: "2019-12-13T14:35:35.034Z", pod: "production-6866bc8974-m4sk4", message: "10.8.2.1 - - [27/Oct/2019:23:49:54 UTC] \"GET / HTTP/1.1\" 200 13" } } - let(:es_message_3) { { timestamp: "2019-12-13T14:35:36.034Z", pod: "production-6866bc8974-m4sk4", message: "10.8.2.1 - - [04/Nov/2019:23:09:24 UTC] \"GET / HTTP/1.1\" 200 13" } } - let(:es_message_4) { { timestamp: "2019-12-13T14:35:37.034Z", pod: "production-6866bc8974-m4sk4", message: "- -\u003e /" } } - - let(:es_response) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/logs_response.json')) } - - subject { described_class.new(client) } - - let(:namespace) { "autodevops-deploy-9-production" } - let(:pod_name) { "production-6866bc8974-m4sk4" } - let(:container_name) { "auto-deploy-app" } - let(:search) { "foo +bar "} - let(:start_time) { "2019-12-13T14:35:34.034Z" } - let(:end_time) { "2019-12-13T14:35:34.034Z" } - let(:cursor) { "9999934,1572449784442" } - - let(:body) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query.json')) } - let(:body_with_container) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_container.json')) } - let(:body_with_search) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_search.json')) } - let(:body_with_times) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_times.json')) } - let(:body_with_start_time) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_start_time.json')) } - let(:body_with_end_time) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_end_time.json')) } - let(:body_with_cursor) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_cursor.json')) } - let(:body_with_filebeat_6) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/query_with_filebeat_6.json')) } - - RSpec::Matchers.define :a_hash_equal_to_json do |expected| - match do |actual| - actual.as_json == expected - end - end - - describe '#pod_logs' do - it 'returns the logs as an array' do - expect(client).to receive(:search).with(body: a_hash_equal_to_json(body)).and_return(es_response) - - result = subject.pod_logs(namespace, pod_name: pod_name) - expect(result).to eq(logs: [es_message_4, es_message_3, es_message_2, es_message_1], cursor: cursor) - end - - it 'can further filter the logs by container name' do - expect(client).to receive(:search).with(body: a_hash_equal_to_json(body_with_container)).and_return(es_response) - - result = subject.pod_logs(namespace, pod_name: pod_name, container_name: container_name) - expect(result).to eq(logs: [es_message_4, es_message_3, es_message_2, es_message_1], cursor: cursor) - end - - it 'can further filter the logs by search' do - expect(client).to receive(:search).with(body: a_hash_equal_to_json(body_with_search)).and_return(es_response) - - result = subject.pod_logs(namespace, pod_name: pod_name, search: search) - expect(result).to eq(logs: [es_message_4, es_message_3, es_message_2, es_message_1], cursor: cursor) - end - - it 'can further filter the logs by start_time and end_time' do - expect(client).to receive(:search).with(body: a_hash_equal_to_json(body_with_times)).and_return(es_response) - - result = subject.pod_logs(namespace, pod_name: pod_name, start_time: start_time, end_time: end_time) - expect(result).to eq(logs: [es_message_4, es_message_3, es_message_2, es_message_1], cursor: cursor) - end - - it 'can further filter the logs by only start_time' do - expect(client).to receive(:search).with(body: a_hash_equal_to_json(body_with_start_time)).and_return(es_response) - - result = subject.pod_logs(namespace, pod_name: pod_name, start_time: start_time) - expect(result).to eq(logs: [es_message_4, es_message_3, es_message_2, es_message_1], cursor: cursor) - end - - it 'can further filter the logs by only end_time' do - expect(client).to receive(:search).with(body: a_hash_equal_to_json(body_with_end_time)).and_return(es_response) - - result = subject.pod_logs(namespace, pod_name: pod_name, end_time: end_time) - expect(result).to eq(logs: [es_message_4, es_message_3, es_message_2, es_message_1], cursor: cursor) - end - - it 'can search after a cursor' do - expect(client).to receive(:search).with(body: a_hash_equal_to_json(body_with_cursor)).and_return(es_response) - - result = subject.pod_logs(namespace, pod_name: pod_name, cursor: cursor) - expect(result).to eq(logs: [es_message_4, es_message_3, es_message_2, es_message_1], cursor: cursor) - end - - it 'can search on filebeat 6' do - expect(client).to receive(:search).with(body: a_hash_equal_to_json(body_with_filebeat_6)).and_return(es_response) - - result = subject.pod_logs(namespace, pod_name: pod_name, chart_above_v2: false) - expect(result).to eq(logs: [es_message_4, es_message_3, es_message_2, es_message_1], cursor: cursor) - end - end -end diff --git a/spec/lib/gitlab/elasticsearch/logs/pods_spec.rb b/spec/lib/gitlab/elasticsearch/logs/pods_spec.rb deleted file mode 100644 index 07fa0980d36..00000000000 --- a/spec/lib/gitlab/elasticsearch/logs/pods_spec.rb +++ /dev/null @@ -1,35 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Gitlab::Elasticsearch::Logs::Pods do - let(:client) { Elasticsearch::Transport::Client } - - let(:es_query) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/pods_query.json'), symbolize_names: true) } - let(:es_response) { Gitlab::Json.parse(fixture_file('lib/elasticsearch/pods_response.json')) } - let(:namespace) { "autodevops-deploy-9-production" } - - subject { described_class.new(client) } - - describe '#pods' do - it 'returns the pods' do - expect(client).to receive(:search).with(body: es_query).and_return(es_response) - - result = subject.pods(namespace) - expect(result).to eq([ - { - name: "runner-gitlab-runner-7bbfb5dcb5-p6smb", - container_names: %w[runner-gitlab-runner] - }, - { - name: "elastic-stack-elasticsearch-master-1", - container_names: %w[elasticsearch chown sysctl] - }, - { - name: "ingress-nginx-ingress-controller-76449bcc8d-8qgl6", - container_names: %w[nginx-ingress-controller] - } - ]) - end - end -end diff --git a/spec/models/integrations/base_chat_notification_spec.rb b/spec/models/integrations/base_chat_notification_spec.rb index 8cbefbb9b47..eb503e501d6 100644 --- a/spec/models/integrations/base_chat_notification_spec.rb +++ b/spec/models/integrations/base_chat_notification_spec.rb @@ -292,15 +292,15 @@ RSpec.describe Integrations::BaseChatNotification do end end - describe '#get_channel_field' do + describe '#event_channel_value' do it 'returns the channel field value for the given event' do subject.push_channel = '#pushes' - expect(subject.get_channel_field(:push)).to eq('#pushes') + expect(subject.event_channel_value(:push)).to eq('#pushes') end it 'raises an error for unsupported events' do - expect { subject.get_channel_field(:foo) }.to raise_error(NoMethodError) + expect { subject.event_channel_value(:foo) }.to raise_error(NoMethodError) end end end diff --git a/spec/models/integrations/prometheus_spec.rb b/spec/models/integrations/prometheus_spec.rb index fbeaebfd807..ae965ed78d1 100644 --- a/spec/models/integrations/prometheus_spec.rb +++ b/spec/models/integrations/prometheus_spec.rb @@ -475,47 +475,4 @@ RSpec.describe Integrations::Prometheus, :use_clean_rails_memory_store_caching, end end end - - describe '#fields' do - let(:expected_fields) do - [ - { - type: 'checkbox', - name: 'manual_configuration', - title: s_('PrometheusService|Active'), - help: s_('PrometheusService|Select this checkbox to override the auto configuration settings with your own settings.'), - required: true - }, - { - type: 'text', - name: 'api_url', - title: 'API URL', - placeholder: s_('PrometheusService|https://prometheus.example.com/'), - help: s_('PrometheusService|The Prometheus API base URL.'), - required: true - }, - { - type: 'text', - name: 'google_iap_audience_client_id', - title: 'Google IAP Audience Client ID', - placeholder: s_('PrometheusService|IAP_CLIENT_ID.apps.googleusercontent.com'), - help: s_('PrometheusService|The ID of the IAP-secured resource.'), - autocomplete: 'off', - required: false - }, - { - type: 'textarea', - name: 'google_iap_service_account_json', - title: 'Google IAP Service Account JSON', - placeholder: s_('PrometheusService|{ "type": "service_account", "project_id": ... }'), - help: s_('PrometheusService|The contents of the credentials.json file of your service account.'), - required: false - } - ] - end - - it 'returns fields' do - expect(integration.fields).to eq(expected_fields) - end - end end diff --git a/spec/requests/api/environments_spec.rb b/spec/requests/api/environments_spec.rb index 93f21c880a4..a35c1630caa 100644 --- a/spec/requests/api/environments_spec.rb +++ b/spec/requests/api/environments_spec.rb @@ -26,90 +26,7 @@ RSpec.describe API::Environments do expect(json_response.first['tier']).to eq(environment.tier) expect(json_response.first['external_url']).to eq(environment.external_url) expect(json_response.first['project']).to match_schema('public_api/v4/project') - expect(json_response.first['enable_advanced_logs_querying']).to eq(false) expect(json_response.first).not_to have_key('last_deployment') - expect(json_response.first).not_to have_key('gitlab_managed_apps_logs_path') - end - - context 'when the user can read pod logs' do - context 'with successful deployment on cluster' do - let_it_be(:deployment) { create(:deployment, :on_cluster, :success, environment: environment, project: project) } - - it 'returns environment with enable_advanced_logs_querying and logs_api_path' do - get api("/projects/#{project.id}/environments", user) - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - expect(json_response.size).to eq(1) - expect(json_response.first['gitlab_managed_apps_logs_path']).to eq( - "/#{project.full_path}/-/logs/k8s.json?cluster_id=#{deployment.cluster_id}" - ) - end - end - - context 'when elastic stack is available' do - before do - allow_next_found_instance_of(Environment) do |env| - allow(env).to receive(:elastic_stack_available?).and_return(true) - end - end - - it 'returns environment with enable_advanced_logs_querying and logs_api_path' do - get api("/projects/#{project.id}/environments", user) - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - expect(json_response.size).to eq(1) - expect(json_response.first['enable_advanced_logs_querying']).to eq(true) - expect(json_response.first['logs_api_path']).to eq( - "/#{project.full_path}/-/logs/elasticsearch.json?environment_name=#{environment.name}" - ) - end - end - - context 'when elastic stack is not available' do - before do - allow_next_found_instance_of(Environment) do |env| - allow(env).to receive(:elastic_stack_available?).and_return(false) - end - end - - it 'returns environment with enable_advanced_logs_querying logs_api_path' do - get api("/projects/#{project.id}/environments", user) - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - expect(json_response.size).to eq(1) - expect(json_response.first['enable_advanced_logs_querying']).to eq(false) - expect(json_response.first['logs_api_path']).to eq( - "/#{project.full_path}/-/logs/k8s.json?environment_name=#{environment.name}" - ) - end - end - end - - context 'when the user cannot read pod logs' do - before do - allow_next_found_instance_of(User) do |user| - allow(user).to receive(:can?).and_call_original - allow(user).to receive(:can?).with(:read_pod_logs, project).and_return(false) - end - end - - it 'does not contain enable_advanced_logs_querying' do - get api("/projects/#{project.id}/environments", user) - - expect(response).to have_gitlab_http_status(:ok) - expect(response).to include_pagination_headers - expect(json_response).to be_an Array - expect(json_response.size).to eq(1) - expect(json_response.first).not_to have_key('enable_advanced_logs_querying') - expect(json_response.first).not_to have_key('logs_api_path') - expect(json_response.first).not_to have_key('gitlab_managed_apps_logs_path') - end end context 'when filtering' do diff --git a/spec/requests/projects/issues_controller_spec.rb b/spec/requests/projects/issues_controller_spec.rb index 248e3e3a92b..de1d55ff5be 100644 --- a/spec/requests/projects/issues_controller_spec.rb +++ b/spec/requests/projects/issues_controller_spec.rb @@ -50,22 +50,6 @@ RSpec.describe Projects::IssuesController do a_hash_including('id' => discussion_2.id.to_s) ]) end - - context 'when paginated_issue_discussions is disabled' do - before do - stub_feature_flags(paginated_issue_discussions: false) - end - - it 'returns all discussions and ignores per_page param' do - get_discussions(per_page: 2) - - discussions = Gitlab::Json.parse(response.body) - notes = discussions.flat_map { |d| d['notes'] } - - expect(discussions.count).to eq(4) - expect(notes.count).to eq(5) - end - end end end diff --git a/spec/rubocop/cop/gitlab/namespaced_class_spec.rb b/spec/rubocop/cop/gitlab/namespaced_class_spec.rb index d9209a8672c..83d0eaf4884 100644 --- a/spec/rubocop/cop/gitlab/namespaced_class_spec.rb +++ b/spec/rubocop/cop/gitlab/namespaced_class_spec.rb @@ -20,7 +20,7 @@ RSpec.describe RuboCop::Cop::Gitlab::NamespacedClass do it 'flags a class definition without additional namespace' do expect_offense(namespaced(<<~SOURCE)) class MyClass - ^^^^^^^^^^^^^ #{described_class::MSG} + ^^^^^^^ #{described_class::MSG} end SOURCE end @@ -28,7 +28,7 @@ RSpec.describe RuboCop::Cop::Gitlab::NamespacedClass do it 'flags a compact class definition without additional namespace' do expect_offense(<<~SOURCE, namespace: namespace) class %{namespace}::MyClass - ^{namespace}^^^^^^^^^^^^^^^ #{described_class::MSG} + ^{namespace}^^^^^^^^^ #{described_class::MSG} end SOURCE end @@ -36,7 +36,7 @@ RSpec.describe RuboCop::Cop::Gitlab::NamespacedClass do it 'flags a class definition with inheritance without additional namespace' do expect_offense(namespaced(<<~SOURCE)) class MyClass < ApplicationRecord - ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{described_class::MSG} + ^^^^^^^ #{described_class::MSG} def some_method true end diff --git a/spec/serializers/cluster_entity_spec.rb b/spec/serializers/cluster_entity_spec.rb index 514828e3c69..93003e75c0c 100644 --- a/spec/serializers/cluster_entity_spec.rb +++ b/spec/serializers/cluster_entity_spec.rb @@ -56,37 +56,6 @@ RSpec.describe ClusterEntity do end end - context 'gitlab_managed_apps_logs_path' do - let(:cluster) { create(:cluster, :project) } - let(:user) { create(:user) } - - subject { described_class.new(cluster, request: request).as_json } - - before do - allow_next_instance_of(Clusters::ClusterPresenter) do |presenter| - allow(presenter).to receive(:show_path).and_return(nil) - end - end - - it 'return projects log explorer path' do - log_explorer_path = project_logs_path(cluster.project, cluster_id: cluster.id) - - expect_next_instance_of(Clusters::ClusterPresenter, cluster, current_user: user) do |presenter| - expect(presenter).to receive(:gitlab_managed_apps_logs_path).and_return(log_explorer_path) - end - - expect(subject[:gitlab_managed_apps_logs_path]).to eq(log_explorer_path) - end - - context 'when feature is disabled' do - before do - stub_feature_flags(monitor_logging: false) - end - - specify { is_expected.not_to include(:gitlab_managed_apps_logs_path) } - end - end - context 'enable_advanced_logs_querying' do let(:cluster) { create(:cluster, :project) } let(:user) { create(:user) } diff --git a/spec/serializers/environment_entity_spec.rb b/spec/serializers/environment_entity_spec.rb index 9b6a293da16..cbe32600941 100644 --- a/spec/serializers/environment_entity_spec.rb +++ b/spec/serializers/environment_entity_spec.rb @@ -133,54 +133,6 @@ RSpec.describe EnvironmentEntity do end end - context 'pod_logs' do - context 'with reporter access' do - before do - project.add_reporter(user) - end - - it 'does not expose logs keys' do - expect(subject).not_to include(:logs_path) - expect(subject).not_to include(:logs_api_path) - expect(subject).not_to include(:enable_advanced_logs_querying) - end - end - - context 'with developer access' do - before do - project.add_developer(user) - end - - it 'exposes logs keys' do - expect(subject).to include(:logs_path) - expect(subject).to include(:logs_api_path) - expect(subject).to include(:enable_advanced_logs_querying) - end - - it 'uses k8s api when ES is not available' do - expect(subject[:logs_api_path]).to eq(k8s_project_logs_path(project, environment_name: environment.name, format: :json)) - end - - it 'uses ES api when ES is available' do - allow(environment).to receive(:elastic_stack_available?).and_return(true) - - expect(subject[:logs_api_path]).to eq(elasticsearch_project_logs_path(project, environment_name: environment.name, format: :json)) - end - - context 'with feature flag disabled' do - before do - stub_feature_flags(monitor_logging: false) - end - - it 'does not expose logs keys' do - expect(subject).not_to include(:logs_path) - expect(subject).not_to include(:logs_api_path) - expect(subject).not_to include(:enable_advanced_logs_querying) - end - end - end - end - context 'with deployment service ready' do before do allow(environment).to receive(:has_terminals?).and_return(true) diff --git a/yarn.lock b/yarn.lock index 413219ac652..a9378975e33 100644 --- a/yarn.lock +++ b/yarn.lock @@ -976,6 +976,11 @@ exec-sh "^0.3.2" minimist "^1.2.0" +"@csstools/selector-specificity@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@csstools/selector-specificity/-/selector-specificity-2.0.1.tgz#b6b8d81780b9a9f6459f4bfe9226ac6aefaefe87" + integrity sha512-aG20vknL4/YjQF9BSV7ts4EWm/yrjagAN7OWBNmlbEOUiu0llj4OGrFoOKK3g2vey4/p2omKCoHrWtPxSwV3HA== + "@discoveryjs/json-ext@^0.5.0": version "0.5.6" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.6.tgz#d5e0706cf8c6acd8c6032f8d54070af261bbbb2f" @@ -1034,14 +1039,14 @@ resolved "https://registry.yarnpkg.com/@gitlab/favicon-overlay/-/favicon-overlay-2.0.0.tgz#2f32d0b6a4d5b8ac44e2927083d9ab478a78c984" integrity sha512-GNcORxXJ98LVGzOT9dDYKfbheqH6lNgPDD72lyXRnQIH7CjgGyos8i17aSBPq1f4s3zF3PyedFiAR4YEZbva2Q== -"@gitlab/stylelint-config@4.0.0": - version "4.0.0" - resolved "https://registry.yarnpkg.com/@gitlab/stylelint-config/-/stylelint-config-4.0.0.tgz#d24646592908d92dce35aaa8e7bea66fd53e4160" - integrity sha512-5avbb8XQLdnL/vdrxf9jvdPl/HPaXnI7Y/fArOHe1uMpgcBoBWUKmon15+lHJ4MgURsGuYSiM2FIgArDSylR4g== +"@gitlab/stylelint-config@4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@gitlab/stylelint-config/-/stylelint-config-4.1.0.tgz#bd431406c8f8725afba353652f08e42c3301a982" + integrity sha512-WiTLRKoXutmAKR0z4Z/kuXiTAtblyA2XWX6vb2/NHhLd7oboKrxR8CiznSfw7SNxmYtqW/ripaQOdanR1fYMwA== dependencies: - postcss-scss "4.0.3" + postcss-scss "4.0.4" stylelint-declaration-strict-value "1.8.0" - stylelint-scss "4.1.0" + stylelint-scss "4.2.0" "@gitlab/svgs@2.21.0": version "2.21.0" @@ -3170,7 +3175,7 @@ braces@^2.3.1: split-string "^3.0.2" to-regex "^3.0.1" -braces@^3.0.1, braces@~3.0.2: +braces@^3.0.2, braces@~3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== @@ -4114,6 +4119,11 @@ css-color-names@0.0.4: resolved "https://registry.yarnpkg.com/css-color-names/-/css-color-names-0.0.4.tgz#808adc2e79cf84738069b646cb20ec27beb629e0" integrity sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= +css-functions-list@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/css-functions-list/-/css-functions-list-3.1.0.tgz#cf5b09f835ad91a00e5959bcfc627cd498e1321b" + integrity sha512-/9lCvYZaUbBGvYUgYGFJ4dcYiyqdhSjG7IPVluoV8A1ILjkF7ilmhp1OGUz8n+nmBcu0RNrQAzgD8B6FJbrt2w== + css-loader@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/css-loader/-/css-loader-2.1.1.tgz#d8254f72e412bb2238bb44dd674ffbef497333ea" @@ -4788,7 +4798,7 @@ debug@^3.1.0, debug@^3.2.6, debug@^3.2.7: dependencies: ms "^2.1.1" -debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.3, debug@^4.3.4: +debug@^4.0.0, debug@^4.0.1, debug@^4.1.0, debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: version "4.3.4" resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== @@ -6738,10 +6748,10 @@ html-escaper@^2.0.0: resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.0.tgz#71e87f931de3fe09e56661ab9a29aadec707b491" integrity sha512-a4u9BeERWGu/S8JiWEAQcdrg9v4QArtP9keViQjGMdff20fBdd8waotXaNmODqBe6uZ3Nafi7K/ho4gCQHV3Ig== -html-tags@^3.1.0: - version "3.1.0" - resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.1.0.tgz#7b5e6f7e665e9fb41f30007ed9e0d41e97fb2140" - integrity sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg== +html-tags@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/html-tags/-/html-tags-3.2.0.tgz#dbb3518d20b726524e4dd43de397eb0a95726961" + integrity sha512-vy7ClnArOZwCnqZgvv+ddgHgJiAFXe3Ge9ML5/mBctVJoUoYPCdxVucOywjDARn6CVoh3dRSFdPHy2sX80L0Wg== html-void-elements@^2.0.0: version "2.0.1" @@ -8117,10 +8127,10 @@ kleur@^4.0.3: resolved "https://registry.yarnpkg.com/kleur/-/kleur-4.1.4.tgz#8c202987d7e577766d039a8cd461934c01cda04d" integrity sha512-8QADVssbrFjivHWQU7KkMgptGTl6WAcSdlbBPY4uNF+mWr6DGcKrvY2w4FQJoXch7+fKMjj0dRrL75vk3k23OA== -known-css-properties@^0.24.0: - version "0.24.0" - resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.24.0.tgz#19aefd85003ae5698a5560d2b55135bf5432155c" - integrity sha512-RTSoaUAfLvpR357vWzAz/50Q/BmHfmE6ETSWfutT0AJiw10e6CmcdYRQJlLRd95B53D0Y2aD1jSxD3V3ySF+PA== +known-css-properties@^0.25.0: + version "0.25.0" + resolved "https://registry.yarnpkg.com/known-css-properties/-/known-css-properties-0.25.0.tgz#6ebc4d4b412f602e5cfbeb4086bd544e34c0a776" + integrity sha512-b0/9J1O9Jcyik1GC6KC42hJ41jKwdO/Mq8Mdo5sYN+IuRTXs2YFHZC3kZSx6ueusqa95x3wLYe/ytKjbAfGixA== latest-version@^5.0.0: version "5.1.0" @@ -9090,13 +9100,13 @@ micromatch@^3.1.10, micromatch@^3.1.4: snapdragon "^0.8.1" to-regex "^3.0.2" -micromatch@^4.0.2, micromatch@^4.0.4: - version "4.0.4" - resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.4.tgz#896d519dfe9db25fce94ceb7a500919bf881ebf9" - integrity sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg== +micromatch@^4.0.2, micromatch@^4.0.4, micromatch@^4.0.5: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== dependencies: - braces "^3.0.1" - picomatch "^2.2.3" + braces "^3.0.2" + picomatch "^2.3.1" miller-rabin@^4.0.0: version "4.0.1" @@ -9366,10 +9376,10 @@ multicast-dns@^7.2.4: dns-packet "^5.2.2" thunky "^1.0.2" -nanoid@^3.1.30: - version "3.2.0" - resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.2.0.tgz#62667522da6673971cca916a6d3eff3f415ff80c" - integrity sha512-fmsZYa9lpn69Ad5eDn7FMcnnSR+8R34W9qJEijxYhTbfOWzr22n1QxCMzXLK+ODyW2973V3Fux959iQoUxzUIA== +nanoid@^3.3.4: + version "3.3.4" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.4.tgz#730b67e3cd09e2deacf03c027c81c9d9dbc5e8ab" + integrity sha512-MqBkQh/OHTS2egovRtLk45wEyNXwF+cokD+1YPf9u5VfJiRdAiRwB2froX5Co9Rh20xs4siNPm8naNotSD6RBw== nanomatch@^1.2.9: version "1.2.13" @@ -9549,11 +9559,6 @@ normalize-path@^3.0.0, normalize-path@~3.0.0: resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== -normalize-selector@^0.2.0: - version "0.2.0" - resolved "https://registry.yarnpkg.com/normalize-selector/-/normalize-selector-0.2.0.tgz#d0b145eb691189c63a78d201dc4fdb1293ef0c03" - integrity sha1-0LFF62kRicY6eNIB3E/bEpPvDAM= - normalize-url@^4.1.0: version "4.5.0" resolved "https://registry.yarnpkg.com/normalize-url/-/normalize-url-4.5.0.tgz#453354087e6ca96957bd8f5baf753f5982142129" @@ -10056,10 +10061,10 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== -picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.2.3: - version "2.3.0" - resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" - integrity sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw== +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== pify@^2.0.0: version "2.3.0" @@ -10176,15 +10181,15 @@ postcss-safe-parser@^6.0.0: resolved "https://registry.yarnpkg.com/postcss-safe-parser/-/postcss-safe-parser-6.0.0.tgz#bb4c29894171a94bc5c996b9a30317ef402adaa1" integrity sha512-FARHN8pwH+WiS2OPCxJI8FuRJpTVnn6ZNFiqAM2aeW2LwTHWWmWgIyKC6cUo0L8aeKiF/14MNvnpls6R2PBeMQ== -postcss-scss@4.0.3: - version "4.0.3" - resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-4.0.3.tgz#36c23c19a804274e722e83a54d20b838ab4767ac" - integrity sha512-j4KxzWovfdHsyxwl1BxkUal/O4uirvHgdzMKS1aWJBAV0qh2qj5qAZqpeBfVUYGWv+4iK9Az7SPyZ4fyNju1uA== +postcss-scss@4.0.4: + version "4.0.4" + resolved "https://registry.yarnpkg.com/postcss-scss/-/postcss-scss-4.0.4.tgz#aa8f60e19ee18259bc193db9e4b96edfce3f3b1f" + integrity sha512-aBBbVyzA8b3hUL0MGrpydxxXKXFZc5Eqva0Q3V9qsBOLEMsjb6w49WfpsoWzpEgcqJGW4t7Rio8WXVU9Gd8vWg== -postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9: - version "6.0.9" - resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.9.tgz#ee71c3b9ff63d9cd130838876c13a2ec1a992b2f" - integrity sha512-UO3SgnZOVTwu4kyLR22UQ1xZh086RyNZppb7lLAKBFK8a32ttG5i87Y/P3+2bRSjZNyJ1B7hfFNo273tKe9YxQ== +postcss-selector-parser@^6.0.0, postcss-selector-parser@^6.0.10, postcss-selector-parser@^6.0.2, postcss-selector-parser@^6.0.6, postcss-selector-parser@^6.0.9: + version "6.0.10" + resolved "https://registry.yarnpkg.com/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz#79b61e2c0d1bfc2602d549e11d0876256f8df88d" + integrity sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w== dependencies: cssesc "^3.0.0" util-deprecate "^1.0.2" @@ -10199,14 +10204,14 @@ postcss-value-parser@^4.1.0, postcss-value-parser@^4.2.0: resolved "https://registry.yarnpkg.com/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz#723c09920836ba6d3e5af019f92bc0971c02e514" integrity sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ== -postcss@8.4.5, postcss@^8.2.1, postcss@^8.4.5: - version "8.4.5" - resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.5.tgz#bae665764dfd4c6fcc24dc0fdf7e7aa00cc77f95" - integrity sha512-jBDboWM8qpaqwkMwItqTQTiFikhs/67OYVvblFFTM7MrZjt6yMKd6r2kgXizEbTTljacm4NldIlZnhbjr84QYg== +postcss@8.4.14, postcss@^8.2.1, postcss@^8.4.14: + version "8.4.14" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.14.tgz#ee9274d5622b4858c1007a74d76e42e56fd21caf" + integrity sha512-E398TUmfAYFPBSdzgeieK2Y1+1cpdxJx8yXbK/m57nRhKSmk1GB2tO4lbLBtlkfPQTDKfe4Xqv1ASWPpayPEig== dependencies: - nanoid "^3.1.30" + nanoid "^3.3.4" picocolors "^1.0.0" - source-map-js "^1.0.1" + source-map-js "^1.0.2" postcss@^7.0.14, postcss@^7.0.5, postcss@^7.0.6: version "7.0.39" @@ -11406,10 +11411,10 @@ sigmund@^1.0.1: resolved "https://registry.yarnpkg.com/sigmund/-/sigmund-1.0.1.tgz#3ff21f198cad2175f9f3b781853fd94d0d19b590" integrity sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA= -signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3: - version "3.0.6" - resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.6.tgz#24e630c4b0f03fea446a2bd299e62b4a6ca8d0af" - integrity sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ== +signal-exit@^3.0.0, signal-exit@^3.0.2, signal-exit@^3.0.3, signal-exit@^3.0.7: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== sirv@^1.0.7: version "1.0.11" @@ -11502,7 +11507,7 @@ source-list-map@^2.0.0: resolved "https://registry.yarnpkg.com/source-list-map/-/source-list-map-2.0.0.tgz#aaa47403f7b245a92fbc97ea08f250d6087ed085" integrity sha512-I2UmuJSRr/T8jisiROLU3A3ltr+swpniSmNPI4Ml3ZCX6tVnDsuZzK7F2hl5jTqbZBWCEKlj5HRQiPExXLgE8A== -"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.1: +"source-map-js@>=0.6.2 <2.0.0", source-map-js@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== @@ -11600,11 +11605,6 @@ spdy@^4.0.2: select-hose "^2.0.0" spdy-transport "^3.0.0" -specificity@^0.4.1: - version "0.4.1" - resolved "https://registry.yarnpkg.com/specificity/-/specificity-0.4.1.tgz#aab5e645012db08ba182e151165738d00887b019" - integrity sha512-1klA3Gi5PD1Wv9Q0wUoOQN1IWAuPu0D1U03ThXTr0cJ20+/iq2tHSDnK7Kk/0LXJ1ztUB2/1Os0wKmfyNgUQfg== - split-string@^3.0.1, split-string@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/split-string/-/split-string-3.1.0.tgz#7cb09dda3a86585705c64b39a6466038682e8fe2" @@ -11846,10 +11846,10 @@ stylelint-declaration-strict-value@1.8.0: css-values "^0.1.0" shortcss "^0.1.3" -stylelint-scss@4.1.0: - version "4.1.0" - resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-4.1.0.tgz#39b808696f8152081163d970449257ff80b5c041" - integrity sha512-BNYTo7MMamhFOlcaAWp2dMpjg6hPyM/FFqfDIYzmYVLMmQJqc8lWRIiTqP4UX5bresj9Vo0dKC6odSh43VP2NA== +stylelint-scss@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/stylelint-scss/-/stylelint-scss-4.2.0.tgz#e25fd390ee38a7e89fcfaec2a8f9dce2ec6ddee8" + integrity sha512-HHHMVKJJ5RM9pPIbgJ/XA67h9H0407G68Rm69H4fzFbFkyDMcTV1Byep3qdze5+fJ3c0U7mJrbj6S0Fg072uZA== dependencies: lodash "^4.17.21" postcss-media-query-parser "^0.2.3" @@ -11857,15 +11857,17 @@ stylelint-scss@4.1.0: postcss-selector-parser "^6.0.6" postcss-value-parser "^4.1.0" -stylelint@^14.3.0: - version "14.3.0" - resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-14.3.0.tgz#26b62730da7b3dc320021fc469d80048d7b77ebe" - integrity sha512-PZXSwtJe4f4qBPWBwAbHL0M0Qjrv8iHN+cLpUNsffaVMS3YzpDDRI73+2lsqLAYfQEzxRwpll6BDKImREbpHWA== +stylelint@^14.9.1: + version "14.9.1" + resolved "https://registry.yarnpkg.com/stylelint/-/stylelint-14.9.1.tgz#6494ed38f148b1e75b402d678a3b6a8aae86dfda" + integrity sha512-RdAkJdPiLqHawCSnu21nE27MjNXaVd4WcOHA4vK5GtIGjScfhNnaOuWR2wWdfKFAvcWQPOYe311iveiVKSmwsA== dependencies: + "@csstools/selector-specificity" "^2.0.1" balanced-match "^2.0.0" colord "^2.9.2" cosmiconfig "^7.0.1" - debug "^4.3.3" + css-functions-list "^3.1.0" + debug "^4.3.4" execall "^2.0.0" fast-glob "^3.2.11" fastest-levenshtein "^1.0.12" @@ -11874,26 +11876,24 @@ stylelint@^14.3.0: global-modules "^2.0.0" globby "^11.1.0" globjoin "^0.1.4" - html-tags "^3.1.0" + html-tags "^3.2.0" ignore "^5.2.0" import-lazy "^4.0.0" imurmurhash "^0.1.4" is-plain-object "^5.0.0" - known-css-properties "^0.24.0" + known-css-properties "^0.25.0" mathml-tag-names "^2.1.3" meow "^9.0.0" - micromatch "^4.0.4" + micromatch "^4.0.5" normalize-path "^3.0.0" - normalize-selector "^0.2.0" picocolors "^1.0.0" - postcss "^8.4.5" + postcss "^8.4.14" postcss-media-query-parser "^0.2.3" postcss-resolve-nested-selector "^0.1.1" postcss-safe-parser "^6.0.0" - postcss-selector-parser "^6.0.9" + postcss-selector-parser "^6.0.10" postcss-value-parser "^4.2.0" resolve-from "^5.0.0" - specificity "^0.4.1" string-width "^4.2.3" strip-ansi "^6.0.1" style-search "^0.1.0" @@ -11901,7 +11901,7 @@ stylelint@^14.3.0: svg-tags "^1.0.0" table "^6.8.0" v8-compile-cache "^2.3.0" - write-file-atomic "^4.0.0" + write-file-atomic "^4.0.1" stylis@^4.0.10: version "4.0.10" @@ -12382,11 +12382,6 @@ typedarray-to-buffer@^3.1.5: dependencies: is-typedarray "^1.0.0" -typedarray-to-buffer@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-4.0.0.tgz#cdd2933c61dd3f5f02eda5d012d441f95bfeb50a" - integrity sha512-6dOYeZfS3O9RtRD1caom0sMxgK59b27+IwoNy8RDPsmslSGOyU+mpTamlaIW7aNKi90ZQZ9DFaZL3YRoiSCULQ== - typedarray@^0.0.6: version "0.0.6" resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" @@ -13311,15 +13306,13 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" -write-file-atomic@^4.0.0: - version "4.0.0" - resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.0.tgz#0eff5dc687d3e22535ca3fca8558124645a4b053" - integrity sha512-JhcWoKffJNF7ivO9yflBhc7tn3wKnokMUfWpBriM9yCXj4ePQnRPcWglBkkg1AHC8nsW/EfxwwhqsLtOy59djA== +write-file-atomic@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-4.0.1.tgz#9faa33a964c1c85ff6f849b80b42a88c2c537c8f" + integrity sha512-nSKUxgAbyioruk6hU87QzVbY279oYT6uiwgDoujth2ju4mJ+TZau7SQBhtbTmUyuNYTuXnSyRn66FV0+eCgcrQ== dependencies: imurmurhash "^0.1.4" - is-typedarray "^1.0.0" - signal-exit "^3.0.2" - typedarray-to-buffer "^4.0.0" + signal-exit "^3.0.7" "ws@^5.2.0 || ^6.0.0 || ^7.0.0", ws@^7.2.3, ws@^7.3.1: version "7.5.5"