Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
cba9857205
commit
9e16447c7c
|
@ -1 +1 @@
|
|||
14.1.0
|
||||
14.1.1
|
||||
|
|
|
@ -40,7 +40,7 @@ export default {
|
|||
metric: 'active-record',
|
||||
title: 'pg',
|
||||
header: s__('PerformanceBar|SQL queries'),
|
||||
keys: ['sql', 'cached', 'transaction', 'db_role'],
|
||||
keys: ['sql', 'cached', 'transaction', 'db_role', 'db_config_name'],
|
||||
},
|
||||
{
|
||||
metric: 'bullet',
|
||||
|
|
|
@ -0,0 +1,65 @@
|
|||
# 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
|
|
@ -150,10 +150,10 @@ module Emails
|
|||
end
|
||||
|
||||
def invite_email_headers
|
||||
if Gitlab.dev_env_or_com?
|
||||
if Gitlab::CurrentSettings.mailgun_events_enabled?
|
||||
{
|
||||
'X-Mailgun-Tag' => 'invite_email',
|
||||
'X-Mailgun-Variables' => { 'invite_token' => @token }.to_json
|
||||
'X-Mailgun-Tag' => ::Members::Mailgun::INVITE_EMAIL_TAG,
|
||||
'X-Mailgun-Variables' => { ::Members::Mailgun::INVITE_EMAIL_TOKEN_KEY => @token }.to_json
|
||||
}
|
||||
else
|
||||
{}
|
||||
|
|
|
@ -0,0 +1,8 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Members
|
||||
module Mailgun
|
||||
INVITE_EMAIL_TAG = 'invite_email'
|
||||
INVITE_EMAIL_TOKEN_KEY = :invite_token
|
||||
end
|
||||
end
|
|
@ -0,0 +1,39 @@
|
|||
# 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
|
|
@ -1,5 +1,3 @@
|
|||
- 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
|
||||
|
|
|
@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/333034
|
|||
milestone: '14.0'
|
||||
type: development
|
||||
group: group::gitaly
|
||||
default_enabled: true
|
||||
default_enabled: false
|
||||
|
|
|
@ -1,8 +0,0 @@
|
|||
---
|
||||
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
|
|
@ -221,6 +221,7 @@ Rails.application.routes.draw do
|
|||
|
||||
draw :snippets
|
||||
draw :profile
|
||||
draw :members
|
||||
|
||||
# Product analytics collector
|
||||
match '/collector/i', to: ProductAnalytics::CollectorApp.new, via: :all
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
namespace :members do
|
||||
namespace :mailgun do
|
||||
resources :permanent_failures, only: [:create]
|
||||
end
|
||||
end
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
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
|
||||
end
|
||||
|
||||
def down
|
||||
remove_column :members, :invite_email_success
|
||||
end
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
eed403573697ac7f454ce47d6e4ab3561a10a62177caaaea40d5d70953068175
|
|
@ -14708,6 +14708,7 @@ CREATE TABLE members (
|
|||
expires_at date,
|
||||
ldap boolean DEFAULT false NOT NULL,
|
||||
override boolean DEFAULT false NOT NULL,
|
||||
invite_email_success boolean DEFAULT true NOT NULL,
|
||||
state smallint DEFAULT 0
|
||||
);
|
||||
|
||||
|
|
|
@ -0,0 +1,41 @@
|
|||
---
|
||||
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**.
|
|
@ -21,7 +21,20 @@ From left to right, the performance bar displays:
|
|||
- **Current Host**: the current host serving the page.
|
||||
- **Database queries**: the time taken (in milliseconds) and the total number
|
||||
of database queries, displayed in the format `00ms / 00 (00 cached) pg`. Click to display
|
||||
a modal window with more details.
|
||||
a modal window with more details. You can use this to see the following
|
||||
details for each query:
|
||||
- **In a transaction**: shows up below the query if it was executed in
|
||||
the context of a transaction
|
||||
- **Role**: shows up when [database load
|
||||
balancing](../../database_load_balancing.md) is enabled. It shows
|
||||
which server role was used for the query. "Primary" means that the query
|
||||
was sent to the read/write primary server. "Replica" means it was sent
|
||||
to a read-only replica.
|
||||
- **Config name**: shows up only when the
|
||||
`multiple_database_metrics` feature flag is enabled. This is used to
|
||||
distinguish between different databases configured for different GitLab
|
||||
features. The name shown is the same name used to configure database
|
||||
connections in GitLab.
|
||||
- **Gitaly calls**: the time taken (in milliseconds) and the total number of
|
||||
[Gitaly](../../gitaly/index.md) calls. Click to display a modal window with more
|
||||
details.
|
||||
|
|
|
@ -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. |
|
||||
|
|
|
@ -1472,47 +1472,3 @@ If this happens, examine the following:
|
|||
- Confirm there is sufficient disk space for the Gzip operation.
|
||||
- If NFS is being used, check if the mount option `timeout` is set. The
|
||||
default is `600`, and changing this to smaller values results in this error.
|
||||
|
||||
### `gitaly-backup` for repository backup and restore **(FREE SELF)**
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/333034) in GitLab 14.2.
|
||||
> - [Deployed behind a feature flag](../user/feature_flags.md), enabled by default.
|
||||
> - Recommended for production use.
|
||||
> - 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).
|
||||
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.
|
||||
`gitaly-backup` replaces the previous backup method that directly calls RPCs on Gitaly from GitLab.
|
||||
|
||||
The backup Rake task must be able to find this executable. It can be configured in Omnibus GitLab packages:
|
||||
|
||||
1. Add the following to `/etc/gitlab/gitlab.rb`:
|
||||
|
||||
```ruby
|
||||
gitlab_rails['backup_gitaly_backup_path'] = '/path/to/gitaly-backup'
|
||||
```
|
||||
|
||||
1. [Reconfigure GitLab](../administration/restart_gitlab.md#omnibus-gitlab-reconfigure)
|
||||
for the changes to take effect
|
||||
|
||||
#### Disable or enable `gitaly-backup`
|
||||
|
||||
`gitaly-backup` is under development but ready for production use.
|
||||
It is deployed behind a feature flag that is **enabled by default**.
|
||||
[GitLab administrators with access to the GitLab Rails console](../administration/feature_flags.md)
|
||||
can opt to disable it.
|
||||
|
||||
To disable it:
|
||||
|
||||
```ruby
|
||||
Feature.disable(:gitaly_backup)
|
||||
```
|
||||
|
||||
To enable it:
|
||||
|
||||
```ruby
|
||||
Feature.enable(:gitaly_backup)
|
||||
```
|
||||
|
|
|
@ -39,6 +39,7 @@ 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. |
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 15 KiB |
|
@ -7,21 +7,18 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Compliance report **(ULTIMATE)**
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36524) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.8.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/36524) in [GitLab Ultimate](https://about.gitlab.com/pricing/) 12.8 as Compliance Dashboard.
|
||||
> - [Renamed](https://gitlab.com/gitlab-org/gitlab/-/issues/299360) to compliance report in GitLab 14.2.
|
||||
|
||||
The compliance report gives you the ability to see a group's merge request activity
|
||||
by providing a high-level view for all projects in the group. For example, code approved
|
||||
for merging into production.
|
||||
Compliance report gives you the ability to see a group's merge request activity. It provides a
|
||||
high-level view for all projects in the group. For example, code approved for merging into
|
||||
production.
|
||||
|
||||
## Overview
|
||||
|
||||
To access the compliance report for a group, navigate to **{shield}** **Security & Compliance > Compliance** on the group's menu.
|
||||
|
||||
![Compliance report](img/compliance_report_v13_11.png)
|
||||
To access compliance report for a group, go to **{shield}** **Security & Compliance > Compliance**
|
||||
on the group's menu.
|
||||
|
||||
NOTE:
|
||||
The compliance report shows only the latest MR on each project.
|
||||
Compliance report shows only the latest merge request on each project.
|
||||
|
||||
## Merge request drawer
|
||||
|
||||
|
@ -67,7 +64,7 @@ Our criteria for the separation of duties is as follows:
|
|||
- [A merge request committer is **not** allowed to approve a merge request they have added commits to](../../project/merge_requests/approvals/settings.md#prevent-committers-from-approving-their-own-work)
|
||||
- [The minimum number of approvals required to merge a merge request is **at least** two](../../project/merge_requests/approvals/rules.md)
|
||||
|
||||
The "Approval status" column shows you, at a glance, whether a merge request is complying with the above.
|
||||
The **Approval status** column shows you at a glance whether a merge request is complying with the above.
|
||||
This column has four states:
|
||||
|
||||
| State | Description |
|
||||
|
@ -77,8 +74,7 @@ This column has four states:
|
|||
| ![Warning](img/warning_icon_v13_3.png) | The merge request complies with **some** of the above criteria |
|
||||
| ![Success](img/success_icon_v13_3.png) | The merge request complies with **all** of the above criteria |
|
||||
|
||||
If you do not see the success icon in your compliance report; please review the above criteria for the merge requests
|
||||
project to make sure it complies with the separation of duties described above.
|
||||
If you see a non-success state, review the criteria for the merge request's project to ensure it complies with the separation of duties.
|
||||
|
||||
## Chain of Custody report **(ULTIMATE)**
|
||||
|
||||
|
@ -87,7 +83,7 @@ project to make sure it complies with the separation of duties described above.
|
|||
The Chain of Custody report allows customers to export a list of merge commits within the group.
|
||||
The data provides a comprehensive view with respect to merge commits. It includes the merge commit SHA,
|
||||
merge request author, merge request ID, merge user, pipeline ID, group name, project name, and merge request approvers.
|
||||
Depending on the merge strategy, the merge commit SHA can either be a merge commit, squash commit or a diff head commit.
|
||||
Depending on the merge strategy, the merge commit SHA can be a merge commit, squash commit, or a diff head commit.
|
||||
|
||||
To download the Chain of Custody report, navigate to **{shield}** **Security & Compliance > Compliance** on the group's menu and click **List of all merge commits**
|
||||
|
||||
|
|
|
@ -34,11 +34,14 @@ module Gitlab
|
|||
Gitlab::Runtime.max_threads + headroom
|
||||
end
|
||||
|
||||
def config
|
||||
@config ||=
|
||||
def uncached_config
|
||||
scope.connection_db_config.configuration_hash.with_indifferent_access
|
||||
end
|
||||
|
||||
def config
|
||||
@config ||= uncached_config
|
||||
end
|
||||
|
||||
def pool_size
|
||||
config[:pool] || default_pool_size
|
||||
end
|
||||
|
@ -69,7 +72,7 @@ module Gitlab
|
|||
|
||||
# Disables prepared statements for the current database connection.
|
||||
def disable_prepared_statements
|
||||
scope.establish_connection(config.merge(prepared_statements: false))
|
||||
scope.establish_connection(uncached_config.merge(prepared_statements: false))
|
||||
end
|
||||
|
||||
def read_only?
|
||||
|
|
|
@ -66,7 +66,8 @@ module Peek
|
|||
backtrace: Gitlab::BacktraceCleaner.clean_backtrace(caller),
|
||||
cached: data[:cached] ? 'Cached' : '',
|
||||
transaction: data[:connection].transaction_open? ? 'In a transaction' : '',
|
||||
db_role: db_role(data)
|
||||
db_role: db_role(data),
|
||||
db_config_name: "Config name: #{::Gitlab::Database.db_config_name(data[:connection])}"
|
||||
}
|
||||
end
|
||||
|
||||
|
@ -76,7 +77,15 @@ module Peek
|
|||
role = ::Gitlab::Database::LoadBalancing.db_role_for_connection(data[:connection]) ||
|
||||
::Gitlab::Database::LoadBalancing::ROLE_UNKNOWN
|
||||
|
||||
role.to_s.capitalize
|
||||
"Role: #{role.to_s.capitalize}"
|
||||
end
|
||||
|
||||
def format_call_details(call)
|
||||
if Feature.enabled?(:multiple_database_metrics, default_enabled: :yaml)
|
||||
super
|
||||
else
|
||||
super.except(:db_config_name)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -297,7 +297,7 @@ namespace :gitlab do
|
|||
end
|
||||
|
||||
def repository_backup_strategy
|
||||
if Feature.enabled?(:gitaly_backup, default_enabled: :yaml)
|
||||
if Feature.enabled?(:gitaly_backup)
|
||||
max_concurrency = ENV['GITLAB_BACKUP_MAX_CONCURRENCY'].presence
|
||||
max_storage_concurrency = ENV['GITLAB_BACKUP_MAX_STORAGE_CONCURRENCY'].presence
|
||||
Backup::GitalyBackup.new(progress, parallel: max_concurrency, parallel_storage: max_storage_concurrency)
|
||||
|
|
|
@ -269,10 +269,7 @@ 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
|
||||
|
||||
|
@ -286,7 +283,6 @@ RSpec.describe 'Admin updates settings' do
|
|||
expect(current_settings.hide_third_party_offers).to be true
|
||||
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'
|
||||
|
@ -300,15 +296,6 @@ RSpec.describe 'Admin updates settings' do
|
|||
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
|
||||
|
||||
context 'Integration page', :js do
|
||||
before do
|
||||
visit integrations_admin_application_settings_path
|
||||
|
|
|
@ -140,6 +140,19 @@ RSpec.describe Gitlab::Database::Connection do
|
|||
|
||||
expect(connection.scope.connection.prepared_statements).to eq(false)
|
||||
end
|
||||
|
||||
context 'with dynamic connection pool size' do
|
||||
before do
|
||||
connection.scope.establish_connection(connection.config.merge(pool: 7))
|
||||
end
|
||||
|
||||
it 'retains the set pool size' do
|
||||
connection.disable_prepared_statements
|
||||
|
||||
expect(connection.scope.connection.prepared_statements).to eq(false)
|
||||
expect(connection.scope.connection.pool.size).to eq(7)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#read_only?' do
|
||||
|
|
|
@ -167,6 +167,7 @@ ProjectMember:
|
|||
- expires_at
|
||||
- ldap
|
||||
- override
|
||||
- invite_email_success
|
||||
User:
|
||||
- id
|
||||
- username
|
||||
|
|
|
@ -52,6 +52,7 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
|
|||
allow(connection_primary_1).to receive(:transaction_open?).and_return(false)
|
||||
allow(connection_primary_2).to receive(:transaction_open?).and_return(true)
|
||||
allow(connection_unknown).to receive(:transaction_open?).and_return(false)
|
||||
allow(::Gitlab::Database).to receive(:db_config_name).and_return('the_db_config_name')
|
||||
end
|
||||
|
||||
context 'when database load balancing is not enabled' do
|
||||
|
@ -77,32 +78,48 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
|
|||
cached: '',
|
||||
transaction: '',
|
||||
duration: 1000.0,
|
||||
sql: 'SELECT * FROM users WHERE id = 10'
|
||||
sql: 'SELECT * FROM users WHERE id = 10',
|
||||
db_config_name: "Config name: the_db_config_name"
|
||||
),
|
||||
a_hash_including(
|
||||
start: be_a(Time),
|
||||
cached: 'Cached',
|
||||
transaction: '',
|
||||
duration: 2000.0,
|
||||
sql: 'SELECT * FROM users WHERE id = 10'
|
||||
sql: 'SELECT * FROM users WHERE id = 10',
|
||||
db_config_name: "Config name: the_db_config_name"
|
||||
),
|
||||
a_hash_including(
|
||||
start: be_a(Time),
|
||||
cached: '',
|
||||
transaction: 'In a transaction',
|
||||
duration: 3000.0,
|
||||
sql: 'UPDATE users SET admin = true WHERE id = 10'
|
||||
sql: 'UPDATE users SET admin = true WHERE id = 10',
|
||||
db_config_name: "Config name: the_db_config_name"
|
||||
),
|
||||
a_hash_including(
|
||||
start: be_a(Time),
|
||||
cached: '',
|
||||
transaction: '',
|
||||
duration: 4000.0,
|
||||
sql: 'SELECT VERSION()'
|
||||
sql: 'SELECT VERSION()',
|
||||
db_config_name: "Config name: the_db_config_name"
|
||||
)
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
context 'when the multiple_database_metrics feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(multiple_database_metrics: false)
|
||||
end
|
||||
|
||||
it 'does not include db_config_name field' do
|
||||
ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 1.second, '1', event_1)
|
||||
|
||||
expect(subject.results[:details][0][:db_config_name]).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'when database load balancing is enabled' do
|
||||
|
@ -114,7 +131,7 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
|
|||
allow(Gitlab::Database::LoadBalancing).to receive(:db_role_for_connection).with(connection_unknown).and_return(nil)
|
||||
end
|
||||
|
||||
it 'includes db role data' do
|
||||
it 'includes db role data and db_config_name name' do
|
||||
Timecop.freeze(2021, 2, 23, 10, 0) do
|
||||
ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 1.second, '1', event_1)
|
||||
ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 2.seconds, '2', event_2)
|
||||
|
@ -127,9 +144,9 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
|
|||
summary: {
|
||||
"Cached" => 1,
|
||||
"In a transaction" => 1,
|
||||
"Primary" => 2,
|
||||
"Replica" => 1,
|
||||
"Unknown" => 1
|
||||
"Role: Primary" => 2,
|
||||
"Role: Replica" => 1,
|
||||
"Role: Unknown" => 1
|
||||
},
|
||||
duration: '10000.00ms',
|
||||
warnings: ["active-record duration: 10000.0 over 3000"],
|
||||
|
@ -140,7 +157,8 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
|
|||
transaction: '',
|
||||
duration: 1000.0,
|
||||
sql: 'SELECT * FROM users WHERE id = 10',
|
||||
db_role: 'Primary'
|
||||
db_role: 'Role: Primary',
|
||||
db_config_name: "Config name: the_db_config_name"
|
||||
),
|
||||
a_hash_including(
|
||||
start: be_a(Time),
|
||||
|
@ -148,7 +166,8 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
|
|||
transaction: '',
|
||||
duration: 2000.0,
|
||||
sql: 'SELECT * FROM users WHERE id = 10',
|
||||
db_role: 'Replica'
|
||||
db_role: 'Role: Replica',
|
||||
db_config_name: "Config name: the_db_config_name"
|
||||
),
|
||||
a_hash_including(
|
||||
start: be_a(Time),
|
||||
|
@ -156,7 +175,8 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
|
|||
transaction: 'In a transaction',
|
||||
duration: 3000.0,
|
||||
sql: 'UPDATE users SET admin = true WHERE id = 10',
|
||||
db_role: 'Primary'
|
||||
db_role: 'Role: Primary',
|
||||
db_config_name: "Config name: the_db_config_name"
|
||||
),
|
||||
a_hash_including(
|
||||
start: be_a(Time),
|
||||
|
@ -164,10 +184,23 @@ RSpec.describe Peek::Views::ActiveRecord, :request_store do
|
|||
transaction: '',
|
||||
duration: 4000.0,
|
||||
sql: 'SELECT VERSION()',
|
||||
db_role: 'Unknown'
|
||||
db_role: 'Role: Unknown',
|
||||
db_config_name: "Config name: the_db_config_name"
|
||||
)
|
||||
)
|
||||
)
|
||||
end
|
||||
|
||||
context 'when the multiple_database_metrics feature flag is disabled' do
|
||||
before do
|
||||
stub_feature_flags(multiple_database_metrics: false)
|
||||
end
|
||||
|
||||
it 'does not include db_config_name field' do
|
||||
ActiveSupport::Notifications.publish('sql.active_record', Time.current, Time.current + 1.second, '1', event_1)
|
||||
|
||||
expect(subject.results[:details][0][:db_config_name]).to be_nil
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -827,15 +827,15 @@ RSpec.describe Notify do
|
|||
end
|
||||
end
|
||||
|
||||
context 'when on gitlab.com' do
|
||||
context 'when mailgun events are enabled' do
|
||||
before do
|
||||
allow(Gitlab).to receive(:dev_env_or_com?).and_return(true)
|
||||
stub_application_setting(mailgun_events_enabled: true)
|
||||
end
|
||||
|
||||
it 'has custom headers' do
|
||||
aggregate_failures do
|
||||
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)
|
||||
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)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
# 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
|
|
@ -0,0 +1,42 @@
|
|||
# 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
|
Loading…
Reference in New Issue