diff --git a/Gemfile b/Gemfile index e4901223f95..9b1076baf87 100644 --- a/Gemfile +++ b/Gemfile @@ -488,7 +488,7 @@ gem 'flipper', '~> 0.21.0' gem 'flipper-active_record', '~> 0.21.0' gem 'flipper-active_support_cache_store', '~> 0.21.0' gem 'unleash', '~> 3.2.2' -gem 'gitlab-experiment', '~> 0.6.2' +gem 'gitlab-experiment', '~> 0.6.3' # Structured logging gem 'lograge', '~> 0.5' diff --git a/Gemfile.lock b/Gemfile.lock index 38dc22cd566..999bed3eb4d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -463,7 +463,7 @@ GEM gitlab-dangerfiles (2.3.0) danger (>= 8.3.1) danger-gitlab (>= 8.0.0) - gitlab-experiment (0.6.2) + gitlab-experiment (0.6.3) activesupport (>= 3.0) request_store (>= 1.0) scientist (~> 1.6, >= 1.6.0) @@ -1468,7 +1468,7 @@ DEPENDENCIES github-markup (~> 1.7.0) gitlab-chronic (~> 0.10.5) gitlab-dangerfiles (~> 2.3.0) - gitlab-experiment (~> 0.6.2) + gitlab-experiment (~> 0.6.3) gitlab-fog-azure-rm (~> 1.1.1) gitlab-labkit (~> 0.21.0) gitlab-license (~> 2.0) diff --git a/app/controllers/members/mailgun/permanent_failures_controller.rb b/app/controllers/members/mailgun/permanent_failures_controller.rb deleted file mode 100644 index 685faa34694..00000000000 --- a/app/controllers/members/mailgun/permanent_failures_controller.rb +++ /dev/null @@ -1,65 +0,0 @@ -# frozen_string_literal: true - -module Members - module Mailgun - class PermanentFailuresController < ApplicationController - respond_to :json - - skip_before_action :authenticate_user! - skip_before_action :verify_authenticity_token - - before_action :ensure_feature_enabled! - before_action :authenticate_signature! - before_action :validate_invite_email! - - feature_category :authentication_and_authorization - - def create - webhook_processor.execute - - head :ok - end - - private - - def ensure_feature_enabled! - render_406 unless Gitlab::CurrentSettings.mailgun_events_enabled? - end - - def authenticate_signature! - access_denied! unless valid_signature? - end - - def valid_signature? - return false if Gitlab::CurrentSettings.mailgun_signing_key.blank? - - # per this guide: https://documentation.mailgun.com/en/latest/user_manual.html#webhooks - digest = OpenSSL::Digest.new('SHA256') - data = [params.dig(:signature, :timestamp), params.dig(:signature, :token)].join - - hmac_digest = OpenSSL::HMAC.hexdigest(digest, Gitlab::CurrentSettings.mailgun_signing_key, data) - - ActiveSupport::SecurityUtils.secure_compare(params.dig(:signature, :signature), hmac_digest) - end - - def validate_invite_email! - # permanent_failures webhook does not provide a way to filter failures, so we'll get them all on this endpoint - # and we only care about our invite_emails - render_406 unless payload[:tags]&.include?(::Members::Mailgun::INVITE_EMAIL_TAG) - end - - def webhook_processor - ::Members::Mailgun::ProcessWebhookService.new(payload) - end - - def payload - @payload ||= params.permit!['event-data'] - end - - def render_406 - # failure to stop retries per https://documentation.mailgun.com/en/latest/user_manual.html#webhooks - head :not_acceptable - end - end - end -end diff --git a/app/mailers/emails/members.rb b/app/mailers/emails/members.rb index 5940f8e5a33..fe2d2891547 100644 --- a/app/mailers/emails/members.rb +++ b/app/mailers/emails/members.rb @@ -154,10 +154,10 @@ module Emails end def invite_email_headers - if Gitlab::CurrentSettings.mailgun_events_enabled? + if Gitlab.dev_env_or_com? { - 'X-Mailgun-Tag' => ::Members::Mailgun::INVITE_EMAIL_TAG, - 'X-Mailgun-Variables' => { ::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY => @token }.to_json + 'X-Mailgun-Tag' => 'invite_email', + 'X-Mailgun-Variables' => { 'invite_token' => @token }.to_json } else {} diff --git a/app/services/members/mailgun.rb b/app/services/members/mailgun.rb deleted file mode 100644 index 43fb5a14ef1..00000000000 --- a/app/services/members/mailgun.rb +++ /dev/null @@ -1,8 +0,0 @@ -# frozen_string_literal: true - -module Members - module Mailgun - INVITE_EMAIL_TAG = 'invite_email' - INVITE_EMAIL_TOKEN_KEY = :invite_token - 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 e359a83ad42..00000000000 --- a/app/services/members/mailgun/process_webhook_service.rb +++ /dev/null @@ -1,39 +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 - - 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/views/admin/application_settings/_mailgun.html.haml b/app/views/admin/application_settings/_mailgun.html.haml index 40b4d5cac6d..6204f7df5dc 100644 --- a/app/views/admin/application_settings/_mailgun.html.haml +++ b/app/views/admin/application_settings/_mailgun.html.haml @@ -1,3 +1,5 @@ +- return unless Feature.enabled?(:mailgun_events_receiver) + - expanded = integration_expanded?('mailgun_') %section.settings.as-mailgun.no-animate#js-mailgun-settings{ class: ('expanded' if expanded) } .settings-header diff --git a/app/views/admin/application_settings/network.html.haml b/app/views/admin/application_settings/network.html.haml index 72a27e4523f..500b7b95189 100644 --- a/app/views/admin/application_settings/network.html.haml +++ b/app/views/admin/application_settings/network.html.haml @@ -68,7 +68,8 @@ %button.btn.gl-button.btn-default.js-settings-toggle{ type: 'button' } = expanded_by_default? ? _('Collapse') : _('Expand') %p - = _('Configure limit for issues created per minute by web and API requests.') + = _('Limit the number of issues per minute a user can create through web and API requests.') + = link_to _('Learn more.'), help_page_path('user/admin_area/settings/rate_limit_on_issues_creation.md'), target: '_blank', rel: 'noopener noreferrer' .settings-content = render 'issue_limits' diff --git a/app/views/layouts/nav/sidebar/_group_menus.html.haml b/app/views/layouts/nav/sidebar/_group_menus.html.haml index 40d994bdf36..42114287cdf 100644 --- a/app/views/layouts/nav/sidebar/_group_menus.html.haml +++ b/app/views/layouts/nav/sidebar/_group_menus.html.haml @@ -1,20 +1,3 @@ -- if group_sidebar_link?(:runners) - = nav_link(path: 'groups/runners#index') do - = link_to group_runners_path(@group), title: _('CI/CD'), class: 'has-sub-items' do - .nav-icon-container - = sprite_icon('rocket') - %span.nav-item-name - = _('CI/CD') - %ul.sidebar-sub-level-items - = nav_link(path: 'groups/runners#index', html_options: { class: "fly-out-top-item" } ) do - = link_to group_runners_path(@group), title: _('CI/CD') do - %strong.fly-out-top-item-name - = _('CI/CD') - %li.divider.fly-out-top-item - = nav_link(path: 'groups/runners#index') do - = link_to group_runners_path(@group), title: s_('Runners|Runners') do - %span= s_('Runners|Runners') - - if group_sidebar_link?(:kubernetes) = nav_link(controller: [:clusters]) do = link_to group_clusters_path(@group) do diff --git a/config/feature_flags/development/mailgun_events_receiver.yml b/config/feature_flags/development/mailgun_events_receiver.yml new file mode 100644 index 00000000000..119d8d34f21 --- /dev/null +++ b/config/feature_flags/development/mailgun_events_receiver.yml @@ -0,0 +1,8 @@ +--- +name: mailgun_events_receiver +introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64249 +rollout_issue_url: +milestone: '14.1' +type: development +group: group::expansion +default_enabled: false diff --git a/config/metrics/counts_28d/20210216180424_i_search_total_monthly.yml b/config/metrics/counts_28d/20210216180424_i_search_total_monthly.yml index d678e6c3c91..dfec960830d 100644 --- a/config/metrics/counts_28d/20210216180424_i_search_total_monthly.yml +++ b/config/metrics/counts_28d/20210216180424_i_search_total_monthly.yml @@ -10,6 +10,10 @@ value_type: number status: data_available time_frame: 28d data_source: redis_hll +instrumentation_class: RedisHLLMetric +options: + events: + - i_search_total distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216180431_search_total_unique_counts_monthly.yml b/config/metrics/counts_28d/20210216180431_search_total_unique_counts_monthly.yml index ec39054bffb..2bb0d4edc0d 100644 --- a/config/metrics/counts_28d/20210216180431_search_total_unique_counts_monthly.yml +++ b/config/metrics/counts_28d/20210216180431_search_total_unique_counts_monthly.yml @@ -10,6 +10,12 @@ value_type: number status: data_available time_frame: 28d data_source: redis_hll +instrumentation_class: RedisHLLMetric +options: + events: + - i_search_total + - i_search_advanced + - i_search_paid distribution: - ce - ee diff --git a/config/metrics/counts_28d/20210216183922_search_unique_visits_for_any_target_monthly.yml b/config/metrics/counts_28d/20210216183922_search_unique_visits_for_any_target_monthly.yml index ef051f7031e..15939ae2a9d 100644 --- a/config/metrics/counts_28d/20210216183922_search_unique_visits_for_any_target_monthly.yml +++ b/config/metrics/counts_28d/20210216183922_search_unique_visits_for_any_target_monthly.yml @@ -10,6 +10,12 @@ value_type: number status: data_available time_frame: 28d data_source: redis_hll +instrumentation_class: RedisHLLMetric +options: + events: + - i_search_total + - i_search_advanced + - i_search_paid distribution: - ce - ee diff --git a/config/metrics/counts_7d/20210216180422_i_search_total_weekly.yml b/config/metrics/counts_7d/20210216180422_i_search_total_weekly.yml index af0ba376863..c88b9ad8bb8 100644 --- a/config/metrics/counts_7d/20210216180422_i_search_total_weekly.yml +++ b/config/metrics/counts_7d/20210216180422_i_search_total_weekly.yml @@ -10,6 +10,10 @@ value_type: number status: data_available time_frame: 7d data_source: redis_hll +instrumentation_class: RedisHLLMetric +options: + events: + - i_search_total distribution: - ee - ce diff --git a/config/metrics/counts_7d/20210216180429_search_total_unique_counts_weekly.yml b/config/metrics/counts_7d/20210216180429_search_total_unique_counts_weekly.yml index fb889331ead..440e99d642c 100644 --- a/config/metrics/counts_7d/20210216180429_search_total_unique_counts_weekly.yml +++ b/config/metrics/counts_7d/20210216180429_search_total_unique_counts_weekly.yml @@ -10,6 +10,12 @@ value_type: number status: data_available time_frame: 7d data_source: redis_hll +instrumentation_class: RedisHLLMetric +options: + events: + - i_search_total + - i_search_advanced + - i_search_paid distribution: - ee - ce diff --git a/config/routes.rb b/config/routes.rb index ff979d7da10..a4404f9d3a8 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -221,7 +221,6 @@ Rails.application.routes.draw do draw :snippets draw :profile - draw :members # Product analytics collector match '/collector/i', to: ProductAnalytics::CollectorApp.new, via: :all diff --git a/config/routes/members.rb b/config/routes/members.rb deleted file mode 100644 index e84f0987171..00000000000 --- a/config/routes/members.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -namespace :members do - namespace :mailgun do - resources :permanent_failures, only: [:create] - end -end diff --git a/db/migrate/20210719192928_add_invite_email_success_to_member.rb b/db/migrate/20210719192928_add_invite_email_success_to_member.rb index 40feb13a564..ad629483a82 100644 --- a/db/migrate/20210719192928_add_invite_email_success_to_member.rb +++ b/db/migrate/20210719192928_add_invite_email_success_to_member.rb @@ -2,12 +2,10 @@ class AddInviteEmailSuccessToMember < ActiveRecord::Migration[6.1] def up - unless column_exists?(:members, :invite_email_success) - add_column :members, :invite_email_success, :boolean, null: false, default: true - end + # no-op end def down - remove_column :members, :invite_email_success + # no-op end end diff --git a/db/structure.sql b/db/structure.sql index d6620c1b78e..1fcc8804893 100644 --- a/db/structure.sql +++ b/db/structure.sql @@ -14758,8 +14758,7 @@ CREATE TABLE members ( requested_at timestamp without time zone, expires_at date, ldap boolean DEFAULT false NOT NULL, - override boolean DEFAULT false NOT NULL, - invite_email_success boolean DEFAULT true NOT NULL + override boolean DEFAULT false NOT NULL ); CREATE SEQUENCE members_id_seq diff --git a/doc/administration/integration/mailgun.md b/doc/administration/integration/mailgun.md deleted file mode 100644 index 6486cc9de04..00000000000 --- a/doc/administration/integration/mailgun.md +++ /dev/null @@ -1,41 +0,0 @@ ---- -stage: Growth -group: Expansion -info: To determine the technical writer assigned to the Stage/Group associated with this page, see https://about.gitlab.com/handbook/engineering/ux/technical-writing/#assignments -type: reference, howto ---- - -# Mailgun and GitLab **(FREE SELF)** - -When you use Mailgun to send emails for your GitLab instance and [Mailgun](https://www.mailgun.com/) -integration is enabled and configured in GitLab, you can receive their webhook for -permanent invite email failures. To set up the integration, you must: - -1. [Configure your Mailgun domain](#configure-your-mailgun-domain). -1. [Enable Mailgun integration](#enable-mailgun-integration). - -After completing the integration, Mailgun `permanent_failure` webhooks are sent to your GitLab instance. - -## Configure your Mailgun domain - -Before you can enable Mailgun in GitLab, set up your own Mailgun permanent failure endpoint to receive the webhooks. - -Using the [Mailgun webhook guide](https://www.mailgun.com/blog/a-guide-to-using-mailguns-webhooks/): - -1. Add a webhook with the **Event type** set to **Permanent Failure**. -1. Fill in the URL of your instance and include the `/-/members/mailgun/permanent_failures` path. - - Example: `https://myinstance.gitlab.com/-/members/mailgun/permanent_failures` - -## Enable Mailgun integration - -After configuring your Mailgun domain for the permanent failures endpoint, -you're ready to enable the Mailgun integration: - -1. Sign in to GitLab as an [Administrator](../../user/permissions.md) user. -1. On the top bar, select **Menu >** **{admin}** **Admin**. -1. In the left sidebar, go to **Settings > General** and expand the **Mailgun** section. -1. Select the **Enable Mailgun** check box. -1. Enter the Mailgun HTTP webhook signing key as described in - [the Mailgun documentation](https://documentation.mailgun.com/en/latest/user_manual.html#webhooks) and - shown in the [API security](https://app.mailgun.com/app/account/security/api_keys) section for your Mailgun account. -1. Select **Save changes**. diff --git a/doc/api/graphql/removed_items.md b/doc/api/graphql/removed_items.md index d8fc6cb35f8..1c425d5f1d5 100644 --- a/doc/api/graphql/removed_items.md +++ b/doc/api/graphql/removed_items.md @@ -41,8 +41,8 @@ Fields removed in [GitLab 14.0](https://gitlab.com/gitlab-org/gitlab/-/merge_req Fields removed in [GitLab 13.6](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/44866): | Field name | GraphQL type | Deprecated in | Use instead | -| -------------------- | -------------------- | ------------- | -------------------------- | -| `date` | `Timelog` **(STARTER)** | 12.10 | `spentAt` | +|----------------------|--------------------------|---------------|----------------------------| +| `date` | `Timelog` | 12.10 | `spentAt` | | `designs` | `Issue`, `EpicIssue` | 12.2 | `designCollection` | | `latestPipeline` | `Commit` | 12.5 | `pipelines` | | `mergeCommitMessage` | `MergeRequest` | 11.8 | `latestMergeCommitMessage` | diff --git a/doc/api/settings.md b/doc/api/settings.md index 671a9c008fc..e3366cf176c 100644 --- a/doc/api/settings.md +++ b/doc/api/settings.md @@ -328,7 +328,7 @@ listed in the descriptions of the relevant settings. | `issues_create_limit` | integer | no | Max number of issue creation requests per minute per user. Disabled by default.| | `keep_latest_artifact` | boolean | no | Prevent the deletion of the artifacts from the most recent successful jobs, regardless of the expiry time. Enabled by default. | | `local_markdown_version` | integer | no | Increase this value when any cached Markdown should be invalidated. | -| `mailgun_signing_key` | string | no | The Mailgun HTTP webhook signing key for receiving events from webhook. | +| `mailgun_signing_key` | string | no | The Mailgun HTTP webhook signing key for receiving events from webhook | | `mailgun_events_enabled` | boolean | no | Enable Mailgun event receiver. | | `maintenance_mode_message` | string | no | **(PREMIUM)** Message displayed when instance is in maintenance mode. | | `maintenance_mode` | boolean | no | **(PREMIUM)** When instance is in maintenance mode, non-administrative users can sign in with read-only access and make read-only API requests. | diff --git a/doc/api/users.md b/doc/api/users.md index beed816f387..e389759a9ba 100644 --- a/doc/api/users.md +++ b/doc/api/users.md @@ -434,7 +434,7 @@ Parameters: | `email` | Yes | Email | | `extern_uid` | No | External UID | | `external` | No | Flags the user as external - true or false (default) | -| `extra_shared_runners_minutes_limit` | No | Extra pipeline minutes quota for this user (purchased in addition to the minutes included in the plan) **(STARTER)** | +| `extra_shared_runners_minutes_limit` | No | Extra pipeline minutes quota for this user (purchased in addition to the minutes included in the plan) **(PREMIUM)** | | `force_random_password` | No | Set user password to a random value - true or false (default) | | `group_id_for_saml` | No | ID of group where SAML has been configured | | `linkedin` | No | LinkedIn | @@ -447,7 +447,7 @@ Parameters: | `projects_limit` | No | Number of projects user can create | | `provider` | No | External provider name | | `reset_password` | No | Send user password reset link - true or false(default) | -| `shared_runners_minutes_limit` | No | Pipeline minutes quota for this user (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` **(STARTER)** | +| `shared_runners_minutes_limit` | No | Pipeline minutes quota for this user (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` **(PREMIUM)** | | `skip_confirmation` | No | Skip confirmation - true or false (default) | | `skype` | No | Skype ID | | `theme_id` | No | The GitLab theme for the user (see [the user preference docs](../user/profile/preferences.md#navigation-theme) for more information) | @@ -476,7 +476,7 @@ Parameters: | `email` | No | Email | | `extern_uid` | No | External UID | | `external` | No | Flags the user as external - true or false (default) | -| `extra_shared_runners_minutes_limit` | No | Extra pipeline minutes quota for this user (purchased in addition to the minutes included in the plan) **(STARTER)** | +| `extra_shared_runners_minutes_limit` | No | Extra pipeline minutes quota for this user (purchased in addition to the minutes included in the plan) **(PREMIUM)** | | `group_id_for_saml` | No | ID of group where SAML has been configured | | `id` | Yes | The ID of the user | | `linkedin` | No | LinkedIn | @@ -489,7 +489,7 @@ Parameters: | `projects_limit` | No | Limit projects each user can create | | `provider` | No | External provider name | | `public_email` | No | The public email of the user (must be already verified) | -| `shared_runners_minutes_limit` | No | Pipeline minutes quota for this user (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` **(STARTER)** | +| `shared_runners_minutes_limit` | No | Pipeline minutes quota for this user (included in plan). Can be `nil` (default; inherit system default), `0` (unlimited) or `> 0` **(PREMIUM)** | | `skip_reconfirmation` | No | Skip reconfirmation - true or false (default) | | `skype` | No | Skype ID | | `theme_id` | No | The GitLab theme for the user (see [the user preference docs](../user/profile/preferences.md#navigation-theme) for more information) | @@ -859,9 +859,13 @@ Example response: Get the counts (same as in top right menu) of the currently signed in user. -| Attribute | Type | Description | -| ---------------- | ------ | ------------------------------------------------------------ | -| `merge_requests` | number | Merge requests that are active and assigned to current user. | +| Attribute | Type | Description | +| --------------------------------- | ------ | ---------------------------------------------------------------------------- | +| `assigned_issues` | number | Number of issues that are open and assigned to the current user. [Added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66909) in GitLab 14.2. | +| `assigned_merge_requests` | number | Number of merge requests that are active and assigned to the current user. [Added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50026) in GitLab 13.8. | +| `merge_requests` | number | [Deprecated](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50026) in GitLab 13.8. Equivalent to and replaced by `assigned_merge_requests`. | +| `review_requested_merge_requests` | number | Number of merge requests that the current user has been requested to review. [Added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50026) in GitLab 13.8. | +| `todos` | number | Number of pending to-do items for current user. [Added](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/66909) in GitLab 14.2. | ```plaintext GET /user_counts @@ -875,7 +879,11 @@ Example response: ```json { - "merge_requests": 4 + "merge_requests": 4, + "assigned_issues": 15, + "assigned_merge_requests": 11, + "review_requested_merge_requests": 0, + "todos": 1 } ``` diff --git a/doc/development/documentation/styleguide/word_list.md b/doc/development/documentation/styleguide/word_list.md index b3c0fb19565..e34f494d0be 100644 --- a/doc/development/documentation/styleguide/word_list.md +++ b/doc/development/documentation/styleguide/word_list.md @@ -108,6 +108,10 @@ Try to avoid. Be as specific as you can. Do not use **and so on** as a replaceme - Avoid: You can update objects, like merge requests, issues, etc. - Use instead: You can update objects, like merge requests and issues. +## foo + +Do not use in product documentation. You can use it in our API and contributor documentation, but try to use a clearer and more meaningful example instead. + ## future tense When possible, use present tense instead. For example, use `after you execute this command, GitLab displays the result` instead of `after you execute this command, GitLab will display the result`. ([Vale](../testing.md#vale) rule: [`FutureTense.yml`](https://gitlab.com/gitlab-org/gitlab/-/blob/master/doc/.vale/gitlab/FutureTense.yml)) diff --git a/doc/raketasks/backup_restore.md b/doc/raketasks/backup_restore.md index 7fc19566a52..250abf2fa60 100644 --- a/doc/raketasks/backup_restore.md +++ b/doc/raketasks/backup_restore.md @@ -1481,7 +1481,7 @@ If this happens, examine the following: > - For GitLab self-managed instances, GitLab administrators can opt to [disable it](#disable-or-enable-gitaly-backup). There can be -[risks when disabling released features](../user/feature_flags.md#risks-when-disabling-released-features). +[risks when disabling released features](../administration/feature_flags.md#risks-when-disabling-released-features). Refer to this feature's version history for more details. `gitaly-backup` is used by the backup Rake task to create and restore repository backups from Gitaly. diff --git a/doc/user/admin_area/settings/help_page.md b/doc/user/admin_area/settings/help_page.md index f79c9e58162..6b6987634d9 100644 --- a/doc/user/admin_area/settings/help_page.md +++ b/doc/user/admin_area/settings/help_page.md @@ -67,7 +67,7 @@ You can specify a custom URL to which users are directed when they: > - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](#enable-or-disable-gitlab-documentation-link-redirects). **(FREE SELF)** This in-development feature might not be available for your use. There can be -[risks when enabling features still in development](../../feature_flags.md#risks-when-enabling-features-still-in-development). +[risks when enabling features still in development](../../../administration/feature_flags.md#risks-when-enabling-features-still-in-development). Refer to this feature's version history for more details. Documentation links go to the `/help` section on the instance by default, but you can diff --git a/doc/user/admin_area/settings/img/rate_limit_on_issues_creation_v13_1.png b/doc/user/admin_area/settings/img/rate_limit_on_issues_creation_v13_1.png deleted file mode 100644 index 9edc916c7fb..00000000000 Binary files a/doc/user/admin_area/settings/img/rate_limit_on_issues_creation_v13_1.png and /dev/null differ diff --git a/doc/user/admin_area/settings/img/rate_limit_on_issues_creation_v14_2.png b/doc/user/admin_area/settings/img/rate_limit_on_issues_creation_v14_2.png new file mode 100644 index 00000000000..63f4d5a4a1a Binary files /dev/null and b/doc/user/admin_area/settings/img/rate_limit_on_issues_creation_v14_2.png differ diff --git a/doc/user/admin_area/settings/index.md b/doc/user/admin_area/settings/index.md index 92b8cd03009..6f8aa6a2e04 100644 --- a/doc/user/admin_area/settings/index.md +++ b/doc/user/admin_area/settings/index.md @@ -39,7 +39,6 @@ To access the default page for Admin Area settings: | ------ | ----------- | | [Elasticsearch](../../../integration/elasticsearch.md#enabling-advanced-search) | Elasticsearch integration. Elasticsearch AWS IAM. | | [Kroki](../../../administration/integration/kroki.md#enable-kroki-in-gitlab) | Allow rendering of diagrams in AsciiDoc and Markdown documents using [kroki.io](https://kroki.io). | -| [Mailgun](../../../administration/integration/mailgun.md) | Enable your GitLab instance to receive invite email bounce events from Mailgun, if it is your email provider. | | [PlantUML](../../../administration/integration/plantuml.md) | Allow rendering of PlantUML diagrams in documents. | | [Slack application](../../../user/project/integrations/gitlab_slack_application.md#configuration) **(FREE SAAS)** | Slack integration allows you to interact with GitLab via slash commands in a chat window. This option is only available on GitLab.com, though it may be [available for self-managed instances in the future](https://gitlab.com/gitlab-org/gitlab/-/issues/28164). | | [Third party offers](third_party_offers.md) | Control the display of third party offers. | diff --git a/doc/user/admin_area/settings/rate_limit_on_issues_creation.md b/doc/user/admin_area/settings/rate_limit_on_issues_creation.md index ef2b8ad80cd..f4422473ce4 100644 --- a/doc/user/admin_area/settings/rate_limit_on_issues_creation.md +++ b/doc/user/admin_area/settings/rate_limit_on_issues_creation.md @@ -22,7 +22,7 @@ For example, if you set a limit of 300, requests using the [Projects::IssuesController#create](https://gitlab.com/gitlab-org/gitlab/raw/master/app/controllers/projects/issues_controller.rb) action exceeding a rate of 300 per minute are blocked. Access to the endpoint is allowed after one minute. -![Rate limits on issues creation](img/rate_limit_on_issues_creation_v13_1.png) +![Rate limits on issues creation](img/rate_limit_on_issues_creation_v14_2.png) This limit is: diff --git a/doc/user/project/code_owners.md b/doc/user/project/code_owners.md index 32ad0db1866..7d51fb59793 100644 --- a/doc/user/project/code_owners.md +++ b/doc/user/project/code_owners.md @@ -11,7 +11,7 @@ type: reference > - Code Owners for merge request approvals was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/4418) in GitLab Premium 11.9. > - Moved to GitLab Premium in 13.9. -Code Owners define who owns specific files or folders in a repository. +Code Owners define who owns specific files or directories in a repository. - The users you define as Code Owners are displayed in the UI when you browse directories. - You can set your merge requests so they must be approved by Code Owners before merge. @@ -23,7 +23,7 @@ If you don't want to use Code Owners for approvals, you can ## Set up Code Owners You can use Code Owners to specify users or [shared groups](members/share_project_with_groups.md) -that are responsible for specific files and folders in a repository. +that are responsible for specific files and directories in a repository. To set up Code Owners: @@ -41,24 +41,65 @@ To set up Code Owners: filename @username1 @username2 # Code Owners for a directory - foldername @username1 @username2 + directoryname/ @username1 @username2 # All group members as Code Owners for a file filename @groupname - # All group members as Code Owners for a folder - foldername @groupname + # All group members as Code Owners for a directory + directoryname/ @groupname ``` -The Code Owners are now displayed in the UI. +The Code Owners are now displayed in the UI. They apply to the current branch only. Next steps: - [Add Code Owners as merge request approvers](merge_requests/approvals/rules.md#code-owners-as-eligible-approvers). - Set up [Code Owner approval on a protected branch](protected_branches.md#require-code-owner-approval-on-a-protected-branch). -NOTE: -The Code Owners apply to the current branch only. +## Groups as Code Owners + +> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53182) in GitLab 12.1. +> - Group and subgroup hierarchy support was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32432) in GitLab 13.0. + +You can use members of groups and subgroups as Code Owners for a project. + +For example, if you have these groups: + +- **Group X** (`group-x`) with **Project A** in it. +- **Subgroup Y** (`group-x/subgroup-y`), which belongs to **Group X**, with **Project B** in it. + +The eligible Code Owners: + +- For **Project A** are the members of **Group X** only, because **Project A** doesn't belong to **Subgroup Y**. +- For **Project B** are the members of both **Group X** and **Subgroup Y**. + +![Eligible Code Owners](img/code_owners_members_v13_4.png) + +You can [invite](members/share_project_with_groups.md) **Subgroup Y** to **Project A** +so that their members also become eligible Code Owners. + +![Invite subgroup members to become eligible Code Owners](img/code_owners_invite_members_v13_4.png) + +If you do not invite **Subgroup Y** to **Project A**, but make them Code Owners, their approval +of the merge request becomes optional. + +### Add a group as a Code Owner + +To set a group as a Code Owner: + +In the `CODEOWNERS` file, enter text that follows one of these patterns: + +```plaintext +# All group members as Code Owners for a file +file.md @group-x + +# All subgroup members as Code Owners for a file +file.md @group-x/subgroup-y + +# All group and subgroup members as Code Owners for a file +file.md @group-x @group-x/subgroup-y +``` ## When a file matches multiple `CODEOWNERS` entries @@ -74,83 +115,24 @@ README.md @user1 *.md @user2 ``` -The user that would show for `README.md` would be `@user2`. +The Code Owner for `README.md` would be `@user2`. -## Groups as Code Owners +If you use sections, the last user _for each section_ is used. -> - [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/53182) in GitLab 12.1. -> - Group and subgroup hierarchy support was [introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/32432) in GitLab 13.0. +Only one CODEOWNERS pattern can match per file path. -Groups and subgroups members are inherited as eligible Code Owners to a -project, as long as the hierarchy is respected. - -For example, consider a given group called "Group X" (slug `group-x`) and a -"Subgroup Y" (slug `group-x/subgroup-y`) that belongs to the Group X, and -suppose you have a project called "Project A" within the group and a -"Project B" within the subgroup. - -The eligible Code Owners to Project B are both the members of the Group X and -the Subgroup Y. The eligible Code Owners to the Project A are just the -members of the Group X, given that Project A doesn't belong to the Subgroup Y: - -![Eligible Code Owners](img/code_owners_members_v13_4.png) - -But you have the option to [invite](members/share_project_with_groups.md) -the Subgroup Y to the Project A so that their members also become eligible -Code Owners: - -NOTE: -If you do not invite Subgroup Y to Project A, but make them Code Owners, their approval -of the merge request becomes optional. - -![Invite subgroup members to become eligible Code Owners](img/code_owners_invite_members_v13_4.png) - -After being invited, any member (`@user`) of the group or subgroup can be set -as Code Owner to files of the Project A or B, and the entire Group X -(`@group-x`) or Subgroup Y (`@group-x/subgroup-y`), as follows: - -```plaintext -# A member of the group or subgroup as Code Owner to a file -file.md @user - -# All group members as Code Owners to a file -file.md @group-x - -# All subgroup members as Code Owners to a file -file.md @group-x/subgroup-y - -# All group and subgroup members as Code Owners to a file -file.md @group-x @group-x/subgroup-y -``` - -### Code Owners sections **(PREMIUM)** +### Organize Code Owners by putting them into sections > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12137) in GitLab Premium 13.2 behind a feature flag, enabled by default. > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/42389) in GitLab 13.4. -Code Owner rules can be grouped into named sections. This allows for better -organization of broader categories of Code Owner rules to be applied. -Additionally, the usual guidance that only the last pattern matching the file is -applied is expanded such that the last pattern matching _for each section_ is -applied. +You can organize Code Owners by putting them into named sections. -For example, in a large organization, independent teams may have a common interest -in parts of the application, for instance, a payment processing company may have -"development", "security", and "compliance" teams looking after common parts of -the codebase. All three teams may need to approve changes. Although approval rules -make this possible, they apply to every merge request. Also, while Code Owners are -applied based on which files are changed, only one CODEOWNERS pattern can match per -file path. +You can use sections for shared directories, so that multiple +teams can be reviewers. -Using `CODEOWNERS` sections allows multiple teams that only need to approve certain -changes, to set their own independent patterns by specifying discrete sections in the -`CODEOWNERS` file. The section rules may be used for shared paths so that multiple -teams can be added as reviewers. - -Sections can be added to `CODEOWNERS` files as a new line with the name of the -section inside square brackets. Every entry following is assigned to that -section. The following example would create two Code Owner rules for the "README -Owners" section: +To add a section to the `CODEOWNERS` file, enter a section name in brackets, +followed by the files or directories, and users, groups, or subgroups: ```plaintext [README Owners] @@ -158,43 +140,41 @@ README.md @user1 @user2 internal/README.md @user2 ``` -Multiple sections can be used, even with matching file or directory patterns. -Reusing the same section name groups the results together under the same -section, with the most specific rule or last matching pattern being used. For -example, consider the following entries in a `CODEOWNERS` file: - -```plaintext -[Documentation] -ee/docs @gl-docs -docs @gl-docs - -[Database] -README.md @gl-database -model/db @gl-database - -[DOCUMENTATION] -README.md @gl-docs -``` - -This results in three entries under the "Documentation" section header, and two -entries under "Database". Case is not considered when combining sections, so in -this example, entries defined under the sections "Documentation" and -"DOCUMENTATION" would be combined into one, using the case of the first instance -of the section encountered in the file. - -When assigned to a section, each Code Owner rule displayed in merge requests -widget is sorted under a "section" label. In the screenshot below, we can see -the rules for "Groups" and "Documentation" sections: +Each Code Owner in the merge request widget is listed under a label. +The following image shows a **Groups** and **Documentation** section: ![MR widget - Sectional Code Owners](img/sectional_code_owners_v13.2.png) -#### Optional Code Owners sections **(PREMIUM)** +### Sections with duplicate names + +If multiple sections have the same name, they are combined. +Also, section headings are not case-sensitive. For example: + +```plaintext +[Documentation] +ee/docs/ @docs +docs/ @docs + +[Database] +README.md @database +model/db/ @database + +[DOCUMENTATION] +README.md @docs +``` + +This code results in three entries under the **Documentation** section header, and two +entries under **Database**. The entries defined under the sections **Documentation** and +**DOCUMENTATION** are combined, using the case of the first section. + +### Make a Code Owners section optional > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/232995) in GitLab Premium 13.8 behind a feature flag, enabled by default. > - [Feature flag removed](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/53227) in GitLab 13.9. -To make a certain section optional, add a Code Owners section prepended with the -caret `^` character. Approvals from owners listed in the section are **not** required. For example: +You can make a section optional, so that approval from the Code Owners in that section is optional. + +Put a caret `^` character before the Code Owners section name. For example: ```plaintext [Documentation] @@ -211,83 +191,64 @@ The optional Code Owners section displays in merge requests under the **Approval ![MR widget - Optional Code Owners sections](img/optional_code_owners_sections_v13_8.png) -If a section is duplicated in the file, and one of them is marked as optional and the other isn't, the requirement prevails. - -For example, the Code Owners of the "Documentation" section below is still required to approve merge requests: - -```plaintext -[Documentation] -*.md @root - -[Ruby] -*.rb @root - -^[Go] -*.go @root - -^[Documentation] -*.txt @root -``` +If a section is duplicated in the file, and one of them is marked as optional and the other isn't, the section is required. Optional sections in the `CODEOWNERS` file are treated as optional only when changes are submitted by using merge requests. If a change is submitted directly to the protected branch, approval from Code Owners is still required, even if the -section is marked as optional. We plan to change this behavior in a -[future release](https://gitlab.com/gitlab-org/gitlab/-/issues/297638), -and allow direct pushes to the protected branch for sections marked as optional. +section is marked as optional. [An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/297638) +to allow direct pushes to the protected branch for sections marked as optional. ## Example `CODEOWNERS` file ```plaintext -# This is an example of a CODEOWNERS file -# lines starting with a `#` will be ignored. +# This is an example of a CODEOWNERS file. +# Lines that start with `#` are ignored. # app/ @commented-rule -# We can specify a default match using wildcards: +# Specify a default Code Owner by using a wildcard: * @default-codeowner -# We can also specify "multiple tab or space" separated codeowners: +# Specify multiple Code Owners by using a tab or space: * @multiple @code @owners # Rules defined later in the file take precedence over the rules # defined before. -# This will match all files for which the file name ends in `.rb` +# For example, for all files with a filename ending in `.rb`: *.rb @ruby-owner -# Files with a `#` can still be accessed by escaping the pound sign +# Files with a `#` can still be accessed by escaping the pound sign: \#file_with_pound.rb @owner-file-with-pound -# Multiple codeowners can be specified, separated by spaces or tabs +# Specify multiple Code Owners separated by spaces or tabs. # In the following case the CODEOWNERS file from the root of the repo -# has 3 Code Owners (@multiple @code @owners) +# has 3 Code Owners (@multiple @code @owners): CODEOWNERS @multiple @code @owners -# Both usernames or email addresses can be used to match -# users. Everything else will be ignored. For example this will -# specify `@legal` and a user with email `janedoe@gitlab.com` as the -# owner for the LICENSE file +# You can use both usernames or email addresses to match +# users. Everything else is ignored. For example, this code +# specifies the `@legal` and a user with email `janedoe@gitlab.com` as the +# owner for the LICENSE file: LICENSE @legal this_does_not_match janedoe@gitlab.com -# Group names can be used to match groups and nested groups to specify -# them as owners for a file +# Use group names to match groups, and nested groups to specify +# them as owners for a file: README @group @group/with-nested/subgroup -# Ending a path in a `/` will specify the Code Owners for every file -# nested in that directory, on any level +# End a path in a `/` to specify the Code Owners for every file +# nested in that directory, on any level: /docs/ @all-docs -# Ending a path in `/*` will specify Code Owners for every file in -# that directory, but not nested deeper. This will match -# `docs/index.md` but not `docs/projects/index.md` +# End a path in `/*` to specify Code Owners for every file in +# a directory, but not nested deeper. This code matches +# `docs/index.md` but not `docs/projects/index.md`: /docs/* @root-docs -# This will make a `lib` directory nested anywhere in the repository -# match +# This code makes matches a `lib` directory nested anywhere in the repository: lib/ @lib-owner -# This will only match a `config` directory in the root of the -# repository +# This code match only a `config` directory in the root of the repository: /config/ @config-owner # If the path contains spaces, escape them like this: @@ -295,14 +256,14 @@ path\ with\ spaces/ @space-owner # Code Owners section: [Documentation] -ee/docs @gl-docs -docs @gl-docs +ee/docs @docs +docs @docs [Database] -README.md @gl-database -model/db @gl-database +README.md @database +model/db @database -# This section will be joined with the [Documentation] section previously defined: +# This section is combined with the previously defined [Documentation] section: [DOCUMENTATION] -README.md @gl-docs +README.md @docs ``` diff --git a/lib/api/user_counts.rb b/lib/api/user_counts.rb index 31c923a219a..634dd0f2179 100644 --- a/lib/api/user_counts.rb +++ b/lib/api/user_counts.rb @@ -6,15 +6,17 @@ module API resource :user_counts do desc 'Return the user specific counts' do - detail 'Open MR Count' + detail 'Assigned open issues, assigned MRs and pending todos count' end get do unauthorized! unless current_user { merge_requests: current_user.assigned_open_merge_requests_count, # @deprecated + assigned_issues: current_user.assigned_open_issues_count, assigned_merge_requests: current_user.assigned_open_merge_requests_count, - review_requested_merge_requests: current_user.review_requested_open_merge_requests_count + review_requested_merge_requests: current_user.review_requested_open_merge_requests_count, + todos: current_user.todos_pending_count } end end diff --git a/lib/sidebars/groups/menus/ci_cd_menu.rb b/lib/sidebars/groups/menus/ci_cd_menu.rb new file mode 100644 index 00000000000..e870bbf5ebc --- /dev/null +++ b/lib/sidebars/groups/menus/ci_cd_menu.rb @@ -0,0 +1,51 @@ +# frozen_string_literal: true + +module Sidebars + module Groups + module Menus + class CiCdMenu < ::Sidebars::Menu + override :configure_menu_items + def configure_menu_items + add_item(runners_menu_item) + + true + end + + override :link + def link + renderable_items.first.link + end + + override :title + def title + _('CI/CD') + end + + override :sprite_icon + def sprite_icon + 'rocket' + end + + private + + def runners_menu_item + return ::Sidebars::NilMenuItem.new(item_id: :runners) unless show_runners? + + ::Sidebars::MenuItem.new( + title: _('Runners'), + link: group_runners_path(context.group), + active_routes: { path: 'groups/runners#index' }, + item_id: :runners + ) + end + + # TODO Proper policies, such as `read_group_runners`, should be implemented per + # See https://gitlab.com/gitlab-org/gitlab/-/issues/334802 + def show_runners? + can?(context.current_user, :admin_group, context.group) && + Feature.enabled?(:runner_list_group_view_vue_ui, context.group, default_enabled: :yaml) + end + end + end + end +end diff --git a/lib/sidebars/groups/panel.rb b/lib/sidebars/groups/panel.rb index 8201ad0f180..398cbd73b2a 100644 --- a/lib/sidebars/groups/panel.rb +++ b/lib/sidebars/groups/panel.rb @@ -10,6 +10,7 @@ module Sidebars add_menu(Sidebars::Groups::Menus::GroupInformationMenu.new(context)) add_menu(Sidebars::Groups::Menus::IssuesMenu.new(context)) add_menu(Sidebars::Groups::Menus::MergeRequestsMenu.new(context)) + add_menu(Sidebars::Groups::Menus::CiCdMenu.new(context)) end override :render_raw_menus_partial diff --git a/locale/gitlab.pot b/locale/gitlab.pot index c2c89adee51..d59bc11fc65 100644 --- a/locale/gitlab.pot +++ b/locale/gitlab.pot @@ -8371,9 +8371,6 @@ msgstr "" msgid "Configure existing installation" msgstr "" -msgid "Configure limit for issues created per minute by web and API requests." -msgstr "" - msgid "Configure limit for notes created per minute by web and API requests." msgstr "" @@ -19741,6 +19738,9 @@ msgstr "" msgid "Limit the number of concurrent operations this secondary node can run in the background." msgstr "" +msgid "Limit the number of issues per minute a user can create through web and API requests." +msgstr "" + msgid "Limited to showing %d event at most" msgid_plural "Limited to showing %d events at most" msgstr[0] "" diff --git a/spec/experiments/application_experiment_spec.rb b/spec/experiments/application_experiment_spec.rb index 4966e508f7e..b288d074133 100644 --- a/spec/experiments/application_experiment_spec.rb +++ b/spec/experiments/application_experiment_spec.rb @@ -236,6 +236,11 @@ RSpec.describe ApplicationExperiment, :experiment do expect(subject.process_redirect_url(url)).to be_nil end end + + it "generates the correct urls based on where the engine was mounted" do + url = Rails.application.routes.url_helpers.experiment_redirect_url(subject, url: 'https://docs.gitlab.com') + expect(url).to include("/-/experiment/namespaced%2Fstub:#{subject.context.key}?https://docs.gitlab.com") + end end context "when resolving variants" do diff --git a/spec/experiments/new_project_readme_content_experiment_spec.rb b/spec/experiments/new_project_readme_content_experiment_spec.rb index f76b8a1ded1..a6a81580a29 100644 --- a/spec/experiments/new_project_readme_content_experiment_spec.rb +++ b/spec/experiments/new_project_readme_content_experiment_spec.rb @@ -30,9 +30,9 @@ RSpec.describe NewProjectReadmeContentExperiment, :experiment do end it "renders redirect URLs" do - expect(markdown).to include( - Rails.application.routes.url_helpers.experiment_redirect_url(subject, url: initial_url) - ) + url = Rails.application.routes.url_helpers.experiment_redirect_url(subject, url: initial_url) + expect(url).to include("/-/experiment/#{subject.to_param}?") + expect(markdown).to include(url) end end end diff --git a/spec/features/admin/admin_settings_spec.rb b/spec/features/admin/admin_settings_spec.rb index cc65e5753c0..fe4c532060b 100644 --- a/spec/features/admin/admin_settings_spec.rb +++ b/spec/features/admin/admin_settings_spec.rb @@ -269,7 +269,10 @@ RSpec.describe 'Admin updates settings' do end context 'Integrations page' do + let(:mailgun_events_receiver_enabled) { true } + before do + stub_feature_flags(mailgun_events_receiver: mailgun_events_receiver_enabled) visit general_admin_application_settings_path end @@ -283,16 +286,26 @@ RSpec.describe 'Admin updates settings' do expect(current_settings.hide_third_party_offers).to be true end - it 'enabling Mailgun events', :aggregate_failures do - page.within('.as-mailgun') do - check 'Enable Mailgun event receiver' - fill_in 'Mailgun HTTP webhook signing key', with: 'MAILGUN_SIGNING_KEY' - click_button 'Save changes' - end + context 'when mailgun_events_receiver feature flag is enabled' do + it 'enabling Mailgun events', :aggregate_failures do + page.within('.as-mailgun') do + check 'Enable Mailgun event receiver' + fill_in 'Mailgun HTTP webhook signing key', with: 'MAILGUN_SIGNING_KEY' + click_button 'Save changes' + end - expect(page).to have_content 'Application settings saved successfully' - expect(current_settings.mailgun_events_enabled).to be true - expect(current_settings.mailgun_signing_key).to eq 'MAILGUN_SIGNING_KEY' + expect(page).to have_content 'Application settings saved successfully' + expect(current_settings.mailgun_events_enabled).to be true + expect(current_settings.mailgun_signing_key).to eq 'MAILGUN_SIGNING_KEY' + end + end + + context 'when mailgun_events_receiver feature flag is disabled' do + let(:mailgun_events_receiver_enabled) { false } + + it 'does not have mailgun' do + expect(page).not_to have_selector('.as-mailgun') + end end end diff --git a/spec/lib/gitlab/import_export/safe_model_attributes.yml b/spec/lib/gitlab/import_export/safe_model_attributes.yml index 10162ade48b..77d126e012e 100644 --- a/spec/lib/gitlab/import_export/safe_model_attributes.yml +++ b/spec/lib/gitlab/import_export/safe_model_attributes.yml @@ -167,7 +167,6 @@ ProjectMember: - expires_at - ldap - override -- invite_email_success User: - id - username diff --git a/spec/lib/sidebars/groups/menus/ci_cd_menu_spec.rb b/spec/lib/sidebars/groups/menus/ci_cd_menu_spec.rb new file mode 100644 index 00000000000..1ba89af1b02 --- /dev/null +++ b/spec/lib/sidebars/groups/menus/ci_cd_menu_spec.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +require 'spec_helper' + +RSpec.describe Sidebars::Groups::Menus::CiCdMenu do + let_it_be(:owner) { create(:user) } + let_it_be(:root_group) do + build(:group, :private).tap do |g| + g.add_owner(owner) + end + end + + let(:group) { root_group } + let(:user) { owner } + let(:context) { Sidebars::Groups::Context.new(current_user: user, container: group) } + + describe 'Menu Items' do + subject { described_class.new(context).renderable_items.index { |e| e.item_id == item_id } } + + describe 'Runners' do + let(:item_id) { :runners } + + specify { is_expected.not_to be_nil } + + describe 'when feature flag :runner_list_group_view_vue_ui is disabled' do + before do + stub_feature_flags(runner_list_group_view_vue_ui: false) + end + + specify { is_expected.to be_nil } + end + + describe 'when the user does not have access' do + let(:user) { nil } + + specify { is_expected.to be_nil } + end + end + end +end diff --git a/spec/mailers/notify_spec.rb b/spec/mailers/notify_spec.rb index d00260a3bcd..240abfc5c53 100644 --- a/spec/mailers/notify_spec.rb +++ b/spec/mailers/notify_spec.rb @@ -832,15 +832,15 @@ RSpec.describe Notify do end end - context 'when mailgun events are enabled' do + context 'when on gitlab.com' do before do - stub_application_setting(mailgun_events_enabled: true) + allow(Gitlab).to receive(:dev_env_or_com?).and_return(true) end it 'has custom headers' do aggregate_failures do - expect(subject).to have_header('X-Mailgun-Tag', ::Members::Mailgun::INVITE_EMAIL_TAG) - expect(subject).to have_header('X-Mailgun-Variables', { ::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY => project_member.invite_token }.to_json) + expect(subject).to have_header('X-Mailgun-Tag', 'invite_email') + expect(subject).to have_header('X-Mailgun-Variables', { 'invite_token' => project_member.invite_token }.to_json) end end end diff --git a/spec/requests/api/user_counts_spec.rb b/spec/requests/api/user_counts_spec.rb index 94e25d647fc..ab2aa87d1b7 100644 --- a/spec/requests/api/user_counts_spec.rb +++ b/spec/requests/api/user_counts_spec.rb @@ -3,8 +3,10 @@ require 'spec_helper' RSpec.describe API::UserCounts do - let(:user) { create(:user) } - let(:project) { create(:project, :public) } + let_it_be(:user) { create(:user) } + let_it_be(:project) { create(:project, :public) } + let_it_be(:issue) { create(:issue, project: project, author: user, assignees: [user]) } + let_it_be(:todo) { create(:todo, :pending, user: user, project: project) } let!(:merge_request) { create(:merge_request, :simple, author: user, assignees: [user], source_project: project, title: "Test") } @@ -18,22 +20,36 @@ RSpec.describe API::UserCounts do end context 'when authenticated' do - it 'returns open counts for current user' do + it 'returns assigned issue counts for current_user' do get api('/user_counts', user) - expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to be_a Hash - expect(json_response['merge_requests']).to eq(1) + expect(json_response['assigned_issues']).to eq(1) end - it 'updates the mr count when a new mr is assigned' do - create(:merge_request, source_project: project, author: user, assignees: [user]) + context 'merge requests' do + it 'returns assigned MR counts for current user' do + get api('/user_counts', user) + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to be_a Hash + expect(json_response['merge_requests']).to eq(1) + end + + it 'updates the mr count when a new mr is assigned' do + create(:merge_request, source_project: project, author: user, assignees: [user]) + + get api('/user_counts', user) + + expect(response).to have_gitlab_http_status(:ok) + expect(json_response).to be_a Hash + expect(json_response['merge_requests']).to eq(2) + end + end + + it 'returns pending todo counts for current_user' do get api('/user_counts', user) - expect(response).to have_gitlab_http_status(:ok) - expect(json_response).to be_a Hash - expect(json_response['merge_requests']).to eq(2) + expect(json_response['todos']).to eq(1) end end end diff --git a/spec/requests/members/mailgun/permanent_failure_spec.rb b/spec/requests/members/mailgun/permanent_failure_spec.rb deleted file mode 100644 index e47aedf8e94..00000000000 --- a/spec/requests/members/mailgun/permanent_failure_spec.rb +++ /dev/null @@ -1,128 +0,0 @@ -# frozen_string_literal: true - -require 'spec_helper' - -RSpec.describe 'receive a permanent failure' do - describe 'POST /members/mailgun/permanent_failures', :aggregate_failures do - let_it_be(:member) { create(:project_member, :invited) } - - let(:raw_invite_token) { member.raw_invite_token } - let(:mailgun_events) { true } - let(:mailgun_signing_key) { 'abc123' } - - subject(:post_request) { post members_mailgun_permanent_failures_path(standard_params) } - - before do - stub_application_setting(mailgun_events_enabled: mailgun_events, mailgun_signing_key: mailgun_signing_key) - end - - it 'marks the member invite email success as false' do - expect { post_request }.to change { member.reload.invite_email_success }.from(true).to(false) - - expect(response).to have_gitlab_http_status(:ok) - end - - context 'when the change to a member is not made' do - context 'with incorrect signing key' do - context 'with incorrect signing key' do - let(:mailgun_signing_key) { '_foobar_' } - - it 'does not change member status and responds as not_found' do - expect { post_request }.not_to change { member.reload.invite_email_success } - - expect(response).to have_gitlab_http_status(:not_found) - end - end - - context 'with nil signing key' do - let(:mailgun_signing_key) { nil } - - it 'does not change member status and responds as not_found' do - expect { post_request }.not_to change { member.reload.invite_email_success } - - expect(response).to have_gitlab_http_status(:not_found) - end - end - end - - context 'when the feature is not enabled' do - let(:mailgun_events) { false } - - it 'does not change member status and responds as expected' do - expect { post_request }.not_to change { member.reload.invite_email_success } - - expect(response).to have_gitlab_http_status(:not_acceptable) - end - end - - context 'when it is not an invite email' do - before do - stub_const('::Members::Mailgun::INVITE_EMAIL_TAG', '_foobar_') - end - - it 'does not change member status and responds as expected' do - expect { post_request }.not_to change { member.reload.invite_email_success } - - expect(response).to have_gitlab_http_status(:not_acceptable) - end - end - end - - def standard_params - { - "signature": { - "timestamp": "1625056677", - "token": "eb944d0ace7227667a1b97d2d07276ae51d2b849ed2cfa68f3", - "signature": "9790cc6686eb70f0b1f869180d906870cdfd496d27fee81da0aa86b9e539e790" - }, - "event-data": { - "severity": "permanent", - "tags": ["invite_email"], - "timestamp": 1521233195.375624, - "storage": { - "url": "_anything_", - "key": "_anything_" - }, - "log-level": "error", - "id": "_anything_", - "campaigns": [], - "reason": "suppress-bounce", - "user-variables": { - "invite_token": raw_invite_token - }, - "flags": { - "is-routed": false, - "is-authenticated": true, - "is-system-test": false, - "is-test-mode": false - }, - "recipient-domain": "example.com", - "envelope": { - "sender": "bob@mg.gitlab.com", - "transport": "smtp", - "targets": "alice@example.com" - }, - "message": { - "headers": { - "to": "Alice ", - "message-id": "20130503192659.13651.20287@mg.gitlab.com", - "from": "Bob ", - "subject": "Test permanent_fail webhook" - }, - "attachments": [], - "size": 111 - }, - "recipient": "alice@example.com", - "event": "failed", - "delivery-status": { - "attempt-no": 1, - "message": "", - "code": 605, - "description": "Not delivering to previously bounced address", - "session-seconds": 0 - } - } - } - end - 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 d6a21183395..00000000000 --- a/spec/services/members/mailgun/process_webhook_service_spec.rb +++ /dev/null @@ -1,42 +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 -end diff --git a/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb b/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb index c00c3efe6d6..fc62fbda2cc 100644 --- a/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb +++ b/spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb @@ -3,10 +3,17 @@ require 'spec_helper' RSpec.describe 'layouts/nav/sidebar/_group' do - let_it_be(:group) { create(:group) } + let_it_be(:owner) { create(:user) } + let_it_be(:group) do + create(:group).tap do |g| + g.add_owner(owner) + end + end before do assign(:group, group) + + allow(view).to receive(:current_user).and_return(owner) end it_behaves_like 'has nav sidebar' @@ -79,4 +86,18 @@ RSpec.describe 'layouts/nav/sidebar/_group' do expect(rendered).to have_css('span.badge.badge-pill.merge_counter.js-merge-counter') end end + + describe 'CI/CD' do + it 'has a default link to the runners list path' do + render + + expect(rendered).to have_link('CI/CD', href: group_runners_path(group)) + end + + it 'has a link to the runners list page' do + render + + expect(rendered).to have_link('Runners', href: group_runners_path(group)) + end + end end