Commit f4839aa5 authored by GitLab Bot's avatar GitLab Bot

Automatic merge of gitlab-org/gitlab master

parents 1218f7b4 681a3556
4a4ea7c0489b0eb0f7a65c65e5b15c35e3d16f14
3fbc0ff9c0c9fa486b753aa23ceac9513a2cde7b
......@@ -86,6 +86,7 @@ export default {
groupToBeSharedWith: {},
source: 'unknown',
invalidFeedbackMessage: '',
isLoading: false,
};
},
computed: {
......@@ -169,6 +170,7 @@ export default {
}
},
resetFields() {
this.isLoading = false;
this.selectedAccessLevel = this.defaultAccessLevel;
this.selectedDate = undefined;
this.newUsersToInvite = [];
......@@ -189,6 +191,7 @@ export default {
},
submitInviteMembers() {
this.invalidFeedbackMessage = '';
this.isLoading = true;
const [usersToInviteByEmail, usersToAddById] = this.partitionNewUsersToInvite();
const promises = [];
......@@ -247,12 +250,14 @@ export default {
}
this.invalidFeedbackMessage = message;
this.isLoading = false;
},
showToastMessageSuccess() {
this.$toast.show(this.$options.labels.toastMessageSuccessful, this.toastOptions);
this.closeModal();
},
showInvalidFeedbackMessage(response) {
this.isLoading = false;
this.invalidFeedbackMessage =
responseMessageFromError(response) || this.$options.labels.invalidFeedbackMessageDefault;
},
......@@ -405,6 +410,7 @@ export default {
<div class="gl-mr-3"></div>
<gl-button
:disabled="inviteDisabled"
:loading="isLoading"
variant="success"
data-qa-selector="invite_button"
data-testid="invite-button"
......
= render_if_exists "layouts/nav/ee/push_rules_link" # EE-specific
- 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
......
......@@ -3,69 +3,11 @@
class FinalizePushEventPayloadsBigintConversion2 < ActiveRecord::Migration[6.1]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
TABLE_NAME = 'push_event_payloads'
INDEX_NAME = 'index_push_event_payloads_on_event_id_convert_to_bigint'
def up
ensure_batched_background_migration_is_finished(
job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
table_name: TABLE_NAME,
column_name: 'event_id',
job_arguments: [["event_id"], ["event_id_convert_to_bigint"]]
)
swap_columns
# no-op due to https://gitlab.com/gitlab-com/gl-infra/production/-/issues/5256
end
def down
swap_columns
end
private
def swap_columns
add_concurrent_index TABLE_NAME, :event_id_convert_to_bigint, unique: true, name: INDEX_NAME
# Add a foreign key on `event_id_convert_to_bigint` before we swap the columns and drop the old FK (fk_36c74129da)
add_concurrent_foreign_key TABLE_NAME, :events, column: :event_id_convert_to_bigint, on_delete: :cascade
with_lock_retries(raise_on_exhaustion: true) do
# We'll need ACCESS EXCLUSIVE lock on the related tables,
# lets make sure it can be acquired from the start
execute "LOCK TABLE #{TABLE_NAME}, events IN ACCESS EXCLUSIVE MODE"
# Swap column names
temp_name = 'event_id_tmp'
execute "ALTER TABLE #{quote_table_name(TABLE_NAME)} RENAME COLUMN #{quote_column_name(:event_id)} TO #{quote_column_name(temp_name)}"
execute "ALTER TABLE #{quote_table_name(TABLE_NAME)} RENAME COLUMN #{quote_column_name(:event_id_convert_to_bigint)} TO #{quote_column_name(:event_id)}"
execute "ALTER TABLE #{quote_table_name(TABLE_NAME)} RENAME COLUMN #{quote_column_name(temp_name)} TO #{quote_column_name(:event_id_convert_to_bigint)}"
# We need to update the trigger function in order to make PostgreSQL to
# regenerate the execution plan for it. This is to avoid type mismatch errors like
# "type of parameter 15 (bigint) does not match that when preparing the plan (integer)"
function_name = Gitlab::Database::UnidirectionalCopyTrigger.on_table(TABLE_NAME).name(:event_id, :event_id_convert_to_bigint)
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
# Swap defaults
change_column_default TABLE_NAME, :event_id, nil
change_column_default TABLE_NAME, :event_id_convert_to_bigint, 0
# Swap PK constraint
execute "ALTER TABLE #{TABLE_NAME} DROP CONSTRAINT push_event_payloads_pkey"
rename_index TABLE_NAME, INDEX_NAME, 'push_event_payloads_pkey'
execute "ALTER TABLE #{TABLE_NAME} ADD CONSTRAINT push_event_payloads_pkey PRIMARY KEY USING INDEX push_event_payloads_pkey"
# Drop original FK on the old int4 `event_id` (fk_36c74129da)
remove_foreign_key TABLE_NAME, name: concurrent_foreign_key_name(TABLE_NAME, :event_id)
# We swapped the columns but the FK for event_id is still using the old name for the event_id_convert_to_bigint column
# So we have to also swap the FK name now that we dropped the other one with the same
rename_constraint(
TABLE_NAME,
concurrent_foreign_key_name(TABLE_NAME, :event_id_convert_to_bigint),
concurrent_foreign_key_name(TABLE_NAME, :event_id)
)
end
# no-op due to https://gitlab.com/gitlab-com/gl-infra/production/-/issues/5256
end
end
......@@ -17561,7 +17561,7 @@ ALTER SEQUENCE protected_tags_id_seq OWNED BY protected_tags.id;
CREATE TABLE push_event_payloads (
commit_count bigint NOT NULL,
event_id_convert_to_bigint integer DEFAULT 0 NOT NULL,
event_id integer NOT NULL,
action smallint NOT NULL,
ref_type smallint NOT NULL,
commit_from bytea,
......@@ -17569,7 +17569,7 @@ CREATE TABLE push_event_payloads (
ref text,
commit_title character varying(70),
ref_count integer,
event_id bigint NOT NULL
event_id_convert_to_bigint bigint DEFAULT 0 NOT NULL
);
CREATE TABLE push_rules (
......@@ -181,3 +181,32 @@ You can also specify some attributes for the resulting Vault tokens, such as tim
IP address range, and number of uses. The full list of options is available in
[Vault's documentation on creating roles](https://www.vaultproject.io/api/auth/jwt#create-role)
for the JSON web token method.
## Using a self-signed Vault server
When the Vault server is using a self-signed certificate, you will see the following error in the job logs:
```plaintext
ERROR: Job failed (system failure): resolving secrets: initializing Vault service: preparing authenticated client: checking Vault server health: Get https://vault.example.com:8000/v1/sys/health?drsecondarycode=299&performancestandbycode=299&sealedcode=299&standbycode=299&uninitcode=299: x509: certificate signed by unknown authority
```
You have two options to solve this error:
- Add the self-signed certificate to the GitLab Runner server's CA store.
If you deployed GitLab Runner using the [Helm chart](https://docs.gitlab.com/runner/install/kubernetes.html), you will have to create your own GitLab Runner image.
- Use the `VAULT_CACERT` environment variable to configure GitLab Runner to trust the certificate:
- If you are using systemd to manage GitLab Runner, see [how to add an environment variable for GitLab Runner](https://docs.gitlab.com/runner/configuration/init.html#setting-custom-environment-variables).
- If you deployed GitLab Runner using the [Helm chart](https://docs.gitlab.com/runner/install/kubernetes.html):
1. [Provide a custom certificate for accessing GitLab](https://docs.gitlab.com/runner/install/kubernetes.html#providing-a-custom-certificate-for-accessing-gitlab), and make sure to add the certificate for the Vault server instead of the certificate for GitLab. If your GitLab instance is also using a self-signed certificate, you should be able to add both in the same `Secret`.
1. Add the following lines in your `values.yaml` file:
```yaml
## Replace both the <SECRET_NAME> and the <VAULT_CERTIFICATE>
## with the actual values you used to create the secret
certsSecretName: <SECRET_NAME>
envVars:
- name: VAULT_CACERT
value: "/home/gitlab-runner/.gitlab-runner/certs/<VAULT_CERTIFICATE>"
```
......@@ -684,142 +684,130 @@ For more information, see [Available settings for `services`](../services/index.
### `script`
Use `script` to specify a shell script for the runner to execute.
Use `script` to specify commands for the runner to execute.
All jobs except [trigger jobs](#trigger) require a `script` keyword.
For example:
**Keyword type**: Job keyword. You can use it only as part of a job.
```yaml
job:
script: "bundle exec rspec"
```
**Possible inputs**: An array including:
You can use [YAML anchors with `script`](#yaml-anchors-for-scripts).
- Single line commands.
- Long commands [split over multiple lines](script.md#split-long-commands).
- [YAML anchors](#yaml-anchors-for-scripts).
The `script` keyword can also contain several commands in an array:
**Example of `script`:**
```yaml
job:
job1:
script: "bundle exec rspec"
job2:
script:
- uname -a
- bundle exec rspec
```
Sometimes, `script` commands must be wrapped in single or double quotes.
For example, commands that contain a colon (`:`) must be wrapped in single quotes (`'`).
The YAML parser needs to interpret the text as a string rather than
a "key: value" pair.
**Additional details**:
For example, this script uses a colon:
You might need to use single quotes (`'`) or double quotes (`"`) when using
[special characters in `script`](script.md#use-special-characters-with-script).
```yaml
job:
script:
- curl --request POST --header 'Content-Type: application/json' "https://gitlab/api/v4/projects"
```
**Related topics**:
To be considered valid YAML, you must wrap the entire command in single quotes. If
the command already uses single quotes, you should change them to double quotes (`"`)
if possible:
- You can [ignore non-zero exit codes](script.md#ignore-non-zero-exit-codes).
- [Use color codes with `script`](script.md#add-color-codes-to-script-output)
to make job logs easier to review.
- [Create custom collapsible sections](../jobs/index.md#custom-collapsible-sections)
to simplify job log output.
```yaml
job:
script:
- 'curl --request POST --header "Content-Type: application/json" "https://gitlab/api/v4/projects"'
```
#### `before_script`
You can verify the syntax is valid with the [CI Lint](../lint.md) tool.
Use `before_script` to define an array of commands that should run before each job's
`script` commands, but after [artifacts](#artifacts) are restored.
Be careful when using these characters as well:
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default:` section](#custom-default-keyword-values).
- `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` ``.
**Possible inputs**: An array including:
If any of the script commands return an exit code other than zero, the job
fails and further commands are not executed. Store the exit code in a variable to
avoid this behavior:
- Single line commands.
- Long commands [split over multiple lines](script.md#split-long-commands).
- [YAML anchors](#yaml-anchors-for-scripts).
**Example of `before_script`:**
```yaml
job:
before_script:
- echo "Execute this command before any `script:` commands."
script:
- false || exit_code=$?
- if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;
- echo "This command executes after the job's `before_script` commands."
```
#### `before_script`
Use `before_script` to define an array of commands that should run before each job,
but after [artifacts](#artifacts) are restored.
**Additional details**:
Scripts you specify in `before_script` are concatenated with any scripts you specify
in the main [`script`](#script). The combine scripts execute together in a single shell.
in the main [`script`](#script). The combined scripts execute together in a single shell.
You can overwrite a globally-defined `before_script` if you define it in a job:
**Related topics**:
```yaml
default:
before_script:
- echo "Execute this script in all jobs that don't already have a before_script section."
- [Use `before_script` with `default`](script.md#set-a-default-before_script-or-after_script-for-all-jobs)
to define a default array of commands that should run before the `script` commands in all jobs.
- You can [ignore non-zero exit codes](script.md#ignore-non-zero-exit-codes).
- [Use color codes with `before_script`](script.md#add-color-codes-to-script-output)
to make job logs easier to review.
- [Create custom collapsible sections](../jobs/index.md#custom-collapsible-sections)
to simplify job log output.
job1:
script:
- echo "This script executes after the global before_script."
#### `after_script`
job:
before_script:
- echo "Execute this script instead of the global before_script."
script:
- echo "This script executes after the job's `before_script`"
```
Use `after_script` to define an array of commands that run after each job, including failed jobs.
You can use [YAML anchors with `before_script`](#yaml-anchors-for-scripts).
**Keyword type**: Job keyword. You can use it only as part of a job or in the
[`default:` section](#custom-default-keyword-values).
#### `after_script`
**Possible inputs**: An array including:
Use `after_script` to define an array of commands that run after each job,
including failed jobs.
- Single line commands.
- Long commands [split over multiple lines](script.md#split-long-commands).
- [YAML anchors](#yaml-anchors-for-scripts).
If a job times out or is cancelled, the `after_script` commands do not execute.
An [issue](https://gitlab.com/gitlab-org/gitlab/-/issues/15603) exists to support
executing `after_script` commands for timed-out or cancelled jobs.
**Example of `after_script`:**
```yaml
job:
script:
- echo "An example script section."
after_script:
- echo "Execute this command after the `script` section completes."
```
**Additional details**:
Scripts you specify in `after_script` execute in a new shell, separate from any
`before_script` or `script` scripts. As a result, they:
`before_script` or `script` commands. As a result, they:
- Have a current working directory set back to the default.
- Have no access to changes done by scripts defined in `before_script` or `script`, including:
- Don't have access to changes done by commands defined in the `before_script` or `script`,
including:
- Command aliases and variables exported in `script` scripts.
- Changes outside of the working tree (depending on the runner executor), like
software installed by a `before_script` or `script` script.
- Have a separate timeout, which is hard coded to 5 minutes. See the
[related issue](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2716) for details.
- Have a separate timeout, which is [hard-coded to 5 minutes](https://gitlab.com/gitlab-org/gitlab-runner/-/issues/2716).
- Don't affect the job's exit code. If the `script` section succeeds and the
`after_script` times out or fails, the job exits with code `0` (`Job Succeeded`).
```yaml
default:
after_script:
- echo "Execute this script in all jobs that don't already have an after_script section."
job1:
script:
- echo "This script executes first. When it completes, the global after_script executes."
job:
script:
- echo "This script executes first. When it completes, the job's `after_script` executes."
after_script:
- echo "Execute this script instead of the global after_script."
```
You can use [YAML anchors with `after_script`](#yaml-anchors-for-scripts).
#### Script syntax
If a job times out or is cancelled, the `after_script` commands do not execute.
[An issue exists](https://gitlab.com/gitlab-org/gitlab/-/issues/15603) to add support for executing `after_script` commands for timed-out or cancelled jobs.
You can use syntax in [`script`](#script) sections to:
**Related topics**:
- [Split long commands](script.md#split-long-commands) into multiline commands.
- [Use color codes](script.md#add-color-codes-to-script-output) to make job logs easier to review.
- [Use `after_script` with `default`](script.md#set-a-default-before_script-or-after_script-for-all-jobs)
to define a default array of commands that should run after all jobs.
- You can [ignore non-zero exit codes](script.md#ignore-non-zero-exit-codes).
- [Use color codes with `after_script`](script.md#add-color-codes-to-script-output)
to make job logs easier to review.
- [Create custom collapsible sections](../jobs/index.md#custom-collapsible-sections)
to simplify job log output.
......
......@@ -14,6 +14,85 @@ You can use special syntax in [`script`](index.md#script) sections to:
- [Create custom collapsible sections](../jobs/index.md#custom-collapsible-sections)
to simplify job log output.
## Use special characters with `script:`
Sometimes, `script` commands must be wrapped in single or double quotes.
For example, commands that contain a colon (`:`) must be wrapped in single quotes (`'`).
The YAML parser needs to interpret the text as a string rather than
a "key: value" pair.
For example, this script uses a colon:
```yaml
job:
script:
- curl --request POST --header 'Content-Type: application/json' "https://gitlab/api/v4/projects"
```
To be considered valid YAML, you must wrap the entire command in single quotes. If
the command already uses single quotes, you should change them to double quotes (`"`)
if possible:
```yaml
job:
script:
- 'curl --request POST --header "Content-Type: application/json" "https://gitlab/api/v4/projects"'
```
You can verify the syntax is valid with the [CI Lint](../lint.md) tool.
Be careful when using these characters as well:
- `{`, `}`, `[`, `]`, `,`, `&`, `*`, `#`, `?`, `|`, `-`, `<`, `>`, `=`, `!`, `%`, `@`, `` ` ``.
## Ignore non-zero exit codes
When script commands return an exit code other than zero, the job fails and further
commands do not execute.
Store the exit code in a variable to avoid this behavior:
```yaml
job:
script:
- false || exit_code=$?
- if [ $exit_code -ne 0 ]; then echo "Previous command failed"; fi;
```
## Set a default `before_script` or `after_script` for all jobs
You can use [`before_script`](index.md#before_script) and [`after_script`](index.md#after_script)
with [`default`](index.md#custom-default-keyword-values):
- Use `before_script` with `default` to define a default array of commands that
should run before the `script` commands in all jobs.
- Use `after_script` with default to define a default array of commands
that should run after the job completes.
You can overwrite a default by defining a different one in a job. To ignore the default
use `before_script: []` or `after_script: []`:
```yaml
default:
before_script:
- echo "Execute this `before_script` in all jobs by default."
after_script:
- echo "Execute this `after_script` in all jobs by default."
job1:
script:
- echo "These script commands execute after the default `before_script`,"
- echo "and before the default `after_script`."
job2:
before_script:
- echo "Execute this script instead of the default `before_script`."
script:
- echo "This script executes after the job's `before_script`,"
- echo "but the job does not use the default `after_script`."
after_script: []
```
## Split long commands
You can split long commands into multiline commands to improve readability with
......
......@@ -20,6 +20,8 @@ Deploy tokens can be managed by [maintainers only](../../permissions.md).
Deploy tokens cannot be used with the GitLab API.
Deploy tokens are tied to the project and stay enabled even when the user who created the token is removed from the project.
If you have a key pair, you might want to use [deploy keys](../../project/deploy_keys/index.md)
instead.
......
......@@ -67,6 +67,12 @@ There is also an indicator on the sidebar denoting confidentiality.
| :-----------: | :----------: |
| ![Sidebar confidential issue](img/sidebar_confidential_issue.png) | ![Sidebar not confidential issue](img/sidebar_not_confidential_issue.png) |
## Merge requests for confidential issues
Although you can make issues be confidential in public projects, you cannot make
confidential merge requests. Learn how to create [merge requests for confidential issues](../merge_requests/confidential.md)
that prevent leaks of private data.
## Permissions and access to confidential issues
There are two kinds of level access for confidential issues. The general rule
......@@ -82,48 +88,6 @@ sees in the project's search results respectively.
|:---------------------------------------------------------------------------------------|:---------------------------------------------------------------------------------|
| ![Confidential issues search by maintainer](img/confidential_issues_search_master.png) | ![Confidential issues search by guest](img/confidential_issues_search_guest.png) |
## Merge Requests for Confidential Issues
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/58583) in GitLab 12.1.
To help prevent confidential information being leaked from a public project
in the process of resolving a confidential issue, confidential issues can be
resolved by creating a merge request from a private fork.
The created merge request targets the default branch of the private fork,
not the default branch of the public upstream project. This prevents the merge
request, branch, and commits entering the public repository, and revealing
confidential information prematurely. To make a confidential commit public,
open a merge request from the private fork to the public upstream project.
Permissions are inherited from parent groups. Developers have the same permissions
for private forks created in the same group or in a subgroup of the original
Permissions are inherited from parent groups. When private forks are created
in the same group or subgroup as the original upstream repository, users
receive the same permissions in both projects. This inheritance ensures
Developer users have the needed permissions to both view confidential issues and
resolve them.
### How it works
On a confidential issue, a **Create confidential merge request** button is
available. Clicking on it opens a dropdown where you can choose to
**Create confidential merge request and branch** or **Create branch**:
| Create confidential merge request | Create branch |
| :-------------------------------: | :-----------: |
| ![Create Confidential Merge Request Dropdown](img/confidential_mr_dropdown_v12_1.png) | ![Create Confidential Branch Dropdown](img/confidential_mr_branch_dropdown_v12_1.png) |
The **Project** dropdown includes the list of private forks the user is a member
of as at least a Developer and merge requests are enabled.
Whenever the **Branch name** and **Source (branch or tag)** fields change, the
availability of the target and source branch are checked. Both branches should
be available in the selected private fork.
By clicking the **Create confidential merge request** button, GitLab creates
the branch and merge request in the private fork. When you choose
**Create branch**, GitLab creates only the branch.
## Related links
After the branch is created in the private fork, developers can push code to
that branch to fix the confidential issue.
- [Merge requests for confidential issues](../merge_requests/confidential.md)
---
stage: Create
group: Code Review
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
---
# Merge requests for confidential issues
> [Introduced](https://gitlab.com/gitlab-org/gitlab-foss/-/issues/58583) in GitLab 12.1.
Merge requests in a public repository are also public, even when the merge
request is created for a [confidential issue](../issues/confidential_issues.md).
To avoid leaking confidential information when working on a confidential issue,
create your merge request from a private fork.
Roles are inherited from parent groups. If you create your private fork in the
same group or subgroup as the original (public) repository, developers receive
the same permissions in your fork. This inheritance ensures:
- Developer users have the needed permissions to view confidential issues and resolve them.
- You do not need grant individual users access to your fork.
The [security practices for confidential merge requests](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#security-releases-critical-non-critical-as-a-developer) at GitLab are available to read.
## Create a confidential merge request
WARNING:
To create a confidential merge request, you must create a private fork. This fork
may expose confidential information, if you create your fork in another namespace
that may have other members.
Branches are public by default. To protect the confidentiality of your work, you
must create your changes in a private fork.
Prerequisites:
- You have the Owner or Maintainer role in the public repository, as you need one
of these roles to [create a subgroup](../../group/subgroups/index.md).
- You have [forked](../repository/forking_workflow.md) the public repository.
- Your fork has a **Visibility level** of _Private_.
To create a confidential merge request:
1. Go to the confidential issue's page. Scroll below the issue description and
select **Create confidential merge request**.
1. Select the item that meets your needs:
- *To create both a branch and a merge request,* select
**Create confidential merge request and branch**. Your merge request will
target the default branch of your fork, *not* the default branch of the
public upstream project.
- *To create only a branch,* select **Create branch**.
1. Select a **Project** to use. These projects have merge requests enabled, and
you have the Developer role (or greater) in them.
1. Provide a **Branch name**, and select a **Source (branch or tag)**. GitLab
checks whether these branches are available in your private fork, because both
branches must be available in your selected fork.
1. Select **Create**.
If you created a branch in your private fork, users with the Developer role in the
public repository can push code to that branch in your private fork to fix the
confidential issue.
As your merge request targets your private fork, not the public upstream project,
your branch, merge request, and commits do not enter the public repository. This
prevents prematurely revealing confidential information.
To make a confidential commit public, open a merge request from the private fork
to the public upstream project.
## Related links
- [Confidential issues](../issues/confidential_issues.md)
- [Security practices for confidential merge requests](https://gitlab.com/gitlab-org/release/docs/blob/master/general/security/developer.md#security-releases-critical-non-critical-as-a-developer) at GitLab
- return unless can_modify_group_push_rules?(current_user, @group)
= nav_link(controller: :push_rules) do
= link_to edit_group_push_rules_path(@group), title: _('Push Rules') do
.nav-icon-container
= sprite_icon('push-rules')
%span.nav-item-name
= _('Push Rules')
%ul.sidebar-sub-level-items.is-fly-out-only
= nav_link(controller: :push_rules, html_options: { class: "fly-out-top-item" } ) do
= link_to edit_group_push_rules_path(@group), title: _('Push Rules') do
%strong.fly-out-top-item-name
= _('Push Rules')
......@@ -13,6 +13,7 @@ module EE
insert_menu_before(::Sidebars::Groups::Menus::GroupInformationMenu, ::Sidebars::Groups::Menus::TrialExperimentMenu.new(context))
insert_menu_after(::Sidebars::Groups::Menus::GroupInformationMenu, ::Sidebars::Groups::Menus::EpicsMenu.new(context))
insert_menu_after(::Sidebars::Groups::Menus::MergeRequestsMenu, ::Sidebars::Groups::Menus::SecurityComplianceMenu.new(context))
insert_menu_after(::Sidebars::Groups::Menus::SecurityComplianceMenu, ::Sidebars::Groups::Menus::PushRulesMenu.new(context))
end
end
end
......
# frozen_string_literal: true
module Sidebars
module Groups
module Menus
class PushRulesMenu < ::Sidebars::Menu
override :link
def link
edit_group_push_rules_path(context.group)
end
override :title
def title
_('Push Rules')
end
override :sprite_icon
def sprite_icon
'push-rules'
end
override :render?
def render?
can?(context.current_user, :change_push_rules, context.group)
end
override :active_routes
def active_routes
{ controller: :push_rules }
end
end
end
end
end
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Sidebars::Groups::Menus::PushRulesMenu do
let_it_be(:owner) { create(:user) }
let_it_be(:group) do
build(:group, :private).tap do |g|
g.add_owner(owner)
end
end
let(:user) { owner }
let(:context) { Sidebars::Groups::Context.new(current_user: user, container: group) }
let(:menu) { described_class.new(context) }
describe '#render?' do
context 'when user can change push rules' do
it 'returns true' do
expect(menu.render?).to eq true
end
end
context 'when user cannot change push rules' do
let(:user) { nil }
it 'returns false' do
expect(menu.render?).to eq false
end
end
end
end
......@@ -312,6 +312,17 @@ RSpec.describe 'layouts/nav/sidebar/_group' do
end
end
describe 'Push Rules menu' do
it 'has a link to the push rules list path' do
group.add_owner(user)
allow(view).to receive(:current_user).and_return(user)
render
expect(rendered).to have_link('Push Rules', href: edit_group_push_rules_path(group))
end
end
describe 'DevOps adoption link' do
let!(:current_user) { create(:user) }
......
......@@ -34,12 +34,17 @@ module Gitlab
Gitlab::Runtime.max_threads + headroom
end
def uncached_config
scope.connection_db_config.configuration_hash.with_indifferent_access
end
def config
@config ||= uncached_config
# The result of this method must not be cached, as other methods may use
# it after making configuration changes and expect those changes to be
# present. For example, `disable_prepared_statements` expects the
# configuration settings to always be up to date.
#
# See the following for more information:
#
# - https://gitlab.com/gitlab-org/release/retrospectives/-/issues/39
# - https://gitlab.com/gitlab-com/gl-infra/production/-/issues/5238
scope.connection_db_config.configuration_hash.with_indifferent_access
end
def pool_size
......@@ -72,7 +77,7 @@ module Gitlab
# Disables prepared statements for the current database connection.
def disable_prepared_statements
scope.establish_connection(uncached_config.merge(prepared_statements: false))
scope.establish_connection(config.merge(prepared_statements: false))
end
def read_only?
......
......@@ -137,6 +137,10 @@ describe('InviteMembersModal', () => {
expect(findInviteButton().text()).toBe('Invite');
});
it('renders the Invite button modal without isLoading', () => {
expect(findInviteButton().props('loading')).toBe(false);
});
describe('rendering the access levels dropdown', () => {
it('sets the default dropdown text to the default access level name', () => {
expect(findDropdown().attributes('text')).toBe('Guest');
......@@ -230,6 +234,16 @@ describe('InviteMembersModal', () => {
clickInviteButton();
});
it('sets isLoading on the Invite button when it is clicked', () => {
expect(findInviteButton().props('loading')).toBe(true);
});
it('removes isLoading from the Invite button when request completes', async () => {
await waitForPromises();
expect(findInviteButton().props('loading')).toBe(false);
});
it('calls Api addGroupMembersByUserId with the correct params', async () => {
await waitForPromises;
......@@ -260,6 +274,7 @@ describe('InviteMembersModal', () => {
expect(membersFormGroupInvalidFeedback()).toBe('Member already exists');
expect(findMembersFormGroup().props('state')).toBe(false);
expect(findMembersSelect().props('validationState')).toBe(false);
expect(findInviteButton().props('loading')).toBe(false);
});
it('clears the invalid state and message once the list of members to invite is cleared', async () => {
......@@ -272,6 +287,7 @@ describe('InviteMembersModal', () => {
expect(membersFormGroupInvalidFeedback()).toBe('Member already exists');
expect(findMembersFormGroup().props('state')).toBe(false);
expect(findMembersSelect().props('validationState')).toBe(false);
expect(findInviteButton().props('loading')).toBe(false);
findMembersSelect().vm.$emit('clear');
......@@ -280,6 +296,7 @@ describe('InviteMembersModal', () => {
expect(membersFormGroupInvalidFeedback()).toBe('');
expect(findMembersFormGroup().props('state')).not.toBe(false);
expect(findMembersSelect().props('validationState')).not.toBe(false);
expect(findInviteButton().props('loading')).toBe(false);
});
it('displays the generic error for http server error', async () => {
......@@ -375,6 +392,7 @@ describe('InviteMembersModal', () => {
expect(membersFormGroupInvalidFeedback()).toBe(expectedSyntaxError);
expect(findMembersSelect().props('validationState')).toBe(false);
expect(findInviteButton().props('loading')).toBe(false);
});
it('displays the restricted email error when restricted email is invited', async () => {
......@@ -386,6 +404,7 @@ describe('InviteMembersModal', () => {
expect(membersFormGroupInvalidFeedback()).toContain(expectedEmailRestrictedError);
expect(findMembersSelect().props('validationState')).toBe(false);
expect(findInviteButton().props('loading')).toBe(false);
});
it('displays the successful toast message when email has already been invited', async () => {
......
......@@ -29,12 +29,19 @@ RSpec.describe Gitlab::Database::Connection do
it 'returns a default pool size' do
expect(connection.config).to include(pool: connection.default_pool_size)
end
it 'does not cache its results' do
a = connection.config
b = connection.config
expect(a).not_to equal(b)
end
end
describe '#pool_size' do
context 'when no explicit size is configured' do
it 'returns the default pool size' do
expect(connection.config).to receive(:[]).with(:pool).and_return(nil)
expect(connection).to receive(:config).and_return({ pool: nil })
expect(connection.pool_size).to eq(connection.default_pool_size)
end
......@@ -42,7 +49,7 @@ RSpec.describe Gitlab::Database::Connection do
context 'when an explicit pool size is set' do
it 'returns the pool size' do
expect(connection.config).to receive(:[]).with(:pool).and_return(4)
expect(connection).to receive(:config).and_return({ pool: 4 })
expect(connection.pool_size).to eq(4)
end
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment