Welcome to mirror list, hosted at ThFree Co, Russian Federation.

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Gemfile2
-rw-r--r--Gemfile.lock4
-rw-r--r--app/controllers/members/mailgun/permanent_failures_controller.rb65
-rw-r--r--app/mailers/emails/members.rb6
-rw-r--r--app/services/members/mailgun.rb8
-rw-r--r--app/services/members/mailgun/process_webhook_service.rb39
-rw-r--r--app/views/admin/application_settings/_mailgun.html.haml2
-rw-r--r--app/views/admin/application_settings/network.html.haml3
-rw-r--r--app/views/layouts/nav/sidebar/_group_menus.html.haml17
-rw-r--r--config/feature_flags/development/mailgun_events_receiver.yml8
-rw-r--r--config/metrics/counts_28d/20210216180424_i_search_total_monthly.yml4
-rw-r--r--config/metrics/counts_28d/20210216180431_search_total_unique_counts_monthly.yml6
-rw-r--r--config/metrics/counts_28d/20210216183922_search_unique_visits_for_any_target_monthly.yml6
-rw-r--r--config/metrics/counts_7d/20210216180422_i_search_total_weekly.yml4
-rw-r--r--config/metrics/counts_7d/20210216180429_search_total_unique_counts_weekly.yml6
-rw-r--r--config/routes.rb1
-rw-r--r--config/routes/members.rb7
-rw-r--r--db/migrate/20210719192928_add_invite_email_success_to_member.rb6
-rw-r--r--db/structure.sql3
-rw-r--r--doc/administration/integration/mailgun.md41
-rw-r--r--doc/api/graphql/removed_items.md4
-rw-r--r--doc/api/settings.md2
-rw-r--r--doc/api/users.md24
-rw-r--r--doc/development/documentation/styleguide/word_list.md4
-rw-r--r--doc/raketasks/backup_restore.md2
-rw-r--r--doc/user/admin_area/settings/help_page.md2
-rw-r--r--doc/user/admin_area/settings/img/rate_limit_on_issues_creation_v13_1.pngbin13479 -> 0 bytes
-rw-r--r--doc/user/admin_area/settings/img/rate_limit_on_issues_creation_v14_2.pngbin0 -> 29368 bytes
-rw-r--r--doc/user/admin_area/settings/index.md1
-rw-r--r--doc/user/admin_area/settings/rate_limit_on_issues_creation.md2
-rw-r--r--doc/user/project/code_owners.md251
-rw-r--r--lib/api/user_counts.rb6
-rw-r--r--lib/sidebars/groups/menus/ci_cd_menu.rb51
-rw-r--r--lib/sidebars/groups/panel.rb1
-rw-r--r--locale/gitlab.pot6
-rw-r--r--spec/experiments/application_experiment_spec.rb5
-rw-r--r--spec/experiments/new_project_readme_content_experiment_spec.rb6
-rw-r--r--spec/features/admin/admin_settings_spec.rb29
-rw-r--r--spec/lib/gitlab/import_export/safe_model_attributes.yml1
-rw-r--r--spec/lib/sidebars/groups/menus/ci_cd_menu_spec.rb40
-rw-r--r--spec/mailers/notify_spec.rb8
-rw-r--r--spec/requests/api/user_counts_spec.rb38
-rw-r--r--spec/requests/members/mailgun/permanent_failure_spec.rb128
-rw-r--r--spec/services/members/mailgun/process_webhook_service_spec.rb42
-rw-r--r--spec/views/layouts/nav/sidebar/_group.html.haml_spec.rb23
45 files changed, 360 insertions, 554 deletions
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
--- a/doc/user/admin_area/settings/img/rate_limit_on_issues_creation_v13_1.png
+++ /dev/null
Binary files 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
--- /dev/null
+++ b/doc/user/admin_area/settings/img/rate_limit_on_issues_creation_v14_2.png
Binary files 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,116 +41,98 @@ 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.
-
-## When a file matches multiple `CODEOWNERS` entries
-
-When a file matches multiple entries in the `CODEOWNERS` file,
-the users from last pattern matching the file are used.
-
-For example, in the following `CODEOWNERS` file:
-
-```plaintext
-README.md @user1
-
-# This line would also match the file README.md
-*.md @user2
-```
-
-The user that would show for `README.md` would be `@user2`.
-
## 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.
-Groups and subgroups members are inherited as eligible Code Owners to a
-project, as long as the hierarchy is respected.
+You can use members of groups and subgroups as Code Owners for a project.
-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.
+For example, if you have these groups:
-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:
+- **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)
-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:
+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)
-NOTE:
-If you do not invite Subgroup Y to Project A, but make them Code Owners, their approval
+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)
+### Add a group as a Code Owner
-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:
+To set a group as a Code Owner:
-```plaintext
-# A member of the group or subgroup as Code Owner to a file
-file.md @user
+In the `CODEOWNERS` file, enter text that follows one of these patterns:
-# All group members as Code Owners to a file
+```plaintext
+# All group members as Code Owners for a file
file.md @group-x
-# All subgroup members as Code Owners to a file
+# All subgroup members as Code Owners for a file
file.md @group-x/subgroup-y
-# All group and subgroup members as Code Owners to a file
+# All group and subgroup members as Code Owners for a file
file.md @group-x @group-x/subgroup-y
```
-### Code Owners sections **(PREMIUM)**
+## When a file matches multiple `CODEOWNERS` entries
+
+When a file matches multiple entries in the `CODEOWNERS` file,
+the users from last pattern matching the file are used.
+
+For example, in the following `CODEOWNERS` file:
+
+```plaintext
+README.md @user1
+
+# This line would also match the file README.md
+*.md @user2
+```
+
+The Code Owner for `README.md` would be `@user2`.
+
+If you use sections, the last user _for each section_ is used.
+
+Only one CODEOWNERS pattern can match per file path.
+
+### 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.
-
-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.
-
-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:
+You can organize Code Owners by putting them into named sections.
+
+You can use sections for shared directories, so that multiple
+teams can be reviewers.
+
+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:
+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)
+
+### 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 @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
[DOCUMENTATION]
-README.md @gl-docs
+README.md @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.
+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.
-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:
-
-![MR widget - Sectional Code Owners](img/sectional_code_owners_v13.2.png)
-
-#### Optional Code Owners sections **(PREMIUM)**
+### 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'
+ 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'
end
+ 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'
+ 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 <alice@example.com>",
- "message-id": "20130503192659.13651.20287@mg.gitlab.com",
- "from": "Bob <bob@mg.gitlab.com>",
- "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