diff options
author | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-06 21:09:02 +0300 |
---|---|---|
committer | GitLab Bot <gitlab-bot@gitlab.com> | 2022-06-06 21:09:02 +0300 |
commit | 2d181003830956f5e690cce74be50bb4d96048f8 (patch) | |
tree | cd72c53f6cb3753fc1bd28521e89af66c420f08a | |
parent | c79da5142f46e6e9187f75c329e2c81a8568c581 (diff) |
Add latest changes from gitlab-org/gitlab@master
94 files changed, 977 insertions, 356 deletions
@@ -182,8 +182,8 @@ gem 'diff_match_patch', '~> 0.1.0' # Application server gem 'rack', '~> 2.2.3' -# https://github.com/sharpstone/rack-timeout/blob/master/README.md#rails-apps-manually -gem 'rack-timeout', '~> 0.5.1', require: 'rack/timeout/base' +# https://github.com/zombocom/rack-timeout/blob/master/README.md#rails-apps-manually +gem 'rack-timeout', '~> 0.6.0', require: 'rack/timeout/base' group :puma do gem 'puma', '~> 5.6.2', require: false diff --git a/Gemfile.lock b/Gemfile.lock index b4cd81f2720..d7d9a013f82 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -979,7 +979,7 @@ GEM rack rack-test (1.1.0) rack (>= 1.0, < 3) - rack-timeout (0.5.2) + rack-timeout (0.6.0) rails (6.1.4.7) actioncable (= 6.1.4.7) actionmailbox (= 6.1.4.7) @@ -1613,7 +1613,7 @@ DEPENDENCIES rack-cors (~> 1.0.6) rack-oauth2 (~> 1.16.0) rack-proxy (~> 0.7.2) - rack-timeout (~> 0.5.1) + rack-timeout (~> 0.6.0) rails (~> 6.1.4.7) rails-controller-testing rails-i18n (~> 6.0) diff --git a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue index 7c11b895323..70627ec06ca 100644 --- a/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue +++ b/app/assets/javascripts/vue_shared/components/sidebar/labels_select_vue/dropdown_contents_labels_view.vue @@ -166,7 +166,7 @@ export default { <span class="flex-grow-1">{{ labelsListTitle }}</span> <gl-button :aria-label="__('Close')" - variant="link" + category="tertiary" size="small" class="dropdown-header-button gl-p-0!" icon="close" diff --git a/app/components/pajamas/banner_component.html.haml b/app/components/pajamas/banner_component.html.haml new file mode 100644 index 00000000000..4fa2ed09cd3 --- /dev/null +++ b/app/components/pajamas/banner_component.html.haml @@ -0,0 +1,23 @@ +%section.gl-banner{ @banner_options, class: banner_class } + - if illustration? + .gl-banner-illustration + = illustration + - elsif @svg_path.present? + .gl-banner-illustration + = image_tag @svg_path, alt: "" + + .gl-banner-content + %h1.gl-banner-title= title + + = content + + - if primary_action? + = primary_action + - else + = link_to @button_text, @button_link, { **@button_options, class: 'btn btn-md btn-confirm gl-button js-close-callout' } + + - actions.each do |action| + = action + + %button.gl-button.gl-banner-close.btn-sm.btn-icon.js-close{ @close_options, class: close_class, type: 'button' } + = sprite_icon('close', size: 16, css_class: 'dismiss-icon') diff --git a/app/components/pajamas/banner_component.rb b/app/components/pajamas/banner_component.rb new file mode 100644 index 00000000000..9b6343b47c9 --- /dev/null +++ b/app/components/pajamas/banner_component.rb @@ -0,0 +1,61 @@ +# frozen_string_literal: true + +module Pajamas + class BannerComponent < Pajamas::Component + # @param [String] button_text + # @param [String] button_link + # @param [Boolean] embedded + # @param [Symbol] variant + # @param [String] svg_path + # @param [Hash] banner_options + # @param [Hash] button_options + # @param [Hash] close_options + def initialize( + button_text: 'OK', + button_link: '#', + embedded: false, + variant: :promotion, + svg_path: nil, + banner_options: {}, + button_options: {}, + close_options: {} + ) + @button_text = button_text + @button_link = button_link + @embedded = embedded + @variant = variant.to_sym + @svg_path = svg_path.to_s + @banner_options = banner_options + @button_options = button_options + @close_options = close_options + end + + private + + def banner_class + classes = [] + classes.push('gl-border-none') if @embedded + classes.push('gl-banner-introduction') if introduction? + classes.join(' ') + end + + def close_class + if introduction? + 'btn-confirm btn-confirm-tertiary' + else + 'btn-default btn-default-tertiary' + end + end + + delegate :sprite_icon, to: :helpers + + renders_one :title + renders_one :illustration + renders_one :primary_action + renders_many :actions + + def introduction? + @variant == :introduction + end + end +end diff --git a/app/controllers/autocomplete_controller.rb b/app/controllers/autocomplete_controller.rb index f84d2ed320d..32d1ddf920e 100644 --- a/app/controllers/autocomplete_controller.rb +++ b/app/controllers/autocomplete_controller.rb @@ -62,7 +62,9 @@ class AutocompleteController < ApplicationController def deploy_keys_with_owners deploy_keys = DeployKey.with_write_access_for_project(project) - render json: DeployKeySerializer.new.represent(deploy_keys, { with_owner: true, user: current_user }) + render json: DeployKeys::BasicDeployKeySerializer.new.represent( + deploy_keys, { with_owner: true, user: current_user } + ) end private diff --git a/app/controllers/mailgun/webhooks_controller.rb b/app/controllers/mailgun/webhooks_controller.rb index faeda99769f..f7cb3eaa8ee 100644 --- a/app/controllers/mailgun/webhooks_controller.rb +++ b/app/controllers/mailgun/webhooks_controller.rb @@ -13,13 +13,13 @@ module Mailgun feature_category :team_planning WEBHOOK_PROCESSORS = [ - ::Members::Mailgun::ProcessWebhookService + Gitlab::Mailgun::WebhookProcessors::FailureLogger, + Gitlab::Mailgun::WebhookProcessors::MemberInvites ].freeze def process_webhook WEBHOOK_PROCESSORS.each do |processor_class| - processor = processor_class.new(params['event-data'] || {}) - processor.execute if processor.should_process? + processor_class.new(params['event-data']).execute end head :ok diff --git a/app/events/pages/page_deleted_event.rb b/app/events/pages/page_deleted_event.rb new file mode 100644 index 00000000000..b1ea14a6ec5 --- /dev/null +++ b/app/events/pages/page_deleted_event.rb @@ -0,0 +1,16 @@ +# frozen_string_literal: true + +module Pages + class PageDeletedEvent < ::Gitlab::EventStore::Event + def schema + { + 'type' => 'object', + 'properties' => { + 'project_id' => { 'type' => 'integer' }, + 'namespace_id' => { 'type' => 'integer' } + }, + 'required' => %w[project_id namespace_id] + } + end + end +end diff --git a/app/graphql/types/ci/pipeline_merge_request_event_type_enum.rb b/app/graphql/types/ci/pipeline_merge_request_event_type_enum.rb new file mode 100644 index 00000000000..a1236b8f2c1 --- /dev/null +++ b/app/graphql/types/ci/pipeline_merge_request_event_type_enum.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Types + module Ci + class PipelineMergeRequestEventTypeEnum < BaseEnum + graphql_name 'PipelineMergeRequestEventType' + description 'Event type of the pipeline associated with a merge request' + + value 'MERGED_RESULT', + 'Pipeline run on the changes from the source branch combined with the target branch.', + value: :merged_result + value 'DETACHED', + 'Pipeline run on the changes in the merge request source branch.', + value: :detached + end + end +end + +Types::Ci::PipelineMergeRequestEventTypeEnum.prepend_mod diff --git a/app/graphql/types/ci/pipeline_type.rb b/app/graphql/types/ci/pipeline_type.rb index 81afc7f0f42..60418fec6c5 100644 --- a/app/graphql/types/ci/pipeline_type.rb +++ b/app/graphql/types/ci/pipeline_type.rb @@ -175,6 +175,9 @@ module Types field :warning_messages, [Types::Ci::PipelineMessageType], null: true, description: 'Pipeline warning messages.' + field :merge_request_event_type, Types::Ci::PipelineMergeRequestEventTypeEnum, null: true, + description: "Event type of the pipeline associated with a merge request." + def detailed_status object.detailed_status(current_user) end diff --git a/app/presenters/projects/settings/deploy_keys_presenter.rb b/app/presenters/projects/settings/deploy_keys_presenter.rb index e3323b75188..b760786aa4c 100644 --- a/app/presenters/projects/settings/deploy_keys_presenter.rb +++ b/app/presenters/projects/settings/deploy_keys_presenter.rb @@ -58,7 +58,7 @@ module Projects end def as_json - serializer = DeployKeySerializer.new # rubocop: disable CodeReuse/Serializer + serializer = DeployKeys::DeployKeySerializer.new # rubocop: disable CodeReuse/Serializer opts = { user: current_user, project: project, readable_project_ids: readable_project_ids } { diff --git a/app/serializers/deploy_key_entity.rb b/app/serializers/deploy_key_entity.rb deleted file mode 100644 index 486189b84ca..00000000000 --- a/app/serializers/deploy_key_entity.rb +++ /dev/null @@ -1,39 +0,0 @@ -# frozen_string_literal: true - -class DeployKeyEntity < Grape::Entity - expose :id - expose :user_id - expose :title - expose :fingerprint - expose :fingerprint_sha256 - expose :destroyed_when_orphaned?, as: :destroyed_when_orphaned - expose :almost_orphaned?, as: :almost_orphaned - expose :created_at - expose :updated_at - expose :deploy_keys_projects, using: DeployKeysProjectEntity do |deploy_key| - deploy_key.deploy_keys_projects.select do |deploy_key_project| - !deploy_key_project.project&.pending_delete? && (allowed_to_read_project?(deploy_key_project.project) || options[:user].admin?) - end - end - expose :can_edit - expose :user, as: :owner, using: ::API::Entities::UserBasic, if: -> (_, opts) { can_read_owner?(opts) } - - private - - def can_edit - Ability.allowed?(options[:user], :update_deploy_key, object) || - Ability.allowed?(options[:user], :update_deploy_keys_project, object.deploy_keys_project_for(options[:project])) - end - - def can_read_owner?(opts) - opts[:with_owner] && Ability.allowed?(options[:user], :read_user, object.user) - end - - def allowed_to_read_project?(project) - if options[:readable_project_ids] - options[:readable_project_ids].include?(project.id) - else - Ability.allowed?(options[:user], :read_project, project) - end - end -end diff --git a/app/serializers/deploy_key_serializer.rb b/app/serializers/deploy_key_serializer.rb deleted file mode 100644 index a1cd98b631b..00000000000 --- a/app/serializers/deploy_key_serializer.rb +++ /dev/null @@ -1,5 +0,0 @@ -# frozen_string_literal: true - -class DeployKeySerializer < BaseSerializer - entity DeployKeyEntity -end diff --git a/app/serializers/deploy_keys/basic_deploy_key_entity.rb b/app/serializers/deploy_keys/basic_deploy_key_entity.rb new file mode 100644 index 00000000000..9184bc5f0ce --- /dev/null +++ b/app/serializers/deploy_keys/basic_deploy_key_entity.rb @@ -0,0 +1,28 @@ +# frozen_string_literal: true + +module DeployKeys + class BasicDeployKeyEntity < Grape::Entity + expose :id + expose :user_id + expose :title + expose :fingerprint + expose :fingerprint_sha256 + expose :destroyed_when_orphaned?, as: :destroyed_when_orphaned + expose :almost_orphaned?, as: :almost_orphaned + expose :created_at + expose :updated_at + expose :can_edit + expose :user, as: :owner, using: ::API::Entities::UserBasic, if: -> (_, opts) { can_read_owner?(opts) } + + private + + def can_edit + Ability.allowed?(options[:user], :update_deploy_key, object) || + Ability.allowed?(options[:user], :update_deploy_keys_project, object.deploy_keys_project_for(options[:project])) + end + + def can_read_owner?(opts) + opts[:with_owner] && Ability.allowed?(options[:user], :read_user, object.user) + end + end +end diff --git a/app/serializers/deploy_keys/basic_deploy_key_serializer.rb b/app/serializers/deploy_keys/basic_deploy_key_serializer.rb new file mode 100644 index 00000000000..699f3baac78 --- /dev/null +++ b/app/serializers/deploy_keys/basic_deploy_key_serializer.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module DeployKeys + class BasicDeployKeySerializer < BaseSerializer + entity BasicDeployKeyEntity + end +end diff --git a/app/serializers/deploy_keys/deploy_key_entity.rb b/app/serializers/deploy_keys/deploy_key_entity.rb new file mode 100644 index 00000000000..79f386d1529 --- /dev/null +++ b/app/serializers/deploy_keys/deploy_key_entity.rb @@ -0,0 +1,22 @@ +# frozen_string_literal: true + +module DeployKeys + class DeployKeyEntity < BasicDeployKeyEntity + expose :deploy_keys_projects, using: DeployKeysProjectEntity do |deploy_key| + deploy_key.deploy_keys_projects.select do |deploy_key_project| + !deploy_key_project.project&.pending_delete? && + (allowed_to_read_project?(deploy_key_project.project) || options[:user].can_admin_all_resources?) + end + end + + private + + def allowed_to_read_project?(project) + if options[:readable_project_ids] + options[:readable_project_ids].include?(project.id) + else + Ability.allowed?(options[:user], :read_project, project) + end + end + end +end diff --git a/app/serializers/deploy_keys/deploy_key_serializer.rb b/app/serializers/deploy_keys/deploy_key_serializer.rb new file mode 100644 index 00000000000..b00ef65696f --- /dev/null +++ b/app/serializers/deploy_keys/deploy_key_serializer.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +module DeployKeys + class DeployKeySerializer < BaseSerializer + entity DeployKeyEntity + end +end diff --git a/app/services/members/mailgun/process_webhook_service.rb b/app/services/members/mailgun/process_webhook_service.rb deleted file mode 100644 index c0a9c2d5290..00000000000 --- a/app/services/members/mailgun/process_webhook_service.rb +++ /dev/null @@ -1,43 +0,0 @@ -# frozen_string_literal: true - -module Members - module Mailgun - class ProcessWebhookService - ProcessWebhookServiceError = Class.new(StandardError) - - def initialize(payload) - @payload = payload - end - - def execute - @member = Member.find_by_invite_token(invite_token) - update_member_and_log if member - rescue ProcessWebhookServiceError => e - Gitlab::ErrorTracking.track_exception(e) - end - - def should_process? - payload['event'] == 'failed' && payload['severity'] == 'permanent' && payload['tags']&.include?(::Members::Mailgun::INVITE_EMAIL_TAG) - end - - private - - attr_reader :payload, :member - - def update_member_and_log - log_update_event if member.update(invite_email_success: false) - end - - def log_update_event - Gitlab::AppLogger.info "UPDATED MEMBER INVITE_EMAIL_SUCCESS: member_id: #{member.id}" - end - - def invite_token - # may want to validate schema in some way using ::JSONSchemer.schema(SCHEMA_PATH).valid?(message) if this - # gets more complex - payload.dig('user-variables', ::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY) || - raise(ProcessWebhookServiceError, "Failed to receive #{::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY} in user-variables: #{payload}") - end - end - end -end diff --git a/app/services/pages/delete_service.rb b/app/services/pages/delete_service.rb index 8d33e6c1000..95e99daeb6c 100644 --- a/app/services/pages/delete_service.rb +++ b/app/services/pages/delete_service.rb @@ -11,7 +11,20 @@ module Pages # > The default strategy is :nullify which sets the foreign keys to NULL. PagesDomain.for_project(project).delete_all + publish_deleted_event + DestroyPagesDeploymentsWorker.perform_async(project.id) end + + private + + def publish_deleted_event + event = Pages::PageDeletedEvent.new(data: { + project_id: project.id, + namespace_id: project.namespace_id + }) + + Gitlab::EventStore.publish(event) + end end end diff --git a/app/views/shared/_auto_devops_callout.html.haml b/app/views/shared/_auto_devops_callout.html.haml index d6d84b2181f..c2b941c6106 100644 --- a/app/views/shared/_auto_devops_callout.html.haml +++ b/app/views/shared/_auto_devops_callout.html.haml @@ -1,15 +1,13 @@ -%section.js-autodevops-banner.gl-banner{ data: { uid: 'auto_devops_settings_dismissed', project_path: project_path(@project) } } - .gl-banner-illustration - = image_tag('illustrations/autodevops.svg') += render Pajamas::BannerComponent.new(button_text: s_('AutoDevOps|Enable in settings'), + button_link: project_settings_ci_cd_path(@project, anchor: 'autodevops-settings'), + svg_path: 'illustrations/autodevops.svg', + banner_options: { class: 'js-autodevops-banner', data: { uid: 'auto_devops_settings_dismissed', project_path: project_path(@project) } }, + close_options: { 'aria-label' => s_('AutoDevOps|Dismiss Auto DevOps box'), class: 'js-close-callout' }) do |c| + - c.title do + = s_('AutoDevOps|Auto DevOps') - .gl-banner-content - %h1.gl-banner-title= s_('AutoDevOps|Auto DevOps') - %p= s_('AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration.') - %p - - link = link_to(s_('AutoDevOps|Auto DevOps documentation'), help_page_path('topics/autodevops/index.md'), target: '_blank', rel: 'noopener noreferrer') - = s_('AutoDevOps|Learn more in the %{link_to_documentation}').html_safe % { link_to_documentation: link } - = link_to s_('AutoDevOps|Enable in settings'), project_settings_ci_cd_path(@project, anchor: 'autodevops-settings'), class: 'btn btn-md btn-default gl-button js-close-callout' + %p= s_('AutoDevOps|It will automatically build, test, and deploy your application based on a predefined CI/CD configuration.') - %button.gl-banner-close.close.js-close-callout{ type: 'button', - 'aria-label' => s_('AutoDevOps|Dismiss Auto DevOps box') } - = sprite_icon('close', size: 16, css_class: 'dismiss-icon') + %p + - link = link_to(s_('AutoDevOps|Auto DevOps documentation'), help_page_path('topics/autodevops/index.md'), target: '_blank', rel: 'noopener noreferrer') + = s_('AutoDevOps|Learn more in the %{link_to_documentation}').html_safe % { link_to_documentation: link } diff --git a/app/workers/projects/inactive_projects_deletion_cron_worker.rb b/app/workers/projects/inactive_projects_deletion_cron_worker.rb index 312d161cd9b..a280c9203d6 100644 --- a/app/workers/projects/inactive_projects_deletion_cron_worker.rb +++ b/app/workers/projects/inactive_projects_deletion_cron_worker.rb @@ -34,6 +34,11 @@ module Projects inactive_projects = batch.inactive.without_deleted inactive_projects.each do |project| + if over_time? + save_last_processed_project_id(project.id) + raise TimeoutError + end + next unless Feature.enabled?(:inactive_projects_deletion, project.root_namespace) with_context(project: project, user: admin_user) do @@ -46,11 +51,6 @@ module Projects delete_project(project, admin_user) end end - - if over_time? - save_last_processed_project_id(project.id) - raise TimeoutError - end end end reset_last_processed_project_id diff --git a/config/application.rb b/config/application.rb index 1dd6fc04b16..10d0e175afd 100644 --- a/config/application.rb +++ b/config/application.rb @@ -323,6 +323,8 @@ module Gitlab # Import gitlab-svgs directly from vendored directory config.assets.paths << "#{config.root}/node_modules/@gitlab/svgs/dist" + config.assets.paths << "#{config.root}/node_modules/@jihulab/svgs/dist" if Gitlab.jh? + config.assets.precompile << "illustrations/jh/*.svg" if Gitlab.jh? config.assets.precompile << "icons.svg" config.assets.precompile << "icons.json" config.assets.precompile << "illustrations/*.svg" diff --git a/config/initializers/rack_timeout.rb b/config/initializers/rack_timeout.rb index d5027cae08d..c2f2f3e093c 100644 --- a/config/initializers/rack_timeout.rb +++ b/config/initializers/rack_timeout.rb @@ -4,7 +4,7 @@ # requests, to make sure that server is not paralyzed by long-running # or stuck queries, we add a request timeout which terminates the # request after 60 seconds. This may be dangerous in some situations -# (https://github.com/heroku/rack-timeout/blob/master/doc/exceptions.md) +# (https://github.com/zombocom/rack-timeout/blob/master/doc/exceptions.md) # and it's used only as the last resort. In such case this termination is # logged and we should fix the potential timeout issue in the code itself. diff --git a/doc/.vale/gitlab/Uppercase.yml b/doc/.vale/gitlab/Uppercase.yml index 642693e8230..c2c565bacac 100644 --- a/doc/.vale/gitlab/Uppercase.yml +++ b/doc/.vale/gitlab/Uppercase.yml @@ -26,6 +26,7 @@ exceptions: - BSD - CAS - CDN + - CGI - CIDR - CLI - CNA @@ -35,6 +36,7 @@ exceptions: - CPU - CRIME - CRM + - CRUD - CSRF - CSS - CSV @@ -145,6 +147,7 @@ exceptions: - PNG - POSIX - POST + - PROXY - PUT - RAID - RAM @@ -169,6 +172,7 @@ exceptions: - SATA - SBOM - SCIM + - SCM - SCP - SCSS - SDK @@ -176,6 +180,7 @@ exceptions: - SEO - SFTP - SHA + - SKI - SLA - SLI - SLO diff --git a/doc/administration/geo/disaster_recovery/index.md b/doc/administration/geo/disaster_recovery/index.md index 08559e7c8b9..48767573db8 100644 --- a/doc/administration/geo/disaster_recovery/index.md +++ b/doc/administration/geo/disaster_recovery/index.md @@ -335,7 +335,7 @@ a **secondary** with only a single node. Instead, you must do this manually. #### Promoting a **secondary** site with an external PostgreSQL database running GitLab 14.5 and later -The `gitlab-ctl geo promote` command can be used in conjunction with an external PostgreSQL database. +The `gitlab-ctl geo promote` command can be used in conjunction with an external PostgreSQL database. In this case, you must first manually promote the replica database associated with the **secondary** site: diff --git a/doc/administration/geo/replication/version_specific_upgrades.md b/doc/administration/geo/replication/version_specific_upgrades.md index 4e6aeddfc2e..f0925bdf87e 100644 --- a/doc/administration/geo/replication/version_specific_upgrades.md +++ b/doc/administration/geo/replication/version_specific_upgrades.md @@ -12,7 +12,7 @@ for upgrading Geo sites. ## Upgrading to 14.9 -**DO NOT** upgrade to GitLab 14.9.0. Instead, use 14.9.1 or later. +**Do not** upgrade to GitLab 14.9.0. Instead, use 14.9.1 or later. We've discovered an issue with Geo's CI verification feature that may [cause job traces to be lost](https://gitlab.com/gitlab-com/gl-infra/production/-/issues/6664). This issue was fixed in [the GitLab 14.9.1 patch release](https://about.gitlab.com/releases/2022/03/23/gitlab-14-9-1-released/). diff --git a/doc/administration/operations/extra_sidekiq_routing.md b/doc/administration/operations/extra_sidekiq_routing.md index da25fc8b0a1..2a14fa1d312 100644 --- a/doc/administration/operations/extra_sidekiq_routing.md +++ b/doc/administration/operations/extra_sidekiq_routing.md @@ -136,15 +136,15 @@ GitLab Enterprise Edition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee `queue_selector` supports the following operators, listed from highest to lowest precedence: -- `|` - the logical OR operator. For example, `query_a|query_b` (where `query_a` +- `|` - the logical `OR` operator. For example, `query_a|query_b` (where `query_a` and `query_b` are queries made up of the other operators here) will include queues that match either query. -- `&` - the logical AND operator. For example, `query_a&query_b` (where +- `&` - the logical `AND` operator. For example, `query_a&query_b` (where `query_a` and `query_b` are queries made up of the other operators here) will only include queues that match both queries. -- `!=` - the NOT IN operator. For example, `feature_category!=issue_tracking` +- `!=` - the `NOT IN` operator. For example, `feature_category!=issue_tracking` excludes all queues from the `issue_tracking` feature category. -- `=` - the IN operator. For example, `resource_boundary=cpu` includes all +- `=` - the `IN` operator. For example, `resource_boundary=cpu` includes all queues that are CPU bound. - `,` - the concatenate set operator. For example, `feature_category=continuous_integration,pages` includes all queues from @@ -152,8 +152,8 @@ to lowest precedence: example is also possible using the OR operator, but allows greater brevity, as well as being lower precedence. -The operator precedence for this syntax is fixed: it's not possible to make AND -have higher precedence than OR. +The operator precedence for this syntax is fixed: it's not possible to make `AND` +have higher precedence than `OR`. [In GitLab 12.9](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/26594) and later, as with the standard queue group syntax above, a single `*` as the diff --git a/doc/administration/operations/ssh_certificates.md b/doc/administration/operations/ssh_certificates.md index aa17c08c17c..3141312612e 100644 --- a/doc/administration/operations/ssh_certificates.md +++ b/doc/administration/operations/ssh_certificates.md @@ -53,7 +53,7 @@ the GitLab server itself, but your setup may vary. If the CA is only used for GitLab consider putting this in the `Match User git` section (described below). -The SSH certificates being issued by that CA **MUST** have a "key ID" +The SSH certificates being issued by that CA **must** have a "key ID" corresponding to that user's username on GitLab, for example (some output omitted for brevity): diff --git a/doc/administration/package_information/index.md b/doc/administration/package_information/index.md index a4265af13fd..746961e8613 100644 --- a/doc/administration/package_information/index.md +++ b/doc/administration/package_information/index.md @@ -87,7 +87,7 @@ Depending on the init system, this `WARNING` can be one of: /sbin/init: unrecognized option '--version' ``` -when the underlying init system *IS NOT* upstart. +when the underlying init system *is not* upstart. ```plaintext -.mount loaded active mounted / diff --git a/doc/administration/packages/container_registry.md b/doc/administration/packages/container_registry.md index e106ff2bebd..2fa3eea54bd 100644 --- a/doc/administration/packages/container_registry.md +++ b/doc/administration/packages/container_registry.md @@ -1151,7 +1151,7 @@ for GitLab to run separately from Registry: - `gitlab_rails['registry_enabled']`, must be set to `true`. This setting signals to GitLab that it should allow Registry API requests. - `gitlab_rails['registry_api_url']`, default [set programmatically](https://gitlab.com/gitlab-org/omnibus-gitlab/blob/10-3-stable/files/gitlab-cookbooks/gitlab/libraries/registry.rb#L52). This is the Registry URL used internally that users do not need to interact with, `registry['registry_http_addr']` with scheme. -- `gitlab_rails['registry_host']`, eg. `registry.gitlab.example`. Registry endpoint without the scheme, the address that gets shown to the end user. +- `gitlab_rails['registry_host']`, for example, `registry.gitlab.example`. Registry endpoint without the scheme, the address that gets shown to the end user. - `gitlab_rails['registry_port']`. Registry endpoint port, visible to the end user. - `gitlab_rails['registry_issuer']` must match the issuer in the Registry configuration. - `gitlab_rails['registry_key_path']`, path to the key that matches the certificate on the diff --git a/doc/administration/postgresql/database_load_balancing.md b/doc/administration/postgresql/database_load_balancing.md index 0b6e00902e9..b03abf9881c 100644 --- a/doc/administration/postgresql/database_load_balancing.md +++ b/doc/administration/postgresql/database_load_balancing.md @@ -125,7 +125,7 @@ record. For example: |----------------------|---------------------------------------------------------------------------------------------------|-----------| | `nameserver` | The nameserver to use for looking up the DNS record. | localhost | | `record` | The record to look up. This option is required for service discovery to work. | | -| `record_type` | Optional record type to look up, this can be either `A` or `SRV` (GitLab 12.3 and later) | `A` | +| `record_type` | Optional record type to look up, this can be either `A` or `SRV` (GitLab 12.3 and later) | `A` | | `port` | The port of the nameserver. | 8600 | | `interval` | The minimum time in seconds between checking the DNS record. | 60 | | `disconnect_timeout` | The time in seconds after which an old connection is closed, after the list of hosts was updated. | 120 | @@ -135,7 +135,7 @@ If `record_type` is set to `SRV`, then GitLab continues to use round-robin algor and ignores the `weight` and `priority` in the record. Since `SRV` records usually return hostnames instead of IPs, GitLab needs to look for the IPs of returned hostnames in the additional section of the `SRV` response. If no IP is found for a hostname, GitLab -needs to query the configured `nameserver` for ANY record for each such hostname looking for `A` or `AAAA` +needs to query the configured `nameserver` for `ANY` record for each such hostname looking for `A` or `AAAA` records, eventually dropping this hostname from rotation if it can't resolve its IP. The `interval` value specifies the _minimum_ time between checks. If the `A` diff --git a/doc/administration/restart_gitlab.md b/doc/administration/restart_gitlab.md index c7357b3ef5b..06b6cbd4271 100644 --- a/doc/administration/restart_gitlab.md +++ b/doc/administration/restart_gitlab.md @@ -97,7 +97,7 @@ It also [restarts GitLab components](#how-to-restart-gitlab) where needed, if any of their configuration files have changed. If you manually edit any files in `/var/opt/gitlab` that are managed by Chef, -running reconfigure reverts the changes AND restarts the services that +running reconfigure reverts the changes and restarts the services that depend on those files. ## Installations from source diff --git a/doc/administration/troubleshooting/debug.md b/doc/administration/troubleshooting/debug.md index 9112004a6c2..81ca1bda5d0 100644 --- a/doc/administration/troubleshooting/debug.md +++ b/doc/administration/troubleshooting/debug.md @@ -174,7 +174,7 @@ hearing back from the Unicorn worker. If the CPU spins to 100% while this in progress, there may be something taking longer than it should. To fix this issue, we first need to figure out what is happening. The -following tips are only recommended if you do NOT mind users being affected by +following tips are only recommended if you do not mind users being affected by downtime. Otherwise skip to the next section. 1. Load the problematic URL diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md index 15e33206450..801bd90634b 100644 --- a/doc/api/graphql/reference/index.md +++ b/doc/api/graphql/reference/index.md @@ -14449,6 +14449,7 @@ Represents a file or directory in the project repository that has been locked. | <a id="pipelineid"></a>`id` | [`ID!`](#id) | ID of the pipeline. | | <a id="pipelineiid"></a>`iid` | [`String!`](#string) | Internal ID of the pipeline. | | <a id="pipelinejobartifacts"></a>`jobArtifacts` | [`[CiJobArtifact!]`](#cijobartifact) | Job artifacts of the pipeline. | +| <a id="pipelinemergerequesteventtype"></a>`mergeRequestEventType` | [`PipelineMergeRequestEventType`](#pipelinemergerequesteventtype) | Event type of the pipeline associated with a merge request. | | <a id="pipelinepath"></a>`path` | [`String`](#string) | Relative path to the pipeline's page. | | <a id="pipelineproject"></a>`project` | [`Project`](#project) | Project the pipeline belongs to. | | <a id="pipelinequeuedduration"></a>`queuedDuration` | [`Duration`](#duration) | How long the pipeline was queued before starting. | @@ -19190,6 +19191,16 @@ Values for sorting package. | <a id="pipelineconfigsourceenumunknown_source"></a>`UNKNOWN_SOURCE` | Unknown source. | | <a id="pipelineconfigsourceenumwebide_source"></a>`WEBIDE_SOURCE` | Webide source. | +### `PipelineMergeRequestEventType` + +Event type of the pipeline associated with a merge request. + +| Value | Description | +| ----- | ----------- | +| <a id="pipelinemergerequesteventtypedetached"></a>`DETACHED` | Pipeline run on the changes in the merge request source branch. | +| <a id="pipelinemergerequesteventtypemerged_result"></a>`MERGED_RESULT` | Pipeline run on the changes from the source branch combined with the target branch. | +| <a id="pipelinemergerequesteventtypemerge_train"></a>`MERGE_TRAIN` | Pipeline ran as part of a merge train. | + ### `PipelineScopeEnum` | Value | Description | diff --git a/doc/api/runners.md b/doc/api/runners.md index 3c3a83b67e3..2b31c1cc064 100644 --- a/doc/api/runners.md +++ b/doc/api/runners.md @@ -370,7 +370,7 @@ GET /runners/:id/jobs | `id` | integer | yes | The ID of a runner | | `status` | string | no | Status of the job; one of: `running`, `success`, `failed`, `canceled` | | `order_by`| string | no | Order jobs by `id`. | -| `sort` | string | no | Sort jobs in `asc` or `desc` order (default: `desc`) | +| `sort` | string | no | Sort jobs in `asc` or `desc` order (default: `desc`). Specify `order_by` as well, including for `id`. | ```shell curl --header "PRIVATE-TOKEN: <your_access_token>" "https://gitlab.example.com/api/v4/runners/1/jobs?status=running" diff --git a/doc/api/templates/gitlab_ci_ymls.md b/doc/api/templates/gitlab_ci_ymls.md index 7f69818da8a..ab97823fe07 100644 --- a/doc/api/templates/gitlab_ci_ymls.md +++ b/doc/api/templates/gitlab_ci_ymls.md @@ -5,9 +5,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w type: reference --- -# GitLab CI YMLs API **(FREE)** +# GitLab CI YAMLs API **(FREE)** -In GitLab, there is an API endpoint available to work with GitLab CI/CD YMLs. For more +In GitLab, there is an API endpoint available to work with GitLab CI/CD YAMLs. For more information on CI/CD pipeline configuration in GitLab, see the [configuration reference documentation](../../ci/yaml/index.md). diff --git a/doc/ci/cloud_deployment/ecs/quick_start_guide.md b/doc/ci/cloud_deployment/ecs/quick_start_guide.md index 574e2a4f638..9837722046b 100644 --- a/doc/ci/cloud_deployment/ecs/quick_start_guide.md +++ b/doc/ci/cloud_deployment/ecs/quick_start_guide.md @@ -181,7 +181,7 @@ Now, the demo application is accessible from the internet. ![Create project](img/view-running-app.png) -In this guide, HTTPS/SSL is **NOT** configured. You can access to the application through HTTP only +In this guide, HTTPS/SSL is **not** configured. You can access to the application through HTTP only (for example, `http://<ec2-ipv4-address>`). ## Setup Continuous Deployment from GitLab diff --git a/doc/ci/enable_or_disable_ci.md b/doc/ci/enable_or_disable_ci.md index 2e514fd0f0a..dac52a4540e 100644 --- a/doc/ci/enable_or_disable_ci.md +++ b/doc/ci/enable_or_disable_ci.md @@ -5,50 +5,46 @@ info: To determine the technical writer assigned to the Stage/Group associated w type: howto --- -# How to enable or disable GitLab CI/CD **(FREE)** - -To use GitLab CI/CD, you need: - -- A valid [`.gitlab-ci.yml`](yaml/index.md) file present at the root directory - of your project. -- A [runner](runners/index.md) ready to run jobs. - -You can read our [quick start guide](quick_start/index.md) to get you started. +# Disabling GitLab CI/CD **(FREE)** +GitLab CI/CD is enabled by default on all new projects. If you use an external CI/CD server like Jenkins or Drone CI, you can disable GitLab CI/CD to avoid conflicts with the commits status API. -GitLab CI/CD is enabled by default on all new projects. You can: +You can disable GitLab CI/CD: -- Disable GitLab CI/CD [under each project's settings](#enable-cicd-in-a-project). -- Set GitLab CI/CD to be [disabled in all new projects on an instance](../administration/cicd.md). +- [For each project](#disable-cicd-in-a-project). +- [For all new projects on an instance](../administration/cicd.md). -If you disable GitLab CI/CD in a project: +These changes do not apply to projects in an +[external integration](../user/project/integrations/index.md#available-integrations). -- The **CI/CD** item in the left sidebar is removed. -- The `/pipelines` and `/jobs` pages are no longer available. -- Existing jobs and pipelines are not deleted. Re-enable CI/CD to access them again. +## Disable CI/CD in a project -The project or instance settings do not enable or disable pipelines run in an -[external integration](../user/project/integrations/index.md#available-integrations). +When you disable GitLab CI/CD: -## Enable CI/CD in a project +- The **CI/CD** item in the left sidebar is removed. +- The `/pipelines` and `/jobs` pages are no longer available. +- Existing jobs and pipelines are hidden, not removed. -To enable or disable GitLab CI/CD pipelines in your project: +To disable GitLab CI/CD in your project: 1. On the top bar, select **Menu > Projects** and find your project. 1. On the left sidebar, select **Settings > General**. 1. Expand **Visibility, project features, permissions**. -1. In the **Repository** section, turn on or off **CI/CD** as required. +1. In the **Repository** section, turn off **CI/CD**. +1. Select **Save changes**. -**Project visibility** also affects pipeline visibility. If set to: +## Enable CI/CD in a project -- **Private**: Only project members can access pipelines. -- **Internal** or **Public**: Pipelines can be set to either **Only Project Members** - or **Everyone With Access** by using the dropdown box. +To enable GitLab CI/CD in your project: -Press **Save changes** for the settings to take effect. +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Settings > General**. +1. Expand **Visibility, project features, permissions**. +1. In the **Repository** section, turn on **CI/CD**. +1. Select **Save changes**. <!-- ## Troubleshooting diff --git a/doc/ci/environments/protected_environments.md b/doc/ci/environments/protected_environments.md index adc215c7aa1..701c5355191 100644 --- a/doc/ci/environments/protected_environments.md +++ b/doc/ci/environments/protected_environments.md @@ -208,7 +208,7 @@ configured: deployment ruleset. - Developers should be given no more than the Developer role for the top-level group, or explicitly given the Maintainer role for a child project - They do *NOT* have access to the CI/CD configurations in the + They do *not* have access to the CI/CD configurations in the top-level group, so operators can ensure that the critical configuration won't be accidentally changed by the developers. - For sub-groups and child projects: diff --git a/doc/ci/pipelines/settings.md b/doc/ci/pipelines/settings.md index e409b63e098..40daf154a5f 100644 --- a/doc/ci/pipelines/settings.md +++ b/doc/ci/pipelines/settings.md @@ -31,19 +31,43 @@ To change the visibility of your pipelines and related features: 1. Select or clear the **Public pipelines** checkbox. When it is selected, pipelines and related features are visible: - - For **public** projects, to everyone. - - For **internal** projects, to all logged-in users except [external users](../../user/permissions.md#external-users). - - For **private** projects, to all project members (Guest or higher). + - For [**Public**](../../user/public_access.md) projects, to everyone. + - For **Internal** projects, to all logged-in users except [external users](../../user/permissions.md#external-users). + - For **Private** projects, to all project members (Guest or higher). When it is cleared: - - For **public** projects, job logs, job artifacts, the pipeline security dashboard, + - For **Public** projects, job logs, job artifacts, the pipeline security dashboard, and the **CI/CD** menu items are visible only to project members (Reporter or higher). Other users, including guest users, can only view the status of pipelines and jobs, and only when viewing merge requests or commits. - - For **internal** projects, pipelines are visible to all logged in users except [external users](../../user/permissions.md#external-users). + - For **Internal** projects, pipelines are visible to all logged in users except [external users](../../user/permissions.md#external-users). Related features are visible only to project members (Reporter or higher). - - For **private** projects, pipelines and related features are visible to project members (Reporter or higher) only. + - For **Private** projects, pipelines and related features are visible to project members (Reporter or higher) only. + +### Change pipeline visibility for non-project members in public projects + +You can control the visibility of pipelines for non-project members in [public projects](../../user/public_access.md). + +This setting has no effect when: + +- Project visibility is set to [**Internal** or **Private**](../../user/public_access.md), + because non-project members cannot access internal or private projects. +- The [**Public pipelines**](#change-which-users-can-view-your-pipelines) setting is disabled. + +To change the pipeline visibility for non-project members: + +1. On the top bar, select **Menu > Projects** and find your project. +1. On the left sidebar, select **Settings > General**. +1. Expand **Visibility, project features, permissions**. +1. For **CI/CD**, choose: + - **Only project members**: Only project members can view pipelines. + - **Everyone With Access**: Non-project members can also view pipelines. +1. Select **Save changes**. + +The [CI/CD permissions table](../../user/permissions.md#gitlab-cicd-permissions) +lists the pipeline features non-project members can access when **Everyone With Access** +is selected. ## Auto-cancel redundant pipelines diff --git a/doc/ci/runners/saas/macos/codesigning.md b/doc/ci/runners/saas/macos/codesigning.md index 6d34744b0ac..71fdc61f0b6 100644 --- a/doc/ci/runners/saas/macos/codesigning.md +++ b/doc/ci/runners/saas/macos/codesigning.md @@ -10,7 +10,7 @@ Before you can integrate GitLab with Apple services, install to a device, or dep To code sign an iOS project, you need the following files: -- A certifcate issued by Apple. +- A certificate issued by Apple. - A provisioning profile. ## Code signing iOS Projects with fastlane diff --git a/doc/ci/variables/predefined_variables.md b/doc/ci/variables/predefined_variables.md index b0c2b923559..6ebd15ecd2d 100644 --- a/doc/ci/variables/predefined_variables.md +++ b/doc/ci/variables/predefined_variables.md @@ -116,7 +116,6 @@ as it can cause the pipeline to behave unexpectedly. | `CI_SERVER_PORT` | 12.8 | all | The port of the GitLab instance URL, without host or protocol. For example `8080`. | | `CI_SERVER_PROTOCOL` | 12.8 | all | The protocol of the GitLab instance URL, without host or port. For example `https`. | | `CI_SERVER_REVISION` | all | all | GitLab revision that schedules jobs. | -| `CI_SERVER_TLS_CA_FILE` | all | all | File containing the CA certificate to verify the GitLab server. | | `CI_SERVER_URL` | 12.7 | all | The base URL of the GitLab instance, including protocol and port. For example `https://gitlab.example.com:8080`. | | `CI_SERVER_VERSION_MAJOR` | 11.4 | all | The major version of the GitLab instance. For example, if the GitLab version is `13.6.1`, the `CI_SERVER_VERSION_MAJOR` is `13`. | | `CI_SERVER_VERSION_MINOR` | 11.4 | all | The minor version of the GitLab instance. For example, if the GitLab version is `13.6.1`, the `CI_SERVER_VERSION_MINOR` is `6`. | diff --git a/doc/ci/yaml/index.md b/doc/ci/yaml/index.md index e5c4eb45131..07bcd0beb92 100644 --- a/doc/ci/yaml/index.md +++ b/doc/ci/yaml/index.md @@ -3732,7 +3732,7 @@ successfully complete before starting. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/213729) in GitLab 14.9 [with a flag](../../administration/feature_flags.md) named `ci_trigger_forward_variables`. Disabled by default. > - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/355572) in GitLab 14.10. -> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/355572) in GitLab 15.1. [Feature flag ci_trigger_forward_variables](https://gitlab.com/gitlab-org/gitlab/-/issues/355572) removed. +> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/355572) in GitLab 15.1. [Feature flag `ci_trigger_forward_variables`](https://gitlab.com/gitlab-org/gitlab/-/issues/355572) removed. Use `trigger:forward` to specify what to forward to the downstream pipeline. You can control what is forwarded to both [parent-child pipelines](../pipelines/parent_child_pipelines.md) diff --git a/doc/development/audit_event_guide/index.md b/doc/development/audit_event_guide/index.md index 0ce1c340a84..14cd2fd1dc3 100644 --- a/doc/development/audit_event_guide/index.md +++ b/doc/development/audit_event_guide/index.md @@ -14,7 +14,7 @@ new audit events. Audit Events are a tool for GitLab owners and administrators to view records of important actions performed across the application. -## What should NOT be Audit Events? +## What should not be Audit Events? While any events could trigger an Audit Event, not all events should. In general, events that are not good candidates for audit events are: diff --git a/doc/development/contributing/index.md b/doc/development/contributing/index.md index 363fdfb14a4..182d00d52ab 100644 --- a/doc/development/contributing/index.md +++ b/doc/development/contributing/index.md @@ -37,7 +37,7 @@ Report suspected security vulnerabilities by following the [disclosure process on the GitLab.com website](https://about.gitlab.com/security/disclosure/). WARNING: -Do **NOT** create publicly viewable issues for suspected security vulnerabilities. +Do **not** create publicly viewable issues for suspected security vulnerabilities. ## Code of conduct @@ -130,7 +130,7 @@ The general flow of contributing to GitLab is: - Review the provided checklist. 1. Once you're ready, mark your MR as ready for review with `@gitlab-bot ready`. - This will add the `~"workflow::ready for review"` label, and then automatically assign a merge request coach as reviewer. - - If you know a relevant reviewer (e.g. someone that was involved a related issue), you can also + - If you know a relevant reviewer (for example, someone that was involved a related issue), you can also assign them directly with `@gitlab-bot ready @username`. #### Review process @@ -143,7 +143,7 @@ submissions carefully, and this takes time. Code submissions will usually be rev - A [maintainer](../code_review.md#the-responsibility-of-the-maintainer). After review, the reviewer could ask the author to update the merge request. In that case, the reviewer would set the `~"workflow::in dev"` label. -Once the merge request has been updated and set as ready for review again (e.g. with `@gitlab-bot ready`), they will review the code again. +Once the merge request has been updated and set as ready for review again (for example, with `@gitlab-bot ready`), they will review the code again. This process may repeat any number of times before merge, to help make the contribution the best it can be. Lastly, keep the following in mind when submitting merge requests: diff --git a/doc/development/graphql_guide/batchloader.md b/doc/development/graphql_guide/batchloader.md index 0008fbcebcf..89992f42d27 100644 --- a/doc/development/graphql_guide/batchloader.md +++ b/doc/development/graphql_guide/batchloader.md @@ -162,7 +162,7 @@ you are assured accurate results. GraphQL fields that return lazy values may need these values forced in tests. Forcing refers to explicit demands for evaluation, where this would normally -be arranged by the framework. +be arranged by the framework. You can force a lazy value with the `GraphqlHelpers#batch_sync` method available in [GraphQLHelpers](https://gitlab.com/gitlab-org/gitlab/-/blob/master/spec/support/helpers/graphql_helpers.rb), or by using `Gitlab::Graphql::Lazy.force`. For example: diff --git a/doc/development/internal_api/index.md b/doc/development/internal_api/index.md index 4630cd079e5..06252ed1f79 100644 --- a/doc/development/internal_api/index.md +++ b/doc/development/internal_api/index.md @@ -816,7 +816,7 @@ Each array element contains: | Attribute | Type | Required | Description | |:-------------------|:-----------|:---------|:------------| | `namespace_id` | integer | yes | ID of the namespace to be reconciled | -| `next_reconciliation_date` | date | yes | Date when next reconciliation will happen | +| `next_reconciliation_date` | date | yes | Date of the next reconciliation | | `display_alert_from` | date | yes | Start date to display alert of upcoming reconciliation | Example request: diff --git a/doc/development/logging.md b/doc/development/logging.md index 6a0b50d6970..749f85c9e2d 100644 --- a/doc/development/logging.md +++ b/doc/development/logging.md @@ -344,7 +344,7 @@ provides helper methods to track exceptions: 1. `Gitlab::ErrorTracking.track_exception`: this method only logs and sends exception to Sentry (if configured), 1. `Gitlab::ErrorTracking.log_exception`: this method only logs the exception, - and DOES NOT send the exception to Sentry, + and does not send the exception to Sentry, 1. `Gitlab::ErrorTracking.track_and_raise_for_dev_exception`: this method logs, sends exception to Sentry (if configured) and re-raises the exception for development and test environments. diff --git a/doc/development/rails_initializers.md b/doc/development/rails_initializers.md index c1e3d0c4f22..68f3c07e45a 100644 --- a/doc/development/rails_initializers.md +++ b/doc/development/rails_initializers.md @@ -30,7 +30,7 @@ query) from an initializer means that tasks like `db:drop`, and being dropped. To help detect when database connections are opened from initializers, we now -warn in stderr. For example: +warn in `STDERR`. For example: ```shell DEPRECATION WARNING: Database connection should not be called during initializers (called from block in <module:HasVariable> at app/models/concerns/ci/has_variable.rb:22) diff --git a/doc/development/redis.md b/doc/development/redis.md index 9108148aa62..e48048be624 100644 --- a/doc/development/redis.md +++ b/doc/development/redis.md @@ -56,8 +56,7 @@ the entry, instead of relying on the key changing. ### Multi-key commands -We don't use [Redis Cluster](https://redis.io/topics/cluster-tutorial) at the -moment, but may wish to in the future: [#118820](https://gitlab.com/gitlab-org/gitlab/-/issues/118820). +We don't use Redis Cluster, but support for it is tracked in [this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/118820). This imposes an additional constraint on naming: where GitLab is performing operations that require several keys to be held on the same Redis server - for @@ -120,8 +119,7 @@ on GitLab.com <!-- vale gitlab.Substitutions = NO --> -On GitLab.com, entries from the [Redis -slow log](https://redis.io/commands/slowlog) are available in the +On GitLab.com, entries from the [Redis slow log](https://redis.io/commands/slowlog/) are available in the `pubsub-redis-inf-gprd*` index with the [`redis.slowlog` tag](https://log.gprd.gitlab.net/app/kibana#/discover?_g=(filters:!(),refreshInterval:(pause:!t,value:0),time:(from:now-1d,to:now))&_a=(columns:!(json.type,json.command,json.exec_time_s),filters:!(('$state':(store:appState),meta:(alias:!n,disabled:!f,index:AWSQX_Vf93rHTYrsexmk,key:json.tag,negate:!f,params:(query:redis.slowlog),type:phrase),query:(match:(json.tag:(query:redis.slowlog,type:phrase))))),index:AWSQX_Vf93rHTYrsexmk)). This shows commands that have taken a long time and may be a performance concern. @@ -187,9 +185,9 @@ makes sure that booleans are encoded and decoded consistently. ### `Gitlab::Redis::HLL` -The Redis [`PFCOUNT`](https://redis.io/commands/pfcount), -[`PFADD`](https://redis.io/commands/pfadd), and -[`PFMERGE`](https://redis.io/commands/pfmerge) commands operate on +The Redis [`PFCOUNT`](https://redis.io/commands/pfcount/), +[`PFADD`](https://redis.io/commands/pfadd/), and +[`PFMERGE`](https://redis.io/commands/pfmerge/) commands operate on HyperLogLogs, a data structure that allows estimating the number of unique elements with low memory usage. (In addition to the `PFCOUNT` documentation, Thoughtbot's article on [HyperLogLogs in Redis](https://thoughtbot.com/blog/hyperloglogs-in-redis) @@ -204,7 +202,7 @@ For cases where we need to efficiently check the whether an item is in a group of items, we can use a Redis set. [`Gitlab::SetCache`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/set_cache.rb) provides an `#include?` method that uses the -[`SISMEMBER`](https://redis.io/commands/sismember) command, as well as `#read` +[`SISMEMBER`](https://redis.io/commands/sismember/) command, as well as `#read` to fetch all entries in the set. This is used by the diff --git a/doc/development/ruby3_gotchas.md b/doc/development/ruby3_gotchas.md index 1ab7a06be24..dbe6fa13eee 100644 --- a/doc/development/ruby3_gotchas.md +++ b/doc/development/ruby3_gotchas.md @@ -142,19 +142,19 @@ Build images are not affected because they include the patch set addressing this ## Deprecations are not caught in DeprecationToolkit if the method is stubbed We rely on `deprecation_toolkit` to fail fast when using functionality that is deprecated in Ruby 2 and removed in Ruby 3. -A common issue caught during the transition from Ruby 2 to Ruby 3 relates to -the [separation of positional and keyword arguments in Ruby 3.0](https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/). - +A common issue caught during the transition from Ruby 2 to Ruby 3 relates to +the [separation of positional and keyword arguments in Ruby 3.0](https://www.ruby-lang.org/en/news/2019/12/12/separation-of-positional-and-keyword-arguments-in-ruby-3-0/). + Unfortunately, if the author has stubbed such methods in tests, deprecations would not be caught. -We run automated detection for this warning in tests via `deprecation_toolkit`, -but it relies on the fact that `Kernel#warn` emits a warning, so stubbing out this call will effectively remove the call to warn, which means `deprecation_toolkit` will never see the deprecation warnings. +We run automated detection for this warning in tests via `deprecation_toolkit`, +but it relies on the fact that `Kernel#warn` emits a warning, so stubbing out this call will effectively remove the call to warn, which means `deprecation_toolkit` will never see the deprecation warnings. Stubbing out the implementation removes that warning, and we never pick it up, so the build is green. Please refer to [issue 364099](https://gitlab.com/gitlab-org/gitlab/-/issues/364099) for more context. ## Testing in `irb` and `rails console` -Another pitfall is that testing in `irb`/`rails c` silences the deprecation warning, +Another pitfall is that testing in `irb`/`rails c` silences the deprecation warning, since `irb` in Ruby 2.7.x has a [bug](https://bugs.ruby-lang.org/issues/17377) that prevents deprecation warnings from showing. When writing code and performing code reviews, pay extra attention to method calls of the form `f({k: v})`. diff --git a/doc/development/scalability.md b/doc/development/scalability.md index 4450df0399d..39cd0ecfcdd 100644 --- a/doc/development/scalability.md +++ b/doc/development/scalability.md @@ -222,7 +222,7 @@ only when the primary fails. ### Redis Sentinels -[Redis Sentinel](https://redis.io/topics/sentinel) provides high +[Redis Sentinel](https://redis.io/docs/manual/sentinel/) provides high availability for Redis by watching the primary. If multiple Sentinels detect that the primary has gone away, the Sentinels performs an election to determine a new leader. @@ -232,8 +232,7 @@ election to determine a new leader. No leader: A Redis cluster can get into a mode where there are no primaries. For example, this can happen if Redis nodes are misconfigured to follow the wrong node. Sometimes this requires forcing one node to -become a primary by using the [`REPLICAOF NO ONE` -command](https://redis.io/commands/replicaof). +become a primary by using the [`REPLICAOF NO ONE` command](https://redis.io/commands/replicaof/). ### Sidekiq @@ -275,8 +274,8 @@ in a timely manner: this to `ProcessCommitWorker`. - Redistribute/gerrymander Sidekiq processes by queue types. Long-running jobs (for example, relating to project import) can often - squeeze out jobs that run fast (for example, delivering email). [This technique - was used in to optimize our existing Sidekiq deployment](https://gitlab.com/gitlab-com/gl-infra/infrastructure/-/issues/7219#note_218019483). + squeeze out jobs that run fast (for example, delivering email). + [We used this technique to optimize our existing Sidekiq deployment](https://gitlab.com/gitlab-com/gl-infra/reliability/-/issues/7219#note_218019483). - Optimize jobs. Eliminating unnecessary work, reducing network calls (including SQL and Gitaly), and optimizing processor time can yield significant benefits. diff --git a/doc/development/testing_guide/best_practices.md b/doc/development/testing_guide/best_practices.md index 1c17d056a08..3b2eb5a2cfa 100644 --- a/doc/development/testing_guide/best_practices.md +++ b/doc/development/testing_guide/best_practices.md @@ -1014,7 +1014,7 @@ is used to delete data in all indices in between examples to ensure a clean inde Note that Elasticsearch indexing uses [`Gitlab::Redis::SharedState`](../../../ee/development/redis.md#gitlabrediscachesharedstatequeues). Therefore, the Elasticsearch traits dynamically use the `:clean_gitlab_redis_shared_state` trait. -You do NOT need to add `:clean_gitlab_redis_shared_state` manually. +You do not need to add `:clean_gitlab_redis_shared_state` manually. Specs using Elasticsearch require that you: diff --git a/doc/development/testing_guide/end_to_end/feature_flags.md b/doc/development/testing_guide/end_to_end/feature_flags.md index 0828ceed825..b1d6ef4d681 100644 --- a/doc/development/testing_guide/end_to_end/feature_flags.md +++ b/doc/development/testing_guide/end_to_end/feature_flags.md @@ -206,12 +206,12 @@ There are two ways to confirm that end-to-end tests pass: If enabling the feature flag results in E2E test failures, you can browse the artifacts in the failed pipeline to see screenshots of the failed tests. After which, you can either: -- Identify tests that need to be updated and contact the relevant [counterpart Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) responsible for updating the tests or assisting another engineer to do so. However, if a change does not go through [quad-planning](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/quad-planning/) and a required test update is not made, test failures could block deployment. +- Identify tests that need to be updated and contact the relevant [counterpart Software Engineer in Test](https://about.gitlab.com/handbook/engineering/quality/#individual-contributors) responsible for updating the tests or assisting another engineer to do so. However, if a change does not go through [quad-planning](https://about.gitlab.com/handbook/engineering/quality/quality-engineering/quad-planning/) and a required test update is not made, test failures could block deployment. - Run the failed tests [locally](https://gitlab.com/gitlab-org/gitlab/-/tree/master/qa#run-the-end-to-end-tests-in-a-local-development-environment) with the [feature flag enabled](https://gitlab.com/gitlab-org/gitlab/-/tree/master/qa#running-tests-with-a-feature-flag-enabled-or-disabled). This option requires considerable amount of setup, but you'll be able to see what the browser is doing as it's running the failed tests, which can help debug the problem faster. You can also refer to the [Troubleshooting Guide for E2E tests](troubleshooting.md) for - support for common blockers. + support for common blockers. ### Test execution during feature development diff --git a/doc/development/workhorse/configuration.md b/doc/development/workhorse/configuration.md index 2030ec15b96..b86bb824ea1 100644 --- a/doc/development/workhorse/configuration.md +++ b/doc/development/workhorse/configuration.md @@ -254,7 +254,7 @@ recommended that this option be used with an IP allow list to ensure arbitrary values cannot be generated by untrusted clients. An IP allow list is specified via the `trusted_cidrs_for_propagation` -opton in the Workhorse configuration file. Specify a list of CIDR blocks +option in the Workhorse configuration file. Specify a list of CIDR blocks that can be trusted. For example: ```toml diff --git a/doc/development/workhorse/gitlab_features.md b/doc/development/workhorse/gitlab_features.md index 2aa8d9d2399..365cc7991d8 100644 --- a/doc/development/workhorse/gitlab_features.md +++ b/doc/development/workhorse/gitlab_features.md @@ -53,14 +53,14 @@ memory than it costs to have Workhorse look after it. for example, JavaScript files and CSS files are served straight from disk. - Workhorse can modify responses sent by Rails: for example if you use - `send_file` in Rails then GitLab Workhorse will open the file on + `send_file` in Rails then GitLab Workhorse opens the file on disk and send its contents as the response body to the client. - Workhorse can take over requests after asking permission from Rails. Example: handling `git clone`. - Workhorse can modify requests before passing them to Rails. Example: when handling a Git LFS upload Workhorse first asks permission from - Rails, then it stores the request body in a tempfile, then it sends - a modified request containing the tempfile path to Rails. + Rails, then it stores the request body in a temporary file, then it sends + a modified request containing the file path to Rails. - Workhorse can manage long-lived WebSocket connections for Rails. Example: handling the terminal websocket for environments. - Workhorse does not connect to PostgreSQL, only to Rails and (optionally) Redis. diff --git a/doc/user/admin_area/monitoring/health_check.md b/doc/user/admin_area/monitoring/health_check.md index a36f00c768c..84c7fa3c419 100644 --- a/doc/user/admin_area/monitoring/health_check.md +++ b/doc/user/admin_area/monitoring/health_check.md @@ -12,14 +12,14 @@ database connection, Redis connection, and access to the file system. These endpoints [can be provided to schedulers like Kubernetes](https://kubernetes.io/docs/tasks/configure-pod-container/configure-liveness-readiness-startup-probes/) to hold traffic until the system is ready or restart the container as needed. -## IP whitelist +## IP allowlist -To access monitoring resources, the requesting client IP needs to be included in a whitelist. +To access monitoring resources, the requesting client IP needs to be included in the allowlist. For details, see [how to add IPs to the allowlist for the monitoring endpoints](../../../administration/monitoring/ip_whitelist.md). ## Using the endpoints locally -With default whitelist settings, the probes can be accessed from localhost using the following URLs: +With default allowlist settings, the probes can be accessed from localhost using the following URLs: ```plaintext GET http://localhost/-/health diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md index 970897fd8da..c877ca9837d 100644 --- a/doc/user/admin_area/settings/index.md +++ b/doc/user/admin_area/settings/index.md @@ -160,7 +160,7 @@ The **Preferences** settings contain: The **Reporting** settings contain: - [Spam and Anti-bot Protection](../../../integration/recaptcha.md) - - Enable anti-spam services, like reCAPTCHA, Akismet or [Spamcheck](../reporting/spamcheck.md), and set IP limits. + Enable anti-spam services, like reCAPTCHA, Akismet, or [Spamcheck](../reporting/spamcheck.md), and set IP limits. - [Abuse reports](../review_abuse_reports.md) - Set notification email for abuse reports. ### Repository diff --git a/doc/user/admin_area/settings/visibility_and_access_controls.md b/doc/user/admin_area/settings/visibility_and_access_controls.md index 103eae07517..55a399f0241 100644 --- a/doc/user/admin_area/settings/visibility_and_access_controls.md +++ b/doc/user/admin_area/settings/visibility_and_access_controls.md @@ -95,7 +95,7 @@ To set the default [visibility levels for new projects](../../public_access.md): 1. Expand the **Visibility and access controls** section. 1. Select the desired default project visibility: - **Private** - Project access must be granted explicitly to each user. If this - project is part of a group, access will be granted to members of the group. + project is part of a group, access is granted to members of the group. - **Internal** - The project can be accessed by any logged in user except external users. - **Public** - The project can be accessed without any authentication. 1. Select **Save changes**. diff --git a/doc/user/application_security/api_fuzzing/index.md b/doc/user/application_security/api_fuzzing/index.md index 3781397578d..cbe20ecde30 100644 --- a/doc/user/application_security/api_fuzzing/index.md +++ b/doc/user/application_security/api_fuzzing/index.md @@ -65,7 +65,7 @@ Requirements: - Postman Collection v2.0 or v2.1 WARNING: - **NEVER** run fuzz testing against a production server. Not only can it perform *any* function that + **Never** run fuzz testing against a production server. Not only can it perform *any* function that the API can, it may also trigger bugs in the API. This includes actions like modifying and deleting data. Only run fuzzing against a test server. diff --git a/doc/user/application_security/dast/checks/16.3.md b/doc/user/application_security/dast/checks/16.3.md index e4fc2468dae..6f80a2a32c6 100644 --- a/doc/user/application_security/dast/checks/16.3.md +++ b/doc/user/application_security/dast/checks/16.3.md @@ -32,4 +32,4 @@ information from the `X-Powered-By` header. ## Links - [CWE](https://cwe.mitre.org/data/definitions/16.html) -- [PHP expose_php](https://www.php.net/manual/en/ini.core.php#ini.expose-php) +- [PHP `expose_php`](https://www.php.net/manual/en/ini.core.php#ini.expose-php) diff --git a/doc/user/application_security/dast/checks/16.5.md b/doc/user/application_security/dast/checks/16.5.md index 28bb9f7ee4b..e03da3043ef 100644 --- a/doc/user/application_security/dast/checks/16.5.md +++ b/doc/user/application_security/dast/checks/16.5.md @@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w ## Description -The target website returns AspNet header(s) and version information of this website. By +The target website returns AspNet headers and version information of this website. By exposing these values attackers may attempt to identify if the target software is vulnerable to known vulnerabilities, or catalog known sites running particular versions to exploit in the future when a vulnerability is identified in the particular version. diff --git a/doc/user/application_security/dast/checks/16.6.md b/doc/user/application_security/dast/checks/16.6.md index ddd3a10c5f8..9cbcde669a0 100644 --- a/doc/user/application_security/dast/checks/16.6.md +++ b/doc/user/application_security/dast/checks/16.6.md @@ -8,7 +8,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w ## Description -The target website returns AspNet header(s) along with version information of this website. By +The target website returns AspNet headers along with version information of this website. By exposing these values attackers may attempt to identify if the target software is vulnerable to known vulnerabilities. Or catalog known sites running particular versions to exploit in the future when a vulnerability is identified in the particular version. diff --git a/doc/user/application_security/dast/checks/319.1.md b/doc/user/application_security/dast/checks/319.1.md index 7eed0104809..d598fb70ce3 100644 --- a/doc/user/application_security/dast/checks/319.1.md +++ b/doc/user/application_security/dast/checks/319.1.md @@ -9,19 +9,19 @@ info: To determine the technical writer assigned to the Stage/Group associated w ## Description The target application was found to request resources over insecure transport protocols (HTTP). This is usually due to HTML -elements which load resources using the `http://` scheme instead of `https://`. It should be noted that most modern browsers -block these requests automatically so there is limited risk. +elements which load resources using the `http://` scheme instead of `https://`. It should be noted that most modern browsers +block these requests automatically so there is limited risk. Some parts of the application may not behave correctly since these files are not being properly loaded. ## Remediation -Ensure all HTML elements which load resources from a URL (JavaScript, stylesheets, images, video and other media) are set to +Ensure all HTML elements which load resources from a URL (JavaScript, stylesheets, images, video and other media) are set to use the `https://` scheme instead of `http://`. Alternatively, developers may use the `//` scheme, which will only load resources -over the same protocol that the originating page was loaded. +over the same protocol that the originating page was loaded. -A browser visiting the website `https://example.com` with the HTML loading a file using -`<script src="//example.com/cdn/bundle.js"></script>`, would ensure the `example.com/cdn/bundle.js` file was loaded over +A browser visiting the website `https://example.com` with the HTML loading a file using +`<script src="//example.com/cdn/bundle.js"></script>`, would ensure the `example.com/cdn/bundle.js` file was loaded over HTTPS. ## Details diff --git a/doc/user/application_security/dast/index.md b/doc/user/application_security/dast/index.md index a8e1c7ec369..658b5ba4bf6 100644 --- a/doc/user/application_security/dast/index.md +++ b/doc/user/application_security/dast/index.md @@ -737,7 +737,7 @@ by the application as correctly authenticated. Authentication supports single form logins, multi-step login forms, and authenticating to URLs outside of the configured target URL. WARNING: -**NEVER** run an authenticated scan against a production server. When an authenticated +**Never** run an authenticated scan against a production server. When an authenticated scan is run, it may perform *any* function that the authenticated user can. This includes actions like modifying and deleting data, submitting forms, and following links. Only run an authenticated scan against a test server. diff --git a/doc/user/application_security/index.md b/doc/user/application_security/index.md index 463bb18b941..df24a0dcc3c 100644 --- a/doc/user/application_security/index.md +++ b/doc/user/application_security/index.md @@ -169,7 +169,7 @@ If you want to override this to increase the pipeline speed you may choose which ### Secure job status -Jobs pass if they are able to complete a scan. A _pass_ result does NOT indicate if they did, or did not, identify findings. The only exception is coverage fuzzing, which fails if it identifies findings. +Jobs pass if they are able to complete a scan. A _pass_ result does not indicate if they did, or did not, identify findings. The only exception is coverage fuzzing, which fails if it identifies findings. Jobs fail if they are unable to complete a scan. You can view the pipeline logs for more information. @@ -200,11 +200,11 @@ reports are available to download. To download a report, select ### Ultimate -A merge request contains a security widget which displays a summary of the NEW results. New results are determined by comparing the current findings against existing findings in the target (default) branch (if there are prior findings). +A merge request contains a security widget which displays a summary of the new results. New results are determined by comparing the current findings against existing findings in the target (default) branch (if there are prior findings). We recommend you run a scan of the `default` branch before enabling feature branch scans for your developers. Otherwise, there is no base for comparison and all feature branches display the full scan results in the merge request security widget. -The merge request security widget displays only a subset of the vulnerabilities in the generated JSON artifact because it contains both NEW and EXISTING findings. +The merge request security widget displays only a subset of the vulnerabilities in the generated JSON artifact because it contains both new and existing findings. From the merge request security widget, select **Expand** to unfold the widget, displaying any new and no longer detected (removed) findings by scan type. Select **View full report** to go directly to the **Security** tab in the latest branch pipeline. diff --git a/doc/user/application_security/sast/index.md b/doc/user/application_security/sast/index.md index 448be0ade3a..d86fa2af48a 100644 --- a/doc/user/application_security/sast/index.md +++ b/doc/user/application_security/sast/index.md @@ -525,7 +525,7 @@ defined for the `nodejs-scan` scanner: ''' ``` -##### File passthrough for gosec +##### File passthrough for Gosec Provide the name of the file containing a custom analyzer configuration. In this example, customized rules for the `gosec` scanner are contained in the diff --git a/doc/user/asciidoc.md b/doc/user/asciidoc.md index 41e4929576b..b55a55eebe5 100644 --- a/doc/user/asciidoc.md +++ b/doc/user/asciidoc.md @@ -399,10 +399,10 @@ Color written inside backticks is followed by a color "chip": - `HSLA(540,70%,50%,0.3)` ``` -### STEM +### Equations and Formulas (STEM) -To activate equation and formula support, -set the `stem` attribute in the document's header to `latexmath`. +If you need to include Science, Technology, Engineering and Math (STEM) +expressions, set the `stem` attribute in the document's header to `latexmath`. Equations and formulas are rendered using [KaTeX](https://katex.org/): ```plaintext diff --git a/doc/user/clusters/agent/ci_cd_workflow.md b/doc/user/clusters/agent/ci_cd_workflow.md index 644a753e282..c04c5a1f7ec 100644 --- a/doc/user/clusters/agent/ci_cd_workflow.md +++ b/doc/user/clusters/agent/ci_cd_workflow.md @@ -235,6 +235,10 @@ The identity can be specified with the following keys: See the [official Kubernetes documentation for details](https://kubernetes.io/docs/reference/access-authn-authz/authentication/#user-impersonation). +## Related topics + +- [Self-paced classroom workshop](https://gitlab-for-eks.awsworkshop.io) (Uses AWS EKS, but you can use for other Kubernetes clusters) + ## Troubleshooting ### `kubectl` commands not supported diff --git a/doc/user/clusters/agent/gitops.md b/doc/user/clusters/agent/gitops.md index 3bd48390364..64eae308bec 100644 --- a/doc/user/clusters/agent/gitops.md +++ b/doc/user/clusters/agent/gitops.md @@ -124,10 +124,10 @@ As a result, every field in a resource can have different managers. Only fields are checked for drift. This facilitates the use of in-cluster controllers to modify resources like [Horizontal Pod Autoscalers](https://kubernetes.io/docs/tasks/run-application/horizontal-pod-autoscale/). -## Additional resources - -The following documentation and examples can help you get started with a GitOps workflow. +## Related topics +- [GitOps working examples for training and demos](https://gitlab.com/groups/guided-explorations/gl-k8s-agent/gitops/-/wikis/home) +- [Self-paced classroom workshop](https://gitlab-for-eks.awsworkshop.io) (Uses AWS EKS, but you can use for other Kubernetes clusters) - [Managing Kubernetes secrets in a GitOps workflow](gitops/secrets_management.md) - [Application and manifest repository example](https://gitlab.com/gitlab-examples/ops/gitops-demo/hello-world-service-gitops) diff --git a/doc/user/clusters/agent/index.md b/doc/user/clusters/agent/index.md index 54259b9fc26..5a69da28632 100644 --- a/doc/user/clusters/agent/index.md +++ b/doc/user/clusters/agent/index.md @@ -66,9 +66,11 @@ Read about how to [migrate to the agent for Kubernetes](../../infrastructure/clu ## Related topics - [GitOps workflow](gitops.md) +- [GitOps examples and learning materials](gitops.md#related-topics) - [GitLab CI/CD workflow](ci_cd_workflow.md) - [Install the agent](install/index.md) - [Work with the agent](repository.md) - [Troubleshooting](troubleshooting.md) - [Guided explorations for a production ready GitOps setup](https://gitlab.com/groups/guided-explorations/gl-k8s-agent/gitops/-/wikis/home#gitlab-agent-for-kubernetes-gitops-working-examples) +- [CI/CD for Kubernetes examples and learning materials](ci_cd_workflow.md#related-topics) - [Contribute to the agent's development](https://gitlab.com/gitlab-org/cluster-integration/gitlab-agent/-/tree/master/doc) diff --git a/doc/user/permissions.md b/doc/user/permissions.md index dc8796ffe4d..552df5173af 100644 --- a/doc/user/permissions.md +++ b/doc/user/permissions.md @@ -252,8 +252,8 @@ More details about the permissions for some project-level features follow. - [Public pipelines](../ci/pipelines/settings.md#change-which-users-can-view-your-pipelines): When set to public, gives access to certain CI/CD features to *Guest* project members. -- [Pipeline visibility](../ci/enable_or_disable_ci.md#enable-cicd-in-a-project): When set to **Everyone with Access**, - gives access to certain CI/CD "view" features to *non-project* members. +- [Pipeline visibility](../ci/pipelines/settings.md#change-pipeline-visibility-for-non-project-members-in-public-projects): + When set to **Everyone with Access**, gives access to certain CI/CD "view" features to *non-project* members. | Action | Non-member | Guest | Reporter | Developer | Maintainer | Owner | |---------------------------------------------------------------------------------------------------------------------------|------------|---------|----------|-----------|------------|-------| @@ -521,7 +521,7 @@ and the ignore case flag is set (`/regex pattern/i`). Here are some examples: - Use `\.internal@domain\.com$` to mark email addresses ending with `.internal@domain.com` as internal. - Use `^(?:(?!\.ext@domain\.com).)*$\r?` to mark users with email addresses - NOT including `.ext@domain.com` as internal. + not including `.ext@domain.com` as internal. WARNING: Be aware that this regex could lead to a diff --git a/doc/user/project/highlighting.md b/doc/user/project/highlighting.md index ef0c787b9d3..37ec7c8e8d3 100644 --- a/doc/user/project/highlighting.md +++ b/doc/user/project/highlighting.md @@ -42,7 +42,7 @@ To override syntax highlighting for a file type: After the changes merge into your [default branch](repository/branches/default.md), all `*.pl` files in your project are highlighted in your preferred language. -You can also extend the highlighting with common gateway interface (CGI) options, such as: +You can also extend the highlighting with Common Gateway Interface (CGI) options, such as: ``` conf # JSON file with .erb in it diff --git a/doc/user/project/repository/branches/default.md b/doc/user/project/repository/branches/default.md index f9fd1a48b9a..e087ed6c439 100644 --- a/doc/user/project/repository/branches/default.md +++ b/doc/user/project/repository/branches/default.md @@ -252,7 +252,7 @@ We are tracking this problem in [issue 20474](https://gitlab.com/gitlab-org/gitl This issue often occurs when a branch named `HEAD` is present in the repository. To fix the problem: -1. In your local repository, create a new, temporary branch and push it: +1. In your local repository, create a new temporary branch and push it: ```shell git checkout -b tmp_default && git push -u origin tmp_default diff --git a/doc/user/project/repository/branches/index.md b/doc/user/project/repository/branches/index.md index 14ad550fe79..6da2e5fc7ee 100644 --- a/doc/user/project/repository/branches/index.md +++ b/doc/user/project/repository/branches/index.md @@ -98,7 +98,7 @@ Sometimes when you have hundreds of branches you may want a more flexible matchi ![Before swap revisions](img/swap_revisions_before_v13_12.png) -The Swap revisions feature allows you to swap the Source and Target revisions. When the Swap revisions button is clicked, the selected revisions for Source and Target will be swapped. +The Swap revisions feature allows you to swap the Source and Target revisions. When the Swap revisions button is clicked, the selected revisions for Source and Target is swapped. ![After swap revisions](img/swap_revisions_after_v13_12.png) diff --git a/doc/user/project/repository/csv.md b/doc/user/project/repository/csv.md index 4bf6c7451d5..27424268d2b 100644 --- a/doc/user/project/repository/csv.md +++ b/doc/user/project/repository/csv.md @@ -13,7 +13,7 @@ A comma-separated values (CSV) file is a delimited text file that uses a comma t Each line of the file is a data record. Each record consists of one or more fields, separated by commas. The use of the comma as a field separator is the source of the name for this file format. A CSV file typically stores tabular data (numbers and text) in plain text, in which case each line -will have the same number of fields. +has the same number of fields. The CSV file format is not fully standardized. Other characters can be used as column delimiters. Fields may or may not be surrounded to escape special characters. diff --git a/doc/user/search/advanced_search.md b/doc/user/search/advanced_search.md index bbed1f542cb..d050bbce19f 100644 --- a/doc/user/search/advanced_search.md +++ b/doc/user/search/advanced_search.md @@ -96,7 +96,7 @@ doesn't return any results for searches considered abusive according to the foll - Searches with less than 2 characters. - Searches with any term greater than 100 characters. URL search terms have a maximum of 200 characters. -- Searches with a stop word as the only term (ie: "the", "and", "if", etc.). +- Searches with a stop word as the only term (for example, "the", "and", "if", etc.). - Searches with a `group_id` or `project_id` parameter that is not completely numeric. - Searches with a `repository_ref` or `project_ref` parameter that has special characters not allowed by [Git refname](https://git-scm.com/docs/git-check-ref-format). - Searches with a `scope` that is unknown. diff --git a/lib/api/api.rb b/lib/api/api.rb index c20ca768d48..8cafde4fedb 100644 --- a/lib/api/api.rb +++ b/lib/api/api.rb @@ -131,7 +131,7 @@ module API # This is a specific exception raised by `rack-timeout` gem when Puma # requests surpass its timeout. Given it inherits from Exception, we # should rescue it separately. For more info, see: - # - https://github.com/sharpstone/rack-timeout/blob/master/doc/exceptions.md + # - https://github.com/zombocom/rack-timeout/blob/master/doc/exceptions.md # - https://github.com/ruby-grape/grape#exception-handling rescue_from Rack::Timeout::RequestTimeoutException do |exception| handle_api_exception(exception) diff --git a/lib/gitlab/application_rate_limiter.rb b/lib/gitlab/application_rate_limiter.rb index a79d4e25e5c..b9aa2e8c987 100644 --- a/lib/gitlab/application_rate_limiter.rb +++ b/lib/gitlab/application_rate_limiter.rb @@ -42,7 +42,8 @@ module Gitlab search_rate_limit: { threshold: -> { application_settings.search_rate_limit }, interval: 1.minute }, search_rate_limit_unauthenticated: { threshold: -> { application_settings.search_rate_limit_unauthenticated }, interval: 1.minute }, gitlab_shell_operation: { threshold: 600, interval: 1.minute }, - pipelines_create: { threshold: -> { application_settings.pipeline_limit_per_project_user_sha }, interval: 1.minute } + pipelines_create: { threshold: -> { application_settings.pipeline_limit_per_project_user_sha }, interval: 1.minute }, + temporary_email_failure: { threshold: 50, interval: 1.day } }.freeze end diff --git a/lib/gitlab/mailgun/webhook_processors/base.rb b/lib/gitlab/mailgun/webhook_processors/base.rb new file mode 100644 index 00000000000..9402637a51d --- /dev/null +++ b/lib/gitlab/mailgun/webhook_processors/base.rb @@ -0,0 +1,20 @@ +# frozen_string_literal: true + +module Gitlab + module Mailgun + module WebhookProcessors + class Base + def initialize(payload) + @payload = payload || {} + end + + def execute + end + + private + + attr_reader :payload + end + end + end +end diff --git a/lib/gitlab/mailgun/webhook_processors/failure_logger.rb b/lib/gitlab/mailgun/webhook_processors/failure_logger.rb new file mode 100644 index 00000000000..a7a85bd1672 --- /dev/null +++ b/lib/gitlab/mailgun/webhook_processors/failure_logger.rb @@ -0,0 +1,36 @@ +# frozen_string_literal: true + +module Gitlab + module Mailgun + module WebhookProcessors + class FailureLogger < Base + def execute + log_failure if permanent_failure? || temporary_failure_over_threshold? + end + + def permanent_failure? + payload['event'] == 'failed' && payload['severity'] == 'permanent' + end + + def temporary_failure_over_threshold? + payload['event'] == 'failed' && payload['severity'] == 'temporary' && + Gitlab::ApplicationRateLimiter.throttled?(:temporary_email_failure, scope: payload['recipient']) + end + + private + + def log_failure + Gitlab::ErrorTracking::Logger.error( + event: 'email_delivery_failure', + mailgun_event_id: payload['id'], + recipient: payload['recipient'], + failure_type: payload['severity'], + failure_reason: payload['reason'], + failure_code: payload.dig('delivery-status', 'code'), + failure_message: payload.dig('delivery-status', 'message') + ) + end + end + end + end +end diff --git a/lib/gitlab/mailgun/webhook_processors/member_invites.rb b/lib/gitlab/mailgun/webhook_processors/member_invites.rb new file mode 100644 index 00000000000..f54c44381f0 --- /dev/null +++ b/lib/gitlab/mailgun/webhook_processors/member_invites.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +module Gitlab + module Mailgun + module WebhookProcessors + class MemberInvites < Base + ProcessWebhookServiceError = Class.new(StandardError) + + def execute + return unless should_process? + + @member = Member.find_by_invite_token(invite_token) + update_member_and_log if member + rescue ProcessWebhookServiceError => e + Gitlab::ErrorTracking.track_exception(e) + end + + private + + attr_reader :member + + def should_process? + payload['event'] == 'failed' && payload['severity'] == 'permanent' && + payload['tags']&.include?(::Members::Mailgun::INVITE_EMAIL_TAG) + end + + def update_member_and_log + log_update_event if member.update(invite_email_success: false) + end + + def log_update_event + Gitlab::AppLogger.info( + message: "UPDATED MEMBER INVITE_EMAIL_SUCCESS: member_id: #{member.id}", + event: 'updated_member_invite_email_success' + ) + end + + def invite_token + # may want to validate schema in some way using ::JSONSchemer.schema(SCHEMA_PATH).valid?(message) if this + # gets more complex + payload.dig('user-variables', ::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY) || + raise(ProcessWebhookServiceError, "Expected to receive #{::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY} " \ + "in user-variables: #{payload}") + end + end + end + end +end diff --git a/spec/components/pajamas/banner_component_spec.rb b/spec/components/pajamas/banner_component_spec.rb new file mode 100644 index 00000000000..5969f06dbad --- /dev/null +++ b/spec/components/pajamas/banner_component_spec.rb @@ -0,0 +1,169 @@ +# frozen_string_literal: true +require "spec_helper" + +RSpec.describe Pajamas::BannerComponent, type: :component do + subject do + described_class.new(**options) + end + + let(:title) { "Banner title" } + let(:content) { "Banner content"} + let(:options) { {} } + + describe 'basic usage' do + before do + render_inline(subject) do |c| + c.title { title } + content + end + end + + it 'renders its content' do + expect(rendered_component).to have_text content + end + + it 'renders its title' do + expect(rendered_component).to have_css "h1[class='gl-banner-title']", text: title + end + + it 'renders a close button' do + expect(rendered_component).to have_css "button.gl-banner-close" + end + + describe 'button_text and button_link' do + let(:options) { { button_text: 'Learn more', button_link: '/learn-more' } } + + it 'define the primary action' do + expect(rendered_component).to have_css "a.btn-confirm.gl-button[href='/learn-more']", text: 'Learn more' + end + end + + describe 'banner_options' do + let(:options) { { banner_options: { class: "baz", data: { foo: "bar" } } } } + + it 'are on the banner' do + expect(rendered_component).to have_css ".gl-banner.baz[data-foo='bar']" + end + + context 'with custom classes' do + let(:options) { { variant: :introduction, banner_options: { class: 'extra special' } } } + + it 'don\'t conflict with internal banner_classes' do + expect(rendered_component).to have_css '.extra.special.gl-banner-introduction.gl-banner' + end + end + end + + describe 'close_options' do + let(:options) { { close_options: { class: "js-foo", data: { uid: "123" } } } } + + it 'are on the close button' do + expect(rendered_component).to have_css "button.gl-banner-close.js-foo[data-uid='123']" + end + end + + describe 'embedded' do + context 'by default (false)' do + it 'keeps the banner\'s borders' do + expect(rendered_component).not_to have_css ".gl-banner.gl-border-none" + end + end + + context 'when set to true' do + let(:options) { { embedded: true } } + + it 'removes the banner\'s borders' do + expect(rendered_component).to have_css ".gl-banner.gl-border-none" + end + end + end + + describe 'variant' do + context 'by default (promotion)' do + it 'applies no variant class' do + expect(rendered_component).to have_css "[class='gl-banner']" + end + end + + context 'when set to introduction' do + let(:options) { { variant: :introduction } } + + it "applies the introduction class to the banner" do + expect(rendered_component).to have_css ".gl-banner.gl-banner-introduction" + end + + it "applies the confirm class to the close button" do + expect(rendered_component).to have_css ".gl-banner-close.btn-confirm.btn-confirm-tertiary" + end + end + + context 'when set to unknown variant' do + let(:options) { { variant: :foobar } } + + it 'ignores the unknown variant' do + expect(rendered_component).to have_css "[class='gl-banner']" + end + end + end + + describe 'illustration' do + it 'has none by default' do + expect(rendered_component).not_to have_css ".gl-banner-illustration" + end + + context 'with svg_path' do + let(:options) { { svg_path: 'logo.svg' } } + + it 'renders an image as illustration' do + expect(rendered_component).to have_css ".gl-banner-illustration img" + end + end + end + end + + context 'with illustration slot' do + before do + render_inline(subject) do |c| + c.title { title } + c.illustration { "<svg></svg>".html_safe } + content + end + end + + it 'renders the slot content as illustration' do + expect(rendered_component).to have_css ".gl-banner-illustration svg" + end + + context 'and conflicting svg_path' do + let(:options) { { svg_path: 'logo.svg' } } + + it 'uses the slot content' do + expect(rendered_component).to have_css ".gl-banner-illustration svg" + expect(rendered_component).not_to have_css ".gl-banner-illustration img" + end + end + end + + context 'with primary_action slot' do + before do + render_inline(subject) do |c| + c.title { title } + c.primary_action { "<a class='special' href='#'>Special</a>".html_safe } + content + end + end + + it 'renders the slot content as the primary action' do + expect(rendered_component).to have_css "a.special", text: 'Special' + end + + context 'and conflicting button_text and button_link' do + let(:options) { { button_text: 'Not special', button_link: '/' } } + + it 'uses the slot content' do + expect(rendered_component).to have_css "a.special[href='#']", text: 'Special' + expect(rendered_component).not_to have_css "a.btn[href='/']" + end + end + end +end diff --git a/spec/controllers/autocomplete_controller_spec.rb b/spec/controllers/autocomplete_controller_spec.rb index 0a809e80fcd..e874df62cd7 100644 --- a/spec/controllers/autocomplete_controller_spec.rb +++ b/spec/controllers/autocomplete_controller_spec.rb @@ -411,6 +411,7 @@ RSpec.describe AutocompleteController do expect(json_response.count).to eq(1) expect(json_response.first['title']).to eq(deploy_key.title) expect(json_response.first['owner']['id']).to eq(deploy_key.user.id) + expect(json_response.first['deploy_keys_projects']).to be_nil end context 'with an unknown project' do @@ -433,6 +434,7 @@ RSpec.describe AutocompleteController do expect(json_response.count).to eq(1) expect(json_response.first['title']).to eq(deploy_key.title) expect(json_response.first['owner']).to be_nil + expect(json_response.first['deploy_keys_projects']).to be_nil end end end diff --git a/spec/events/pages/page_deleted_event_spec.rb b/spec/events/pages/page_deleted_event_spec.rb new file mode 100644 index 00000000000..ee05b770c48 --- /dev/null +++ b/spec/events/pages/page_deleted_event_spec.rb @@ -0,0 +1,34 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Pages::PageDeletedEvent do + where(:data, :valid) do + [ + [{ project_id: 1, namespace_id: 2 }, true], + [{ project_id: 1 }, false], + [{ namespace_id: 1 }, false], + [{ project_id: 'foo', namespace_id: 2 }, false], + [{ project_id: 1, namespace_id: 'foo' }, false], + [{ project_id: [], namespace_id: 2 }, false], + [{ project_id: 1, namespace_id: [] }, false], + [{ project_id: {}, namespace_id: 2 }, false], + [{ project_id: 1, namespace_id: {} }, false], + ['foo', false], + [123, false], + [[], false] + ] + end + + with_them do + it 'validates data' do + constructor = -> { described_class.new(data: data) } + + if valid + expect { constructor.call }.not_to raise_error + else + expect { constructor.call }.to raise_error(Gitlab::EventStore::InvalidEvent) + end + end + end +end diff --git a/spec/graphql/types/ci/pipeline_merge_request_event_type_enum_spec.rb b/spec/graphql/types/ci/pipeline_merge_request_event_type_enum_spec.rb new file mode 100644 index 00000000000..3a90e4f1fd9 --- /dev/null +++ b/spec/graphql/types/ci/pipeline_merge_request_event_type_enum_spec.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe GitlabSchema.types['PipelineMergeRequestEventType'] do + specify { expect(described_class.graphql_name).to eq('PipelineMergeRequestEventType') } + + it 'has specific values' do + expect(described_class.values).to match a_hash_including( + 'MERGED_RESULT' => have_attributes(value: :merged_result), + 'DETACHED' => have_attributes(value: :detached) + ) + end +end diff --git a/spec/graphql/types/ci/pipeline_type_spec.rb b/spec/graphql/types/ci/pipeline_type_spec.rb index 94d1b42da37..9dee834d05f 100644 --- a/spec/graphql/types/ci/pipeline_type_spec.rb +++ b/spec/graphql/types/ci/pipeline_type_spec.rb @@ -14,7 +14,7 @@ RSpec.describe Types::Ci::PipelineType do coverage created_at updated_at started_at finished_at committed_at stages user retryable cancelable jobs source_job job job_artifacts downstream upstream path project active user_permissions warnings commit commit_path uses_needs - test_report_summary test_suite ref ref_path warning_messages + test_report_summary test_suite ref ref_path warning_messages merge_request_event_type ] if Gitlab.ee? diff --git a/spec/lib/gitlab/mailgun/webhook_processors/failure_logger_spec.rb b/spec/lib/gitlab/mailgun/webhook_processors/failure_logger_spec.rb new file mode 100644 index 00000000000..a2286415e96 --- /dev/null +++ b/spec/lib/gitlab/mailgun/webhook_processors/failure_logger_spec.rb @@ -0,0 +1,92 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Mailgun::WebhookProcessors::FailureLogger do + describe '#execute', :freeze_time, :clean_gitlab_redis_rate_limiting do + let(:base_payload) do + { + 'id' => 'U2kZkAiuScqcMTq-8Atz-Q', + 'event' => 'failed', + 'recipient' => 'recipient@gitlab.com', + 'reason' => 'bounce', + 'delivery-status' => { + 'code' => '421', + 'message' => '4.4.2 mxfront9g.mail.example.com Error: timeout exceeded' + } + } + end + + context 'on permanent failure' do + let(:processor) { described_class.new(base_payload.merge({ 'severity' => 'permanent' })) } + + it 'logs the failure immediately' do + expect(Gitlab::ErrorTracking::Logger).to receive(:error).with( + event: 'email_delivery_failure', + mailgun_event_id: base_payload['id'], + recipient: base_payload['recipient'], + failure_type: 'permanent', + failure_reason: base_payload['reason'], + failure_code: base_payload['delivery-status']['code'], + failure_message: base_payload['delivery-status']['message'] + ) + + processor.execute + end + end + + context 'on temporary failure' do + let(:processor) { described_class.new(base_payload.merge({ 'severity' => 'temporary' })) } + + before do + allow(Gitlab::ApplicationRateLimiter).to receive(:rate_limits) + .and_return(temporary_email_failure: { threshold: 1, interval: 1.minute }) + end + + context 'when threshold is not exceeded' do + it 'increments counter but does not log the failure' do + expect(Gitlab::ApplicationRateLimiter).to receive(:throttled?).with( + :temporary_email_failure, scope: 'recipient@gitlab.com' + ).and_call_original + expect(Gitlab::ErrorTracking::Logger).not_to receive(:error) + + processor.execute + end + end + + context 'when threshold is exceeded' do + before do + processor.execute + end + + it 'increments counter and logs the failure' do + expect(Gitlab::ApplicationRateLimiter).to receive(:throttled?).with( + :temporary_email_failure, scope: 'recipient@gitlab.com' + ).and_call_original + expect(Gitlab::ErrorTracking::Logger).to receive(:error).with( + event: 'email_delivery_failure', + mailgun_event_id: base_payload['id'], + recipient: base_payload['recipient'], + failure_type: 'temporary', + failure_reason: base_payload['reason'], + failure_code: base_payload['delivery-status']['code'], + failure_message: base_payload['delivery-status']['message'] + ) + + processor.execute + end + end + end + + context 'on other events' do + let(:processor) { described_class.new(base_payload.merge({ 'event' => 'delivered' })) } + + it 'does nothing' do + expect(Gitlab::ErrorTracking::Logger).not_to receive(:error) + expect(Gitlab::ApplicationRateLimiter).not_to receive(:throttled?) + + processor.execute + end + end + end +end diff --git a/spec/lib/gitlab/mailgun/webhook_processors/member_invites_spec.rb b/spec/lib/gitlab/mailgun/webhook_processors/member_invites_spec.rb new file mode 100644 index 00000000000..3bd364b0d15 --- /dev/null +++ b/spec/lib/gitlab/mailgun/webhook_processors/member_invites_spec.rb @@ -0,0 +1,74 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Gitlab::Mailgun::WebhookProcessors::MemberInvites do + describe '#execute', :aggregate_failures do + let_it_be(:member) { create(:project_member, :invited) } + + let(:raw_invite_token) { member.raw_invite_token } + let(:payload) do + { + 'event' => 'failed', + 'severity' => 'permanent', + 'tags' => [Members::Mailgun::INVITE_EMAIL_TAG], + 'user-variables' => { ::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY => raw_invite_token } + } + end + + subject(:service) { described_class.new(payload).execute } + + it 'marks the member invite email success as false' do + expect(Gitlab::AppLogger).to receive(:info).with( + message: /^UPDATED MEMBER INVITE_EMAIL_SUCCESS/, + event: 'updated_member_invite_email_success' + ).and_call_original + + expect { service }.to change { member.reload.invite_email_success }.from(true).to(false) + end + + context 'when invite token is not found in payload' do + before do + payload.delete('user-variables') + end + + it 'does not change member status and logs an error' do + expect(Gitlab::AppLogger).not_to receive(:info) + expect(Gitlab::ErrorTracking).to receive(:track_exception).with( + an_instance_of(described_class::ProcessWebhookServiceError)) + + expect { service }.not_to change { member.reload.invite_email_success } + end + end + + shared_examples 'does nothing' do + it 'does not change member status' do + expect(Gitlab::AppLogger).not_to receive(:info) + + expect { service }.not_to change { member.reload.invite_email_success } + end + end + + context 'when member can not be found' do + let(:raw_invite_token) { '_foobar_' } + + it_behaves_like 'does nothing' + end + + context 'when failure is temporary' do + before do + payload['severity'] = 'temporary' + end + + it_behaves_like 'does nothing' + end + + context 'when email is not a member invite' do + before do + payload.delete('tags') + end + + it_behaves_like 'does nothing' + end + end +end diff --git a/spec/serializers/deploy_key_entity_spec.rb b/spec/serializers/deploy_keys/basic_deploy_key_entity_spec.rb index e8d9701be67..c39eb14e339 100644 --- a/spec/serializers/deploy_key_entity_spec.rb +++ b/spec/serializers/deploy_keys/basic_deploy_key_entity_spec.rb @@ -2,7 +2,7 @@ require 'spec_helper' -RSpec.describe DeployKeyEntity do +RSpec.describe DeployKeys::BasicDeployKeyEntity do include RequestAwareEntity let(:user) { create(:user) } @@ -18,7 +18,7 @@ RSpec.describe DeployKeyEntity do project_private.deploy_keys << deploy_key end - describe 'returns deploy keys with projects a user can read' do + describe 'returns deploy keys' do let(:expected_result) do { id: deploy_key.id, @@ -30,19 +30,7 @@ RSpec.describe DeployKeyEntity do almost_orphaned: false, created_at: deploy_key.created_at, updated_at: deploy_key.updated_at, - can_edit: false, - deploy_keys_projects: [ - { - can_push: false, - project: - { - id: project.id, - name: project.name, - full_path: project_path(project), - full_name: project.full_name - } - } - ] + can_edit: false } end diff --git a/spec/serializers/deploy_keys/deploy_key_entity_spec.rb b/spec/serializers/deploy_keys/deploy_key_entity_spec.rb new file mode 100644 index 00000000000..e989aa8656c --- /dev/null +++ b/spec/serializers/deploy_keys/deploy_key_entity_spec.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe DeployKeys::DeployKeyEntity do + include RequestAwareEntity + + let(:user) { create(:user) } + let(:project) { create(:project, :internal)} + let(:project_private) { create(:project, :private)} + let(:deploy_key) { create(:deploy_key) } + let(:options) { { user: user } } + + let(:entity) { described_class.new(deploy_key, options) } + + before do + project.deploy_keys << deploy_key + project_private.deploy_keys << deploy_key + end + + describe 'returns deploy keys with projects a user can read' do + let(:expected_result) do + { + id: deploy_key.id, + user_id: deploy_key.user_id, + title: deploy_key.title, + fingerprint: deploy_key.fingerprint, + fingerprint_sha256: deploy_key.fingerprint_sha256, + destroyed_when_orphaned: true, + almost_orphaned: false, + created_at: deploy_key.created_at, + updated_at: deploy_key.updated_at, + can_edit: false, + deploy_keys_projects: [ + { + can_push: false, + project: + { + id: project.id, + name: project.name, + full_path: project_path(project), + full_name: project.full_name + } + } + ] + } + end + + it { expect(entity.as_json).to eq(expected_result) } + end +end diff --git a/spec/services/members/mailgun/process_webhook_service_spec.rb b/spec/services/members/mailgun/process_webhook_service_spec.rb deleted file mode 100644 index 3b657c05bd8..00000000000 --- a/spec/services/members/mailgun/process_webhook_service_spec.rb +++ /dev/null @@ -1,72 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe Members::Mailgun::ProcessWebhookService do - describe '#execute', :aggregate_failures do - let_it_be(:member) { create(:project_member, :invited) } - - let(:raw_invite_token) { member.raw_invite_token } - let(:payload) { { 'user-variables' => { ::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY => raw_invite_token } } } - - subject(:service) { described_class.new(payload).execute } - - it 'marks the member invite email success as false' do - expect(Gitlab::AppLogger).to receive(:info).with(/^UPDATED MEMBER INVITE_EMAIL_SUCCESS/).and_call_original - - expect { service }.to change { member.reload.invite_email_success }.from(true).to(false) - end - - context 'when member can not be found' do - let(:raw_invite_token) { '_foobar_' } - - it 'does not change member status' do - expect(Gitlab::AppLogger).not_to receive(:info).with(/^UPDATED MEMBER INVITE_EMAIL_SUCCESS/) - - expect { service }.not_to change { member.reload.invite_email_success } - end - end - - context 'when invite token is not found in payload' do - let(:payload) { {} } - - it 'does not change member status and logs an error' do - expect(Gitlab::AppLogger).not_to receive(:info).with(/^UPDATED MEMBER INVITE_EMAIL_SUCCESS/) - expect(Gitlab::ErrorTracking).to receive(:track_exception).with( - an_instance_of(described_class::ProcessWebhookServiceError)) - - expect { service }.not_to change { member.reload.invite_email_success } - end - end - end - - describe '#should_process?' do - it 'processes permanent failures for member invite emails' do - payload = { 'event' => 'failed', 'severity' => 'permanent', 'tags' => [Members::Mailgun::INVITE_EMAIL_TAG] } - service = described_class.new(payload) - - expect(service.should_process?).to eq(true) - end - - it 'does not process temporary failures' do - payload = { 'event' => 'failed', 'severity' => 'temporary', 'tags' => [Members::Mailgun::INVITE_EMAIL_TAG] } - service = described_class.new(payload) - - expect(service.should_process?).to eq(false) - end - - it 'does not process non member invite emails' do - payload = { 'event' => 'failed', 'severity' => 'permanent', 'tags' => [] } - service = described_class.new(payload) - - expect(service.should_process?).to eq(false) - end - - it 'does not process other types of events' do - payload = { 'event' => 'delivered', 'tags' => [Members::Mailgun::INVITE_EMAIL_TAG] } - service = described_class.new(payload) - - expect(service.should_process?).to eq(false) - end - end -end diff --git a/spec/services/pages/delete_service_spec.rb b/spec/services/pages/delete_service_spec.rb index e02e8e72e0b..0c0b2c0431b 100644 --- a/spec/services/pages/delete_service_spec.rb +++ b/spec/services/pages/delete_service_spec.rb @@ -43,4 +43,10 @@ RSpec.describe Pages::DeleteService do service.execute end.to change { PagesDeployment.count }.by(-1) end + + it 'publishes a ProjectDeleted event with project id and namespace id' do + expected_data = { project_id: project.id, namespace_id: project.namespace_id } + + expect { service.execute }.to publish_event(Pages::PageDeletedEvent).with(expected_data) + end end diff --git a/spec/workers/projects/inactive_projects_deletion_cron_worker_spec.rb b/spec/workers/projects/inactive_projects_deletion_cron_worker_spec.rb index da9c5833926..ec10c66968d 100644 --- a/spec/workers/projects/inactive_projects_deletion_cron_worker_spec.rb +++ b/spec/workers/projects/inactive_projects_deletion_cron_worker_spec.rb @@ -5,6 +5,34 @@ require 'spec_helper' RSpec.describe Projects::InactiveProjectsDeletionCronWorker do include ProjectHelpers + shared_examples 'worker is running for more than 4 minutes' do + before do + subject.instance_variable_set(:@start_time, ::Gitlab::Metrics::System.monotonic_time - 5.minutes) + end + + it 'stores the last processed inactive project_id in redis cache' do + Gitlab::Redis::Cache.with do |redis| + expect { worker.perform } + .to change { redis.get('last_processed_inactive_project_id') }.to(inactive_large_project.id.to_s) + end + end + end + + shared_examples 'worker finishes processing in less than 4 minutes' do + before do + Gitlab::Redis::Cache.with do |redis| + redis.set('last_processed_inactive_project_id', inactive_large_project.id) + end + end + + it 'clears the last processed inactive project_id from redis cache' do + Gitlab::Redis::Cache.with do |redis| + expect { worker.perform } + .to change { redis.get('last_processed_inactive_project_id') }.to(nil) + end + end + end + describe "#perform" do subject(:worker) { described_class.new } @@ -79,6 +107,9 @@ RSpec.describe Projects::InactiveProjectsDeletionCronWorker do expect(inactive_large_project.reload.pending_delete).to eq(false) end + + it_behaves_like 'worker is running for more than 4 minutes' + it_behaves_like 'worker finishes processing in less than 4 minutes' end context 'when feature flag is enabled', :clean_gitlab_redis_shared_state, :sidekiq_inline do @@ -130,33 +161,8 @@ RSpec.describe Projects::InactiveProjectsDeletionCronWorker do end end - context 'when the worker is running for more than 4 minutes' do - before do - subject.instance_variable_set(:@start_time, ::Gitlab::Metrics::System.monotonic_time - 5.minutes) - end - - it 'stores the last processed inactive project_id in redis cache' do - Gitlab::Redis::Cache.with do |redis| - expect { worker.perform } - .to change { redis.get('last_processed_inactive_project_id') }.to(inactive_large_project.id.to_s) - end - end - end - - context 'when the worker finishes processing in less than 4 minutes' do - before do - Gitlab::Redis::Cache.with do |redis| - redis.set('last_processed_inactive_project_id', inactive_large_project.id) - end - end - - it 'clears the last processed inactive project_id from redis cache' do - Gitlab::Redis::Cache.with do |redis| - expect { worker.perform } - .to change { redis.get('last_processed_inactive_project_id') }.to(nil) - end - end - end + it_behaves_like 'worker is running for more than 4 minutes' + it_behaves_like 'worker finishes processing in less than 4 minutes' end it_behaves_like 'an idempotent worker' |