Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2022-02-15 09:17:01 +00:00
parent 66fc7ba6f3
commit e7e44c0e4c
51 changed files with 689 additions and 369 deletions

View File

@ -2,7 +2,7 @@
source 'https://rubygems.org'
gem 'rails', '~> 6.1.4.4'
gem 'rails', '~> 6.1.4.6'
gem 'bootsnap', '~> 1.9.1', require: false

View File

@ -11,63 +11,63 @@ GEM
RedCloth (4.3.2)
acme-client (2.0.9)
faraday (>= 0.17, < 2.0.0)
actioncable (6.1.4.4)
actionpack (= 6.1.4.4)
activesupport (= 6.1.4.4)
actioncable (6.1.4.6)
actionpack (= 6.1.4.6)
activesupport (= 6.1.4.6)
nio4r (~> 2.0)
websocket-driver (>= 0.6.1)
actionmailbox (6.1.4.4)
actionpack (= 6.1.4.4)
activejob (= 6.1.4.4)
activerecord (= 6.1.4.4)
activestorage (= 6.1.4.4)
activesupport (= 6.1.4.4)
actionmailbox (6.1.4.6)
actionpack (= 6.1.4.6)
activejob (= 6.1.4.6)
activerecord (= 6.1.4.6)
activestorage (= 6.1.4.6)
activesupport (= 6.1.4.6)
mail (>= 2.7.1)
actionmailer (6.1.4.4)
actionpack (= 6.1.4.4)
actionview (= 6.1.4.4)
activejob (= 6.1.4.4)
activesupport (= 6.1.4.4)
actionmailer (6.1.4.6)
actionpack (= 6.1.4.6)
actionview (= 6.1.4.6)
activejob (= 6.1.4.6)
activesupport (= 6.1.4.6)
mail (~> 2.5, >= 2.5.4)
rails-dom-testing (~> 2.0)
actionpack (6.1.4.4)
actionview (= 6.1.4.4)
activesupport (= 6.1.4.4)
actionpack (6.1.4.6)
actionview (= 6.1.4.6)
activesupport (= 6.1.4.6)
rack (~> 2.0, >= 2.0.9)
rack-test (>= 0.6.3)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.0, >= 1.2.0)
actiontext (6.1.4.4)
actionpack (= 6.1.4.4)
activerecord (= 6.1.4.4)
activestorage (= 6.1.4.4)
activesupport (= 6.1.4.4)
actiontext (6.1.4.6)
actionpack (= 6.1.4.6)
activerecord (= 6.1.4.6)
activestorage (= 6.1.4.6)
activesupport (= 6.1.4.6)
nokogiri (>= 1.8.5)
actionview (6.1.4.4)
activesupport (= 6.1.4.4)
actionview (6.1.4.6)
activesupport (= 6.1.4.6)
builder (~> 3.1)
erubi (~> 1.4)
rails-dom-testing (~> 2.0)
rails-html-sanitizer (~> 1.1, >= 1.2.0)
activejob (6.1.4.4)
activesupport (= 6.1.4.4)
activejob (6.1.4.6)
activesupport (= 6.1.4.6)
globalid (>= 0.3.6)
activemodel (6.1.4.4)
activesupport (= 6.1.4.4)
activerecord (6.1.4.4)
activemodel (= 6.1.4.4)
activesupport (= 6.1.4.4)
activemodel (6.1.4.6)
activesupport (= 6.1.4.6)
activerecord (6.1.4.6)
activemodel (= 6.1.4.6)
activesupport (= 6.1.4.6)
activerecord-explain-analyze (0.1.0)
activerecord (>= 4)
pg
activestorage (6.1.4.4)
actionpack (= 6.1.4.4)
activejob (= 6.1.4.4)
activerecord (= 6.1.4.4)
activesupport (= 6.1.4.4)
activestorage (6.1.4.6)
actionpack (= 6.1.4.6)
activejob (= 6.1.4.6)
activerecord (= 6.1.4.6)
activesupport (= 6.1.4.6)
marcel (~> 1.0.0)
mini_mime (>= 1.1.0)
activesupport (6.1.4.4)
activesupport (6.1.4.6)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
@ -967,20 +967,20 @@ GEM
rack-test (1.1.0)
rack (>= 1.0, < 3)
rack-timeout (0.5.2)
rails (6.1.4.4)
actioncable (= 6.1.4.4)
actionmailbox (= 6.1.4.4)
actionmailer (= 6.1.4.4)
actionpack (= 6.1.4.4)
actiontext (= 6.1.4.4)
actionview (= 6.1.4.4)
activejob (= 6.1.4.4)
activemodel (= 6.1.4.4)
activerecord (= 6.1.4.4)
activestorage (= 6.1.4.4)
activesupport (= 6.1.4.4)
rails (6.1.4.6)
actioncable (= 6.1.4.6)
actionmailbox (= 6.1.4.6)
actionmailer (= 6.1.4.6)
actionpack (= 6.1.4.6)
actiontext (= 6.1.4.6)
actionview (= 6.1.4.6)
activejob (= 6.1.4.6)
activemodel (= 6.1.4.6)
activerecord (= 6.1.4.6)
activestorage (= 6.1.4.6)
activesupport (= 6.1.4.6)
bundler (>= 1.15.0)
railties (= 6.1.4.4)
railties (= 6.1.4.6)
sprockets-rails (>= 2.0.0)
rails-controller-testing (1.0.5)
actionpack (>= 5.0.1.rc1)
@ -994,9 +994,9 @@ GEM
rails-i18n (6.0.0)
i18n (>= 0.7, < 2)
railties (>= 6.0.0, < 7)
railties (6.1.4.4)
actionpack (= 6.1.4.4)
activesupport (= 6.1.4.4)
railties (6.1.4.6)
actionpack (= 6.1.4.6)
activesupport (= 6.1.4.6)
method_source
rake (>= 0.13)
thor (~> 1.0)
@ -1580,7 +1580,7 @@ DEPENDENCIES
rack-oauth2 (~> 1.16.0)
rack-proxy (~> 0.6.0)
rack-timeout (~> 0.5.1)
rails (~> 6.1.4.4)
rails (~> 6.1.4.6)
rails-controller-testing
rails-i18n (~> 6.0)
rainbow (~> 3.0)

View File

@ -266,7 +266,7 @@ export default {
>
<span class="gl-font-lg">&middot;</span>
<span data-testid="vsa-stage-event-date">
{{ s__('OpenedNDaysAgo|Opened') }}
{{ s__('OpenedNDaysAgo|Created') }}
<gl-link class="gl-text-black-normal" :href="item.url">{{
item.createdAt
}}</gl-link>

View File

@ -102,7 +102,7 @@ export default {
</div>
</div>
<span>
{{ __('Opened') }}
{{ __('Created') }}
<time-ago-tooltip data-testid="startTimeItem" :time="createdAt" />
{{ __('by') }}
</span>

View File

@ -40,7 +40,7 @@ module Projects
avenues = [authorizable_project_members]
avenues << if project.personal?
project_owner_acting_as_maintainer
project_owner
else
authorizable_group_members
end
@ -85,9 +85,15 @@ module Projects
Member.from_union(members)
end
def project_owner_acting_as_maintainer
# workaround until we migrate Project#owners to have membership with
# OWNER access level
def project_owner
user_id = project.namespace.owner.id
access_level = Gitlab::Access::MAINTAINER
access_level = if ::Feature.enabled?(:personal_project_owner_with_owner_access, default_enabled: :yaml)
Gitlab::Access::OWNER
else
Gitlab::Access::MAINTAINER
end
Member
.from(generate_from_statement([[user_id, access_level]])) # rubocop: disable CodeReuse/ActiveRecord

View File

@ -8,8 +8,14 @@ module SelectForProjectAuthorization
select("projects.id AS project_id", "members.access_level")
end
def select_as_maintainer_for_project_authorization
select(["projects.id AS project_id", "#{Gitlab::Access::MAINTAINER} AS access_level"])
# workaround until we migrate Project#owners to have membership with
# OWNER access level
def select_project_owner_for_project_authorization
if ::Feature.enabled?(:personal_project_owner_with_owner_access, default_enabled: :yaml)
select(["projects.id AS project_id", "#{Gitlab::Access::OWNER} AS access_level"])
else
select(["projects.id AS project_id", "#{Gitlab::Access::MAINTAINER} AS access_level"])
end
end
end
end

View File

@ -459,7 +459,7 @@ class Project < ApplicationRecord
delegate :name, to: :owner, allow_nil: true, prefix: true
delegate :members, to: :team, prefix: true
delegate :add_user, :add_users, to: :team
delegate :add_guest, :add_reporter, :add_developer, :add_maintainer, :add_role, to: :team
delegate :add_guest, :add_reporter, :add_developer, :add_maintainer, :add_owner, :add_role, to: :team
delegate :group_runners_enabled, :group_runners_enabled=, to: :ci_cd_settings, allow_nil: true
delegate :root_ancestor, to: :namespace, allow_nil: true
delegate :last_pipeline, to: :commit, allow_nil: true

View File

@ -23,6 +23,10 @@ class ProjectTeam
add_user(user, :maintainer, current_user: current_user)
end
def add_owner(user, current_user: nil)
add_user(user, :owner, current_user: current_user)
end
def add_role(user, role, current_user: nil)
public_send(:"add_#{role}", user, current_user: current_user) # rubocop:disable GitlabSecurity/PublicSend
end
@ -103,7 +107,9 @@ class ProjectTeam
if group
group.owners
else
[project.owner]
# workaround until we migrate Project#owners to have membership with
# OWNER access level
Array.wrap(fetch_members(Gitlab::Access::OWNER)) | Array.wrap(project.owner)
end
end

View File

@ -4,7 +4,7 @@ module Members
module Projects
class CreatorService < Members::CreatorService
def self.access_levels
Gitlab::Access.sym_options
Gitlab::Access.sym_options_with_owner
end
private

View File

@ -14,6 +14,7 @@ module NotificationRecipients
return [] unless project
add_recipients(project.team.maintainers, :mention, nil)
add_recipients(project.team.owners, :mention, nil)
end
def acting_user

View File

@ -147,7 +147,11 @@ module Projects
priority: UserProjectAccessChangedService::LOW_PRIORITY
)
else
@project.add_maintainer(@project.namespace.owner, current_user: current_user)
if ::Feature.enabled?(:personal_project_owner_with_owner_access, default_enabled: :yaml)
@project.add_owner(@project.namespace.owner, current_user: current_user)
else
@project.add_maintainer(@project.namespace.owner, current_user: current_user)
end
end
end

View File

@ -2,6 +2,21 @@
- page_title _('Monitor Settings')
- breadcrumb_title _('Monitor Settings')
.gl-alert.gl-alert-danger.gl-mb-5
- removal_epic_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/7188'
- removal_epic_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="gl-link">'.html_safe % { url: removal_epic_link_url }
- opstrace_link_url = 'https://gitlab.com/groups/gitlab-org/-/epics/6976'
- opstrace_link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer" class="gl-link">'.html_safe % { url: opstrace_link_url }
- link_end = '</a>'.html_safe
.gl-alert-container
= sprite_icon('error', css_class: 'gl-icon gl-alert-icon gl-alert-icon-no-title')
.gl-alert-content
.gl-alert-title
= s_('Deprecations|Feature deprecation and removal')
.gl-alert-body
%p
= html_escape(s_('Deprecations|The metrics, logs and tracing features were deprecated in GitLab 14.7, and are %{removal_link_start} scheduled for removal %{link_end} in GitLab 15.0. For information on a possible replacement, %{opstrace_link_start} learn more about Opstrace %{link_end}.')) % {removal_link_start: removal_epic_link_start, opstrace_link_start: opstrace_link_start, link_end: link_end }
= render 'projects/settings/operations/metrics_dashboard'
= render 'projects/settings/operations/tracing'
= render 'projects/settings/operations/error_tracking'

View File

@ -9,4 +9,5 @@ raise "METRICS_SERVER_TARGET cannot be blank" if target.blank?
metrics_dir = ENV["prometheus_multiproc_dir"] || File.absolute_path("tmp/prometheus_multiproc_dir/#{target}")
wipe_metrics_dir = Gitlab::Utils.to_boolean(ENV['WIPE_METRICS_DIR']) || false
Process.wait(MetricsServer.spawn(target, metrics_dir: metrics_dir, wipe_metrics_dir: wipe_metrics_dir))
server = MetricsServer.new(target, metrics_dir, wipe_metrics_dir)
server.start

View File

@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/343917
milestone: '14.5'
type: development
group: group::container security
default_enabled: false
default_enabled: true

View File

@ -0,0 +1,8 @@
---
name: personal_project_owner_with_owner_access
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/78193
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/351919
milestone: '14.8'
type: development
group: group::workspace
default_enabled: false

View File

@ -1,8 +0,0 @@
---
name: prohibit_hexadecimal_branch_names
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/commit/28439ca4b1dd14f22a5a6ad14530f6bf1046f8bc
rollout_issue_url:
milestone: '12.10'
type: development
group: group::source code
default_enabled: true

View File

@ -185,17 +185,17 @@ This allows you to create a single file. For creating multiple files with a sing
POST /projects/:id/repository/files/:file_path
```
| Attribute | Type | Required | Description |
|------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `file_path` | string | yes | URL encoded full path to new file. Ex. `lib%2Fclass%2Erb`. |
| `branch` | string | yes | Name of the branch |
| `start_branch` | string | no | Name of the branch to start the new commit from |
| `encoding` | string | no | Change encoding to `base64`. Default is `text`. |
| `author_email` | string | no | Specify the commit author's email address |
| `author_name` | string | no | Specify the commit author's name |
| `content` | string | yes | File content |
| `commit_message` | string | yes | Commit message |
| Attribute | Type | Required | Description |
| ---------------- | -------------- | -------- | ----------- |
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `file_path` | string | yes | URL-encoded full path to new file. For example: `lib%2Fclass%2Erb`. |
| `branch` | string | yes | Name of the new branch to create. The commit is added to this branch. |
| `start_branch` | string | no | Name of the base branch to create the new branch from. |
| `encoding` | string | no | Change encoding to `base64`. Default is `text`. |
| `author_email` | string | no | The commit author's email address. |
| `author_name` | string | no | The commit author's name. |
| `content` | string | yes | The file's content. |
| `commit_message` | string | yes | The commit message. |
```shell
curl --request POST --header 'PRIVATE-TOKEN: <your_access_token>' \
@ -222,18 +222,18 @@ This allows you to update a single file. For updating multiple files with a sing
PUT /projects/:id/repository/files/:file_path
```
| Attribute | Type | Required | Description |
|------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
| Attribute | Type | Required | Description |
| ---------------- | -------------- | -------- | ----------- |
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `file_path` | string | yes | URL encoded full path to new file. Ex. `lib%2Fclass%2Erb`. |
| `branch` | string | yes | Name of the branch |
| `start_branch` | string | no | Name of the branch to start the new commit from |
| `encoding` | string | no | Change encoding to `base64`. Default is `text`. |
| `author_email` | string | no | Specify the commit author's email address |
| `author_name` | string | no | Specify the commit author's name |
| `content` | string | yes | File content |
| `commit_message` | string | yes | Commit message |
| `last_commit_id` | string | no | Last known file commit ID |
| `file_path` | string | yes | URL-encoded full path to new file. For example: `lib%2Fclass%2Erb`. |
| `branch` | string | yes | Name of the new branch to create. The commit is added to this branch. |
| `start_branch` | string | no | Name of the base branch to create the new branch from. |
| `encoding` | string | no | Change encoding to `base64`. Default is `text`. |
| `author_email` | string | no | The commit author's email address. |
| `author_name` | string | no | The commit author's name. |
| `content` | string | yes | The file's content. |
| `commit_message` | string | yes | The commit message. |
| `last_commit_id` | string | no | Last known file commit ID. |
```shell
curl --request PUT --header 'PRIVATE-TOKEN: <your_access_token>' \
@ -270,16 +270,16 @@ This allows you to delete a single file. For deleting multiple files with a sing
DELETE /projects/:id/repository/files/:file_path
```
| Attribute | Type | Required | Description |
|------------------|----------------|----------|-----------------------------------------------------------------------------------------------------------------|
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user |
| `file_path` | string | yes | URL encoded full path to new file. Ex. `lib%2Fclass%2Erb`. |
| `branch` | string | yes | Name of the branch |
| `start_branch` | string | no | Name of the branch to start the new commit from |
| `author_email` | string | no | Specify the commit author's email address. |
| `author_name` | string | no | Specify the commit author's name. |
| `commit_message` | string | yes | Commit message. |
| `last_commit_id` | string | no | Last known file commit ID. |
| Attribute | Type | Required | Description |
| ---------------- | -------------- | -------- | ----------- |
| `id` | integer or string | yes | The ID or [URL-encoded path of the project](index.md#namespaced-path-encoding) owned by the authenticated user. |
| `file_path` | string | yes | URL-encoded full path to new file. For example: `lib%2Fclass%2Erb`. |
| `branch` | string | yes | Name of the new branch to create. The commit is added to this branch. |
| `start_branch` | string | no | Name of the base branch to create the new branch from. |
| `author_email` | string | no | The commit author's email address. |
| `author_name` | string | no | The commit author's name. |
| `commit_message` | string | yes | The commit message. |
| `last_commit_id` | string | no | Last known file commit ID. |
```shell
curl --request DELETE --header 'PRIVATE-TOKEN: <your_access_token>' \

View File

@ -398,3 +398,14 @@ end
1. Be sure to update the [GitLab CE/EE documentation](../administration/logs.md) and the [GitLab.com
runbooks](https://gitlab.com/gitlab-com/runbooks/blob/master/docs/logging/README.md).
## Control logging visibility
An increase in the logs can cause a growing backlog of unacknowledged messages. When adding new log messages, make sure they don't increase the overall volume of logging by more than 10%.
### Deprecation notices
If the expected volume of deprecation notices is large:
- Only log them in the development environment.
- If needed, log them in the testing environment.

View File

@ -58,7 +58,7 @@ You can configure the following security controls:
- [API Fuzzing](../api_fuzzing/index.md)
- Select **Enable API Fuzzing** to use API Fuzzing for the current project. For more details, read [API Fuzzing](../../../user/application_security/api_fuzzing/index.md#enable-web-api-fuzzing).
- [Coverage Fuzzing](../coverage_fuzzing/index.md)
- Can be configured with `.gitlab-ci.yml`. For more details, read [Coverage Fuzzing](../../../user/application_security/coverage_fuzzing/index.md#configuration).
- Can be configured with `.gitlab-ci.yml`. For more details, read [Coverage Fuzzing](../../../user/application_security/coverage_fuzzing/index.md#enable-coverage-guided-fuzz-testing).
## Compliance **(ULTIMATE)**

View File

@ -22,8 +22,14 @@ The fuzz testing process:
1. Compiles the target application.
1. Runs the instrumented application, using the `gitlab-cov-fuzz` tool.
1. Parses and analyzes the exception information output by the fuzzer.
1. Downloads the [corpus](../terminology/index.md#corpus) and crash events from previous pipelines.
1. Downloads the [corpus](../terminology/index.md#corpus) from either:
- The previous pipelines.
- If `COVFUZZ_USE_REGISTRY` is set to `true`, the [corpus registry](#corpus-registry).
1. Downloads crash events from previous pipeline.
1. Outputs the parsed crash events and data to the `gl-coverage-fuzzing-report.json` file.
1. Updates the corpus, either:
- In the job's pipeline.
- If `COVFUZZ_USE_REGISTRY` is set to `true`, in the corpus registry.
The results of the coverage-guided fuzz testing are available in the CI/CD pipeline.
@ -43,9 +49,20 @@ You can use the following fuzzing engines to test the specified languages.
| Python | [`pythonfuzz`](https://gitlab.com/gitlab-org/security-products/analyzers/fuzzers/pythonfuzz) | [pythonfuzz-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/pythonfuzz-fuzzing-example) |
| AFL (any language that works on top of AFL) | [AFL](https://lcamtuf.coredump.cx/afl/) | [afl-fuzzing-example](https://gitlab.com/gitlab-org/security-products/demos/coverage-fuzzing/afl-fuzzing-example) |
## Configuration
## Confirm status of coverage-guided fuzz testing
To enable coverage-guided fuzz testing, edit the `.gitlab-ci.yml` file:
To confirm the status of coverage-guided fuzz testing:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Security & Compliance > Configuration**.
1. In the **Coverage Fuzzing** section the status is:
- **Not configured**
- **Enabled**
- A prompt to upgrade to GitLab Ultimate.
## Enable coverage-guided fuzz testing
To enable coverage-guided fuzz testing, edit `.gitlab-ci.yml`:
1. Add the `fuzz` stage to the list of stages.
@ -98,10 +115,13 @@ Use the following variables to configure coverage-guided fuzz testing in your CI
| CI/CD variable | Description |
|---------------------------|---------------------------------------------------------------------------------|
| `COVFUZZ_ADDITIONAL_ARGS` | Arguments passed to `gitlab-cov-fuzz`. Used to customize the behavior of the underlying fuzzing engine. Read the fuzzing engine's documentation for a complete list of arguments. |
| `COVFUZZ_ADDITIONAL_ARGS` | Arguments passed to `gitlab-cov-fuzz`. Used to customize the behavior of the underlying fuzzing engine. Read the fuzzing engine's documentation for a complete list of arguments. |
| `COVFUZZ_BRANCH` | The branch on which long-running fuzzing jobs are to be run. On all other branches, only fuzzing regression tests are run. Default: Repository's default branch. |
| `COVFUZZ_SEED_CORPUS` | Path to a seed corpus directory. Default: empty. |
| `COVFUZZ_URL_PREFIX` | Path to the `gitlab-cov-fuzz` repository cloned for use with an offline environment. You should only change this value when using an offline environment. Default: `https://gitlab.com/gitlab-org/security-products/analyzers/gitlab-cov-fuzz/-/raw`. |
| `COVFUZZ_USE_REGISTRY` | Set to `true` to have the corpus stored in the GitLab corpus registry. The variables `COVFUZZ_CORPUS_NAME` and `COVFUZZ_GITLAB_TOKEN` are required if this variable is set to `true`. Default: `false`. [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5017) in GitLab 14.8. |
| `COVFUZZ_CORPUS_NAME` | Name of the corpus to be used in the job. [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5017) in GitLab 14.8. |
| `COVFUZZ_GITLAB_TOKEN` | Environment variable configured with [Personal Access Token](../../../user/profile/personal_access_tokens.md#create-a-personal-access-token) with API read/write access. [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5017) in GitLab 14.8. |
#### Seed corpus
@ -122,7 +142,91 @@ Each fuzzing step outputs these artifacts:
You can download the JSON report file from the CI/CD pipelines page. For more information, see
[Downloading artifacts](../../../ci/pipelines/job_artifacts.md#download-job-artifacts).
### Coverage-guided fuzz testing report
## Corpus registry
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/5017) in GitLab 14.8.
FLAG:
On self-managed GitLab, by default this feature is available. To hide the feature, ask an
administrator to [disable the feature flags](../../../administration/feature_flags.md) named
`corpus_management` and `corpus_management_ui`. On GitLab.com, this feature is available.
The corpus registry is a library of corpuses. Corpuses in a project's registry are available to
all jobs in that project. A project-wide registry is a more efficient way to manage corpuses than
the default option of one corpus per job.
The corpus registry uses the package registry to store the project's corpuses. Corpuses stored in
the registry are hidden to ensure data integrity.
In the GitLab UI, with corpus management you can:
- View details of the corpus registry.
- Download a corpus.
- Delete a corpus.
- Create a new corpus.
When you download a corpus, the file is named `artifacts.zip`, regardless of the filename used when
the corpus was initially uploaded. This file contains only the corpus, which is different to the
artifacts files you can download from the CI/CD pipeline.
### View details of the corpus registry
To view details of the corpus registry:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Security & Compliance > Configuration**.
1. In the **Coverage Fuzzing** section, select **Manage corpus**.
### Create a corpus in the corpus registry
To create a corpus in the corpus registry, either:
- Create a corpus in a pipeline
- Upload an existing corpus file
#### Create a corpus in a pipeline
To create a corpus in a pipeline:
1. In the `.gitlab-ci.yml` file, edit the `my_fuzz_target` job.
1. Set the following variables:
- Set `COVFUZZ_USE_REGISTRY` to `true`.
- Set `COVFUZZ_CORPUS_NAME` to name the corpus.
- Set `COVFUZZ_GITLAB_TOKEN` to the value of the personal access token.
After the `my_fuzz_target` job runs, the corpus is stored in the corpus registry, with the name
provided by the `COVFUZZ_CORPUS_NAME` variable. The corpus is updated on every pipeline run.
#### Upload a corpus file
To upload an existing corpus file:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Security & Compliance > Configuration**.
1. In the **Coverage Fuzzing** section, select **Manage corpus**.
1. Select **New corpus**.
1. Complete the fields.
1. Select **Upload file**.
1. Select **Add**.
You can now reference the corpus in the `.gitlab-ci.yml` file. Ensure the value used in the
`COVFUZZ_CORPUS_NAME` variable matches exactly the name given to the uploaded corpus file.
### Use a corpus stored in the corpus registry
To use a corpus stored in the corpus registry, you must reference it by its name. To confirm the
name of the relevant corpus, view details of the corpus registry.
Prerequisites:
- [Enable coverage-guide fuzz testing](#enable-coverage-guided-fuzz-testing) in the project.
1. Set the following variables in the `.gitlab-ci.yml` file:
- Set `COVFUZZ_USE_REGISTRY` to `true`.
- Set `COVFUZZ_CORPUS_NAME` to the name of the corpus.
- Set `COVFUZZ_GITLAB_TOKEN` to the value of the personal access token.
## Coverage-guided fuzz testing report
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/220062) in GitLab 13.3 as an [Alpha feature](../../../policy/alpha-beta-support.md#alpha-features).
@ -255,3 +359,16 @@ vulnerability:
engines listed in [Supported fuzzing engines and languages](#supported-fuzzing-engines-and-languages).
<!-- vale gitlab.Acronyms = YES -->
## Troubleshooting
### Error "Unable to extract corpus folder from artifacts zip file"
If you see this error message, and `COVFUZZ_USE_REGISTRY` is set to `true`, ensure that the uploaded
corpus file extracts into a folder named `corpus`.
### Error "400 Bad request - Duplicate package is not allowed"
If you see this error message when running the fuzzing job with `COVFUZZ_USE_REGISTRY` set to `true`,
ensure that duplicates are allowed. For more details, see
[duplicate Generic packages](../../packages/generic_packages/#do-not-allow-duplicate-generic-packages).

View File

@ -196,7 +196,7 @@ see the [related epic](https://gitlab.com/groups/gitlab-org/-/epics/4739).
### View vulnerabilities in cluster images **(ULTIMATE)**
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6346) in GitLab 14.8 [with a flag](../../../../administration/feature_flags.md) named `cluster_vulnerabilities`. Disabled by default.
> [Introduced](https://gitlab.com/groups/gitlab-org/-/epics/6346) in GitLab 14.8 [with a flag](../../../../administration/feature_flags.md) named `cluster_vulnerabilities`. Enabled by default.
Users with at least the [Developer role](../../../permissions.md)
can view cluster vulnerabilities. You can access them through the [vulnerability report](../../../application_security/vulnerabilities/index.md)

View File

@ -280,10 +280,15 @@ To view the activity feed in Atom format, select the
## Share a group with another group
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18328) in GitLab 12.7.
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/18328) in GitLab 12.7.
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11 from a form to a modal window [with a flag](../feature_flags.md). Disabled by default.
> - Modal window [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 14.8.
NOTE:
In GitLab 13.11, you can [replace this form with a modal window](#share-a-group-modal-window).
FLAG:
On self-managed GitLab, by default the modal window feature is available.
To hide the feature, ask an administrator to [disable the feature flag](../../administration/feature_flags.md)
named `invite_members_group_modal`.
On GitLab.com, this feature is available.
Similar to how you [share a project with a group](../project/members/share_project_with_groups.md),
you can share a group with another group. Members get direct access
@ -293,35 +298,14 @@ To share a given group, for example, `Frontend` with another group, for example,
`Engineering`:
1. Go to the `Frontend` group.
1. From the left menu, select **Group information > Members**.
1. Select the **Invite group** tab.
1. On the left sidebar, select **Group information > Members**.
1. Select **Invite a group**.
1. In the **Select a group to invite** list, select `Engineering`.
1. For the **Max role**, select a [role](../permissions.md).
1. Select a [role](../permissions.md).
1. Select **Invite**.
All the members of the `Engineering` group are added to the `Frontend` group.
### Share a group modal window
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11.
> - [Deployed behind a feature flag](../feature_flags.md), disabled by default.
> - Enabled on GitLab.com.
> - Recommended for production use.
> - Replaces the existing form with buttons to open a modal window.
> - To use in GitLab self-managed instances, ask a GitLab administrator to [enable it](../project/members/index.md#enable-or-disable-modal-window).
WARNING:
This feature might not be available to you. Check the **version history** note above for details.
In GitLab 13.11, you can optionally replace the sharing form with a modal window.
To share a group after enabling this feature:
1. Go to your group's page.
1. On the left sidebar, go to **Group information > Members**, and then select **Invite a group**.
1. Select a group, and select a **Max role**.
1. Optional. Select an **Access expiration date**.
1. Select **Invite**.
## Manage group memberships via LDAP **(PREMIUM SELF)**
Group syncing allows LDAP groups to be mapped to GitLab groups. This provides more control over per-group user management. To configure group syncing, edit the `group_base` **DN** (`'OU=Global Groups,OU=GitLab INT,DC=GitLab,DC=org'`). This **OU** contains all groups that will be associated with GitLab groups.

View File

@ -33,14 +33,27 @@ usernames. A GitLab administrator can configure the GitLab instance to
## Project members permissions
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/219299) in GitLab 14.8, personal namespace owners appear with Owner role in new projects in their namespace. Introduced [with a flag](../administration/feature_flags.md) named `personal_project_owner_with_owner_access`. Disabled by default.
FLAG:
On self-managed GitLab, personal namespace owners appearing with the Owner role in new projects in their namespace is disabled. To make it available,
ask an administrator to [enable the feature flag](../administration/feature_flags.md) named `personal_project_owner_with_owner_access`.
The feature is not ready for production use.
On GitLab.com, this feature is not available.
A user's role determines what permissions they have on a project. The Owner role provides all permissions but is
available only:
- For group owners. The role is inherited for a group's projects.
- For Administrators.
Personal namespace owners have the same permissions as an Owner, but are displayed with the Maintainer role on projects created in their personal namespace.
For more information, see [projects members documentation](project/members/index.md).
Personal [namespace](group/index.md#namespaces) owners:
- Are displayed as having the Maintainer role on projects in the namespace, but have the same permissions as a user with the Owner role.
- (Disabled by default) In GitLab 14.8 and later, for new projects in the namespace, are displayed as having the Owner role.
For more information about how to manage project members, see
[members of a project](project/members/index.md).
The following table lists project permissions available for each role:

View File

@ -12,6 +12,15 @@ Each member gets a role, which determines what they can do in the project.
## Add users to a project
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11 from a form to a modal window [with a flag](../../feature_flags.md). Disabled by default.
> - Modal window [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 14.8.
FLAG:
On self-managed GitLab, by default the modal window feature is available.
To hide the feature, ask an administrator to [disable the feature flag](../../../administration/feature_flags.md)
named `invite_members_group_modal`.
On GitLab.com, this feature is available.
Add users to a project so they become members and have permission
to perform actions.
@ -21,11 +30,12 @@ Prerequisite:
To add a user to a project:
1. Go to your project and select **Project information > Members**.
1. On the **Invite member** tab, under **GitLab member or Email address**, type the username or email address.
In GitLab 13.11 and later, you can [replace this form with a modal window](#add-a-member-modal-window).
1. Select a [role](../../permissions.md).
1. Optional. Choose an expiration date. On that date, the user can no longer access the project.
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Project information > Members**.
1. Select **Invite members**.
1. Enter an email address and select a [role](../../permissions.md).
1. Optional. Select an **Access expiration date**.
On that date, the user can no longer access the project.
1. Select **Invite**.
If the user has a GitLab account, they are added to the members list.
@ -40,6 +50,15 @@ using the email address the invitation was sent to.
## Add groups to a project
> - [Changed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11 from a form to a modal window [with a flag](../../feature_flags.md). Disabled by default.
> - Modal window [enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 14.8.
FLAG:
On self-managed GitLab, by default the modal window feature is available.
To hide the feature, ask an administrator to [disable the feature flag](../../../administration/feature_flags.md)
named `invite_members_group_modal`.
On GitLab.com, this feature is available.
When you add a group to a project, each user in the group gets access to the project.
Each user's access is based on:
@ -54,9 +73,10 @@ To add groups to a project:
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Project information > Members**.
1. On the **Invite group** tab, under **Select a group to invite**, choose a group.
1. Select the highest max [role](../../permissions.md) for users in the group.
1. Optional. Choose an expiration date. On that date, the user can no longer access the project.
1. Select **Invite a group**.
1. Select a group.
1. Select the highest [role](../../permissions.md) for users in the group.
1. Optional. Select an **Access expiration date**. On that date, the group can no longer access the project.
1. Select **Invite**.
The members of the group are not displayed on the **Members** tab.
@ -203,40 +223,3 @@ Prerequisite:
## Share a project with a group
Instead of adding users one by one, you can [share a project with an entire group](share_project_with_groups.md).
### Add a member modal window
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 13.11 [with a flag](../../feature_flags.md). Disabled by default.
> - Replaces the existing form with buttons to open a modal window.
> - [Enabled on GitLab.com and self-managed](https://gitlab.com/gitlab-org/gitlab/-/issues/247208) in GitLab 14.8.
FLAG:
On self-managed GitLab, by default this feature is available.
To hide the feature, ask an administrator to [disable the feature flag](#enable-or-disable-modal-window).
On GitLab.com, this feature is available.
1. On the top bar, select **Menu > Projects** and find your project.
1. On the left sidebar, select **Project information > Members**.
1. Select **Invite members**.
1. Enter an email address and select a role.
1. Optional. Select an **Access expiration date**.
1. Select **Invite**.
### Enable or disable modal window **(FREE SELF)**
The modal window for adding a member is under development and is 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 enable it.
To enable it:
```ruby
Feature.enable(:invite_members_group_modal)
```
To disable it:
```ruby
Feature.disable(:invite_members_group_modal)
```

View File

@ -33,7 +33,13 @@ module Gitlab
MAINTAINER_SUBGROUP_ACCESS = 1
class << self
delegate :values, to: :options
def values
if ::Feature.enabled?(:personal_project_owner_with_owner_access, default_enabled: :yaml)
options_with_owner.values
else
options.values
end
end
def all_values
options_with_owner.values

View File

@ -41,7 +41,6 @@ module Gitlab
def prohibited_branch_checks
return if deletion?
return unless Feature.enabled?(:prohibit_hexadecimal_branch_names, project, default_enabled: true)
if branch_name =~ /\A\h{40}\z/
raise GitAccess::ForbiddenError, ERROR_MESSAGES[:prohibited_hex_branch_name]

View File

@ -22,7 +22,7 @@ module Gitlab
user.projects_with_active_memberships.select_for_project_authorization,
# The personal projects of the user.
user.personal_projects.select_as_maintainer_for_project_authorization,
user.personal_projects.select_project_owner_for_project_authorization,
# Projects that belong directly to any of the groups the user has
# access to.

View File

@ -12510,10 +12510,10 @@ msgstr ""
msgid "DevopsAdoption|At least one deploy"
msgstr ""
msgid "DevopsAdoption|At least one issue opened"
msgid "DevopsAdoption|At least one issue created"
msgstr ""
msgid "DevopsAdoption|At least one merge request opened"
msgid "DevopsAdoption|At least one merge request created"
msgstr ""
msgid "DevopsAdoption|At least one pipeline successfully run"
@ -17143,7 +17143,7 @@ msgstr ""
msgid "Group: %{name}"
msgstr ""
msgid "GroupActivityMetrics|Issues opened"
msgid "GroupActivityMetrics|Issues created"
msgstr ""
msgid "GroupActivityMetrics|Last 90 days"
@ -17152,7 +17152,7 @@ msgstr ""
msgid "GroupActivityMetrics|Members added"
msgstr ""
msgid "GroupActivityMetrics|Merge Requests opened"
msgid "GroupActivityMetrics|Merge Requests created"
msgstr ""
msgid "GroupActivityMetrics|Recent activity"
@ -20164,6 +20164,9 @@ msgstr ""
msgid "IssueAnalytics|Assignees"
msgstr ""
msgid "IssueAnalytics|Created by"
msgstr ""
msgid "IssueAnalytics|Due date"
msgstr ""
@ -20176,9 +20179,6 @@ msgstr ""
msgid "IssueAnalytics|Milestone"
msgstr ""
msgid "IssueAnalytics|Opened by"
msgstr ""
msgid "IssueAnalytics|Status"
msgstr ""
@ -20302,10 +20302,10 @@ msgstr ""
msgid "IssuesAnalytics|Avg/Month:"
msgstr ""
msgid "IssuesAnalytics|Issues opened"
msgid "IssuesAnalytics|Issues created"
msgstr ""
msgid "IssuesAnalytics|Issues opened per month"
msgid "IssuesAnalytics|Issues created per month"
msgstr ""
msgid "IssuesAnalytics|Last 12 months"
@ -25429,7 +25429,7 @@ msgstr ""
msgid "Opened issues"
msgstr ""
msgid "OpenedNDaysAgo|Opened"
msgid "OpenedNDaysAgo|Created"
msgstr ""
msgid "Opens in a new window"
@ -43756,9 +43756,6 @@ msgstr ""
msgid "open issue"
msgstr ""
msgid "opened %{timeAgo}"
msgstr ""
msgid "or"
msgstr ""

View File

@ -6,8 +6,23 @@ require_relative 'dependencies'
class MetricsServer # rubocop:disable Gitlab/NamespacedClass
class << self
def spawn(target, metrics_dir:, wipe_metrics_dir: false, trapped_signals: [])
raise "Target must be one of [puma,sidekiq]" unless %w(puma sidekiq).include?(target)
def spawn(target, metrics_dir:, gitlab_config: nil, wipe_metrics_dir: false)
ensure_valid_target!(target)
cmd = "#{Rails.root}/bin/metrics-server"
env = {
'METRICS_SERVER_TARGET' => target,
'WIPE_METRICS_DIR' => wipe_metrics_dir ? '1' : '0'
}
env['GITLAB_CONFIG'] = gitlab_config if gitlab_config
Process.spawn(env, cmd, err: $stderr, out: $stdout, pgroup: true).tap do |pid|
Process.detach(pid)
end
end
def fork(target, metrics_dir:, wipe_metrics_dir: false, reset_signals: [])
ensure_valid_target!(target)
pid = Process.fork
@ -15,7 +30,7 @@ class MetricsServer # rubocop:disable Gitlab/NamespacedClass
# Remove any custom signal handlers the parent process had registered, since we do
# not want to inherit them, and Ruby forks with a `clone` that has the `CLONE_SIGHAND`
# flag set.
Gitlab::ProcessManagement.modify_signals(trapped_signals, 'DEFAULT')
Gitlab::ProcessManagement.modify_signals(reset_signals, 'DEFAULT')
server = MetricsServer.new(target, metrics_dir, wipe_metrics_dir)
# This rewrites /proc/cmdline, since otherwise tools like `top` will show the
@ -29,6 +44,12 @@ class MetricsServer # rubocop:disable Gitlab/NamespacedClass
pid
end
private
def ensure_valid_target!(target)
raise "Target must be one of [puma,sidekiq]" unless %w(puma sidekiq).include?(target)
end
end
def initialize(target, metrics_dir, wipe_metrics_dir)
@ -40,7 +61,7 @@ class MetricsServer # rubocop:disable Gitlab/NamespacedClass
def start
::Prometheus::Client.configure do |config|
config.multiprocess_files_dir = @metrics_dir
config.pid_provider = proc { "#{@target}_exporter" }
config.pid_provider = proc { name }
end
FileUtils.mkdir_p(@metrics_dir, mode: 0700)
@ -57,16 +78,18 @@ class MetricsServer # rubocop:disable Gitlab/NamespacedClass
case @target
when 'puma'
Gitlab::Metrics::Exporter::WebExporter.instance(**default_opts)
else
exporter_class = "Gitlab::Metrics::Exporter::#{@target.camelize}Exporter".constantize
when 'sidekiq'
settings = Settings.new(Settings.monitoring[name])
exporter_class.instance(settings, **default_opts)
Gitlab::Metrics::Exporter::SidekiqExporter.instance(settings, **default_opts)
end
exporter.start
end
def name
"#{@target}_exporter"
case @target
when 'puma' then 'web_exporter'
when 'sidekiq' then 'sidekiq_exporter'
end
end
end

View File

@ -59,8 +59,8 @@
"@gitlab/svgs": "2.5.0",
"@gitlab/ui": "36.1.0",
"@gitlab/visual-review-tools": "1.6.1",
"@rails/actioncable": "6.1.4-1",
"@rails/ujs": "6.1.4-1",
"@rails/actioncable": "6.1.4-6",
"@rails/ujs": "6.1.4-6",
"@sentry/browser": "5.30.0",
"@sourcegraph/code-host-integration": "0.0.60",
"@tiptap/core": "^2.0.0-beta.171",

View File

@ -3,7 +3,7 @@
source 'https://rubygems.org'
gem 'gitlab-qa', require: 'gitlab/qa'
gem 'activesupport', '~> 6.1.4.1' # This should stay in sync with the root's Gemfile
gem 'activesupport', '~> 6.1.4.6' # This should stay in sync with the root's Gemfile
gem 'allure-rspec', '~> 2.15.0'
gem 'capybara', '~> 3.35.0'
gem 'capybara-screenshot', '~> 1.0.23'

View File

@ -2,7 +2,7 @@ GEM
remote: https://rubygems.org/
specs:
abstract_type (0.0.7)
activesupport (6.1.4.1)
activesupport (6.1.4.6)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
@ -226,6 +226,7 @@ GEM
rack (2.2.3)
rack-test (1.1.0)
rack (>= 1.0, < 3)
rainbow (3.0.0)
rake (13.0.6)
regexp_parser (2.1.1)
representable (3.1.1)
@ -321,7 +322,7 @@ PLATFORMS
ruby
DEPENDENCIES
activesupport (~> 6.1.4.1)
activesupport (~> 6.1.4.6)
airborne (~> 0.3.4)
allure-rspec (~> 2.15.0)
capybara (~> 3.35.0)
@ -339,6 +340,7 @@ DEPENDENCIES
parallel (~> 1.19)
parallel_tests (~> 2.29)
pry-byebug (~> 3.5.1)
rainbow (~> 3.0.0)
rake (~> 13)
rest-client (~> 2.1.0)
rotp (~> 3.1.0)

View File

@ -191,11 +191,11 @@ module Gitlab
return unless metrics_server_enabled?
@logger.info("Starting metrics server on port #{sidekiq_exporter_port}")
@metrics_server_pid = MetricsServer.spawn(
@metrics_server_pid = MetricsServer.fork(
'sidekiq',
metrics_dir: @metrics_dir,
wipe_metrics_dir: wipe_metrics_dir,
trapped_signals: TERMINATE_SIGNALS + FORWARD_SIGNALS
reset_signals: TERMINATE_SIGNALS + FORWARD_SIGNALS
)
end

View File

@ -38,13 +38,7 @@ RSpec.describe 'bin/metrics-server', :aggregate_failures do
config_file.write(YAML.dump(config))
config_file.close
env = {
'GITLAB_CONFIG' => config_file.path,
'METRICS_SERVER_TARGET' => target,
'WIPE_METRICS_DIR' => '1',
'prometheus_multiproc_dir' => metrics_dir
}
@pid = Process.spawn(env, 'bin/metrics-server', pgroup: true)
@pid = MetricsServer.spawn(target, metrics_dir: metrics_dir, gitlab_config: config_file.path, wipe_metrics_dir: true)
end
after do

View File

@ -303,7 +303,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubo
end
it 'does not start a sidekiq metrics server' do
expect(MetricsServer).not_to receive(:spawn)
expect(MetricsServer).not_to receive(:fork)
cli.run(%w(foo))
end
@ -320,7 +320,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubo
end
it 'does not start a sidekiq metrics server' do
expect(MetricsServer).not_to receive(:spawn)
expect(MetricsServer).not_to receive(:fork)
cli.run(%w(foo))
end
@ -350,7 +350,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubo
end
it 'does not start a sidekiq metrics server' do
expect(MetricsServer).not_to receive(:spawn)
expect(MetricsServer).not_to receive(:fork)
cli.run(%w(foo))
end
@ -376,7 +376,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubo
end
it 'does not start a sidekiq metrics server' do
expect(MetricsServer).not_to receive(:spawn)
expect(MetricsServer).not_to receive(:fork)
cli.run(%w(foo))
end
@ -406,9 +406,9 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubo
specify do
if start_metrics_server
expect(MetricsServer).to receive(:spawn).with('sidekiq', metrics_dir: metrics_dir, wipe_metrics_dir: true, trapped_signals: trapped_signals)
expect(MetricsServer).to receive(:fork).with('sidekiq', metrics_dir: metrics_dir, wipe_metrics_dir: true, reset_signals: trapped_signals)
else
expect(MetricsServer).not_to receive(:spawn)
expect(MetricsServer).not_to receive(:fork)
end
cli.run(%w(foo))
@ -421,7 +421,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubo
let(:sidekiq_exporter_enabled) { true }
it 'does not start the server' do
expect(MetricsServer).not_to receive(:spawn)
expect(MetricsServer).not_to receive(:fork)
cli.run(%w(foo --dryrun))
end
@ -434,7 +434,7 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubo
before do
allow(cli).to receive(:sleep).with(a_kind_of(Numeric))
allow(MetricsServer).to receive(:spawn).and_return(99)
allow(MetricsServer).to receive(:fork).and_return(99)
cli.start_metrics_server
end
@ -453,8 +453,8 @@ RSpec.describe Gitlab::SidekiqCluster::CLI, stub_settings_source: true do # rubo
allow(Gitlab::ProcessManagement).to receive(:all_alive?).with(an_instance_of(Array)).and_return(false)
allow(cli).to receive(:stop_metrics_server)
expect(MetricsServer).to receive(:spawn).with(
'sidekiq', metrics_dir: metrics_dir, wipe_metrics_dir: false, trapped_signals: trapped_signals
expect(MetricsServer).to receive(:fork).with(
'sidekiq', metrics_dir: metrics_dir, wipe_metrics_dir: false, reset_signals: trapped_signals
)
cli.start_loop

View File

@ -665,7 +665,7 @@ RSpec.describe Projects::ProjectMembersController do
sign_in(user)
end
it 'does not create a member' do
it 'creates a member' do
expect do
post :create, params: {
user_ids: stranger.id,
@ -673,7 +673,9 @@ RSpec.describe Projects::ProjectMembersController do
access_level: Member::OWNER,
project_id: project
}
end.to change { project.members.count }.by(0)
end.to change { project.members.count }.by(1)
expect(project.team_members).to include(user)
end
end

View File

@ -11,21 +11,40 @@ RSpec.describe Projects::Members::EffectiveAccessLevelFinder, '#execute' do
context 'for a personal project' do
let_it_be(:project) { create(:project) }
shared_examples_for 'includes access level of the owner of the project as Maintainer' do
it 'includes access level of the owner of the project as Maintainer' do
expect(subject).to(
contain_exactly(
hash_including(
'user_id' => project.namespace.owner.id,
'access_level' => Gitlab::Access::MAINTAINER
shared_examples_for 'includes access level of the owner of the project' do
context 'when personal_project_owner_with_owner_access feature flag is enabled' do
it 'includes access level of the owner of the project as Owner' do
expect(subject).to(
contain_exactly(
hash_including(
'user_id' => project.namespace.owner.id,
'access_level' => Gitlab::Access::OWNER
)
)
)
)
end
end
context 'when personal_project_owner_with_owner_access feature flag is disabled' do
before do
stub_feature_flags(personal_project_owner_with_owner_access: false)
end
it 'includes access level of the owner of the project as Maintainer' do
expect(subject).to(
contain_exactly(
hash_including(
'user_id' => project.namespace.owner.id,
'access_level' => Gitlab::Access::MAINTAINER
)
)
)
end
end
end
context 'when the project owner is a member of the project' do
it_behaves_like 'includes access level of the owner of the project as Maintainer'
it_behaves_like 'includes access level of the owner of the project'
end
context 'when the project owner is not explicitly a member of the project' do
@ -33,7 +52,7 @@ RSpec.describe Projects::Members::EffectiveAccessLevelFinder, '#execute' do
project.members.find_by(user_id: project.namespace.owner.id).destroy!
end
it_behaves_like 'includes access level of the owner of the project as Maintainer'
it_behaves_like 'includes access level of the owner of the project'
end
end
@ -84,17 +103,32 @@ RSpec.describe Projects::Members::EffectiveAccessLevelFinder, '#execute' do
context 'for a project within a group' do
context 'project in a root group' do
it 'includes access levels of users who are direct members of the parent group' do
group_member = create(:group_member, :developer, source: group)
context 'includes access levels of users who are direct members of the parent group' do
it 'when access level is developer' do
group_member = create(:group_member, :developer, source: group)
expect(subject).to(
include(
hash_including(
'user_id' => group_member.user.id,
'access_level' => Gitlab::Access::DEVELOPER
expect(subject).to(
include(
hash_including(
'user_id' => group_member.user.id,
'access_level' => Gitlab::Access::DEVELOPER
)
)
)
)
end
it 'when access level is owner' do
group_member = create(:group_member, :owner, source: group)
expect(subject).to(
include(
hash_including(
'user_id' => group_member.user.id,
'access_level' => Gitlab::Access::OWNER
)
)
)
end
end
end

View File

@ -40,15 +40,6 @@ RSpec.describe Gitlab::Checks::BranchCheck do
expect { subject.validate! }.not_to raise_error
end
end
context "the feature flag is disabled" do
it "doesn't prohibit a 40-character hexadecimal branch name" do
stub_feature_flags(prohibit_hexadecimal_branch_names: false)
allow(subject).to receive(:branch_name).and_return("267208abfe40e546f5e847444276f7d43a39503e")
expect { subject.validate! }.not_to raise_error
end
end
end
context 'protected branches check' do

View File

@ -47,13 +47,15 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
end
def loggable_data(count:, db_count: nil)
keys = %w[
database_name = Ci::ApplicationRecord.connection.pool.db_config.name
keys = %W[
expensive_operation_duration_s
expensive_operation_db_count
expensive_operation_db_primary_count
expensive_operation_db_primary_duration_s
expensive_operation_db_main_count
expensive_operation_db_main_duration_s
expensive_operation_db_#{database_name}_count
expensive_operation_db_#{database_name}_duration_s
]
data = keys.each.with_object({}) do |key, accumulator|
@ -75,7 +77,7 @@ RSpec.describe ::Gitlab::Ci::Pipeline::Logger do
end
context 'with a single query' do
let(:operation) { -> { Project.count } }
let(:operation) { -> { Ci::Pipeline.count } }
it { is_expected.to eq(operation.call) }

View File

@ -439,6 +439,12 @@ RSpec.describe Gitlab::Database::Migrations::BackgroundMigrationHelpers do
end
context 'when the migration is running against the ci database', if: Gitlab::Database.has_config?(:ci) do
around do |example|
Gitlab::Database::SharedModel.using_connection(::Ci::ApplicationRecord.connection) do
example.run
end
end
it_behaves_like 'helpers that enqueue background migrations', BackgroundMigration::CiDatabaseWorker, 'ci'
end

View File

@ -34,12 +34,28 @@ RSpec.describe Gitlab::ProjectAuthorizations do
.to include(owned_project.id, other_project.id, group_project.id)
end
it 'includes the correct access levels' do
mapping = map_access_levels(authorizations)
context 'when personal_project_owner_with_owner_access feature flag is enabled' do
it 'includes the correct access levels' do
mapping = map_access_levels(authorizations)
expect(mapping[owned_project.id]).to eq(Gitlab::Access::MAINTAINER)
expect(mapping[other_project.id]).to eq(Gitlab::Access::REPORTER)
expect(mapping[group_project.id]).to eq(Gitlab::Access::DEVELOPER)
expect(mapping[owned_project.id]).to eq(Gitlab::Access::OWNER)
expect(mapping[other_project.id]).to eq(Gitlab::Access::REPORTER)
expect(mapping[group_project.id]).to eq(Gitlab::Access::DEVELOPER)
end
end
context 'when personal_project_owner_with_owner_access feature flag is disabled' do
before do
stub_feature_flags(personal_project_owner_with_owner_access: false)
end
it 'includes the correct access levels' do
mapping = map_access_levels(authorizations)
expect(mapping[owned_project.id]).to eq(Gitlab::Access::MAINTAINER)
expect(mapping[other_project.id]).to eq(Gitlab::Access::REPORTER)
expect(mapping[group_project.id]).to eq(Gitlab::Access::DEVELOPER)
end
end
end

View File

@ -36,13 +36,13 @@ RSpec.describe MetricsServer do # rubocop:disable RSpec/FilePath
%w(puma sidekiq).each do |target|
context "when targeting #{target}" do
describe '.spawn' do
describe '.fork' do
context 'when in parent process' do
it 'forks into a new process and detaches it' do
expect(Process).to receive(:fork).and_return(99)
expect(Process).to receive(:detach).with(99)
described_class.spawn(target, metrics_dir: metrics_dir)
described_class.fork(target, metrics_dir: metrics_dir)
end
end
@ -58,13 +58,47 @@ RSpec.describe MetricsServer do # rubocop:disable RSpec/FilePath
expect(server).to receive(:start)
end
described_class.spawn(target, metrics_dir: metrics_dir)
described_class.fork(target, metrics_dir: metrics_dir)
end
it 'resets signal handlers from parent process' do
expect(Gitlab::ProcessManagement).to receive(:modify_signals).with(%i[A B], 'DEFAULT')
described_class.spawn(target, metrics_dir: metrics_dir, trapped_signals: %i[A B])
described_class.fork(target, metrics_dir: metrics_dir, reset_signals: %i[A B])
end
end
end
describe '.spawn' do
let(:expected_env) do
{
'METRICS_SERVER_TARGET' => target,
'WIPE_METRICS_DIR' => '0'
}
end
it 'spawns a new server process and returns its PID' do
expect(Process).to receive(:spawn).with(
expected_env,
end_with('bin/metrics-server'),
hash_including(pgroup: true)
).and_return(99)
expect(Process).to receive(:detach).with(99)
pid = described_class.spawn(target, metrics_dir: metrics_dir)
expect(pid).to eq(99)
end
context 'when path to gitlab.yml is passed' do
it 'sets the GITLAB_CONFIG environment variable' do
expect(Process).to receive(:spawn).with(
expected_env.merge('GITLAB_CONFIG' => 'path/to/config/gitlab.yml'),
end_with('bin/metrics-server'),
hash_including(pgroup: true)
).and_return(99)
described_class.spawn(target, metrics_dir: metrics_dir, gitlab_config: 'path/to/config/gitlab.yml')
end
end
end
@ -72,6 +106,14 @@ RSpec.describe MetricsServer do # rubocop:disable RSpec/FilePath
end
context 'when targeting invalid target' do
describe '.fork' do
it 'raises an error' do
expect { described_class.fork('unsupported', metrics_dir: metrics_dir) }.to(
raise_error('Target must be one of [puma,sidekiq]')
)
end
end
describe '.spawn' do
it 'raises an error' do
expect { described_class.spawn('unsupported', metrics_dir: metrics_dir) }.to(
@ -81,64 +123,86 @@ RSpec.describe MetricsServer do # rubocop:disable RSpec/FilePath
end
end
describe '#start' do
let(:exporter_class) { Class.new(Gitlab::Metrics::Exporter::BaseExporter) }
let(:exporter_double) { double('fake_exporter', start: true) }
let(:settings) { { "fake_exporter" => { "enabled" => true } } }
shared_examples 'a metrics exporter' do |target, expected_name|
describe '#start' do
let(:exporter_double) { double('exporter', start: true) }
let(:wipe_metrics_dir) { true }
subject(:metrics_server) { described_class.new('fake', metrics_dir, true)}
subject(:metrics_server) { described_class.new(target, metrics_dir, wipe_metrics_dir) }
before do
stub_const('Gitlab::Metrics::Exporter::FakeExporter', exporter_class)
expect(exporter_class).to receive(:instance).with(
settings['fake_exporter'], gc_requests: true, synchronous: true
).and_return(exporter_double)
expect(Settings).to receive(:monitoring).and_return(settings)
end
it 'configures ::Prometheus::Client' do
metrics_server.start
it 'configures ::Prometheus::Client' do
metrics_server.start
expect(prometheus_config.multiprocess_files_dir).to eq metrics_dir
expect(::Prometheus::Client.configuration.pid_provider.call).to eq expected_name
end
expect(prometheus_config.multiprocess_files_dir).to eq metrics_dir
expect(::Prometheus::Client.configuration.pid_provider.call).to eq 'fake_exporter'
end
it 'ensures that metrics directory exists in correct mode (0700)' do
expect(FileUtils).to receive(:mkdir_p).with(metrics_dir, mode: 0700)
it 'ensures that metrics directory exists in correct mode (0700)' do
expect(FileUtils).to receive(:mkdir_p).with(metrics_dir, mode: 0700)
metrics_server.start
end
metrics_server.start
end
context 'when wipe_metrics_dir is true' do
it 'removes any old metrics files' do
FileUtils.touch("#{metrics_dir}/remove_this.db")
context 'when wipe_metrics_dir is true' do
subject(:metrics_server) { described_class.new('fake', metrics_dir, true)}
expect { metrics_server.start }.to change { Dir.empty?(metrics_dir) }.from(false).to(true)
end
end
it 'removes any old metrics files' do
FileUtils.touch("#{metrics_dir}/remove_this.db")
context 'when wipe_metrics_dir is false' do
let(:wipe_metrics_dir) { false }
expect { metrics_server.start }.to change { Dir.empty?(metrics_dir) }.from(false).to(true)
it 'does not remove any old metrics files' do
FileUtils.touch("#{metrics_dir}/remove_this.db")
expect { metrics_server.start }.not_to change { Dir.empty?(metrics_dir) }.from(false)
end
end
it 'starts a metrics server' do
expect(exporter_double).to receive(:start)
metrics_server.start
end
it 'starts a RubySampler instance' do
expect(ruby_sampler_double).to receive(:start)
subject.start
end
end
context 'when wipe_metrics_dir is false' do
subject(:metrics_server) { described_class.new('fake', metrics_dir, false)}
describe '#name' do
let(:exporter_double) { double('exporter', start: true) }
it 'does not remove any old metrics files' do
FileUtils.touch("#{metrics_dir}/remove_this.db")
subject(:name) { described_class.new(target, metrics_dir, true).name }
expect { metrics_server.start }.not_to change { Dir.empty?(metrics_dir) }.from(false)
end
end
it 'starts a metrics server' do
expect(exporter_double).to receive(:start)
metrics_server.start
end
it 'starts a RubySampler instance' do
expect(ruby_sampler_double).to receive(:start)
subject.start
it { is_expected.to eq(expected_name) }
end
end
context 'for puma' do
before do
allow(Gitlab::Metrics::Exporter::WebExporter).to receive(:instance).with(
gc_requests: true, synchronous: true
).and_return(exporter_double)
end
it_behaves_like 'a metrics exporter', 'puma', 'web_exporter'
end
context 'for sidekiq' do
let(:settings) { { "sidekiq_exporter" => { "enabled" => true } } }
before do
allow(::Settings).to receive(:monitoring).and_return(settings)
allow(Gitlab::Metrics::Exporter::SidekiqExporter).to receive(:instance).with(
settings['sidekiq_exporter'], gc_requests: true, synchronous: true
).and_return(exporter_double)
end
it_behaves_like 'a metrics exporter', 'sidekiq', 'sidekiq_exporter'
end
end

View File

@ -225,7 +225,7 @@ RSpec.describe ProjectTeam do
let_it_be(:maintainer) { create(:user) }
let_it_be(:developer) { create(:user) }
let_it_be(:guest) { create(:user) }
let_it_be(:project) { create(:project, namespace: maintainer.namespace) }
let_it_be(:project) { create(:project, group: create(:group)) }
let_it_be(:access_levels) { [Gitlab::Access::DEVELOPER, Gitlab::Access::MAINTAINER] }
subject(:members_with_access_levels) { project.team.members_with_access_levels(access_levels) }

View File

@ -3717,7 +3717,7 @@ RSpec.describe User do
context 'with min_access_level' do
let!(:user) { create(:user) }
let!(:project) { create(:project, :private, namespace: user.namespace) }
let!(:project) { create(:project, :private, group: create(:group)) }
before do
project.add_developer(user)

View File

@ -675,13 +675,30 @@ RSpec.describe API::Members do
end
context 'adding owner to project' do
it 'returns 403' do
expect do
post api("/projects/#{project.id}/members", maintainer),
params: { user_id: stranger.id, access_level: Member::OWNER }
context 'when personal_project_owner_with_owner_access feature flag is enabled' do
it 'returns created status' do
expect do
post api("/projects/#{project.id}/members", maintainer),
params: { user_id: stranger.id, access_level: Member::OWNER }
expect(response).to have_gitlab_http_status(:bad_request)
end.not_to change { project.members.count }
expect(response).to have_gitlab_http_status(:created)
end.to change { project.members.count }.by(1)
end
end
context 'when personal_project_owner_with_owner_access feature flag is disabled' do
before do
stub_feature_flags(personal_project_owner_with_owner_access: false)
end
it 'returns created status' do
expect do
post api("/projects/#{project.id}/members", maintainer),
params: { user_id: stranger.id, access_level: Member::OWNER }
expect(response).to have_gitlab_http_status(:bad_request)
end.not_to change { project.members.count }
end
end
end

View File

@ -40,7 +40,7 @@ RSpec.describe AuthorizedProjectUpdate::FindRecordsDueForRefreshService do
it 'is called' do
ProjectAuthorization.delete_all
expect(callback).to receive(:call).with(project.id, Gitlab::Access::MAINTAINER).once
expect(callback).to receive(:call).with(project.id, Gitlab::Access::OWNER).once
service.execute
end
@ -60,20 +60,20 @@ RSpec.describe AuthorizedProjectUpdate::FindRecordsDueForRefreshService do
to_be_removed = [project2.id]
to_be_added = [
{ user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
{ user_id: user.id, project_id: project.id, access_level: Gitlab::Access::OWNER }
]
expect(service.execute).to eq([to_be_removed, to_be_added])
end
it 'finds duplicate entries that has to be removed' do
[Gitlab::Access::MAINTAINER, Gitlab::Access::REPORTER].each do |access_level|
[Gitlab::Access::OWNER, Gitlab::Access::REPORTER].each do |access_level|
user.project_authorizations.create!(project: project, access_level: access_level)
end
to_be_removed = [project.id]
to_be_added = [
{ user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
{ user_id: user.id, project_id: project.id, access_level: Gitlab::Access::OWNER }
]
expect(service.execute).to eq([to_be_removed, to_be_added])
@ -85,7 +85,7 @@ RSpec.describe AuthorizedProjectUpdate::FindRecordsDueForRefreshService do
to_be_removed = [project.id]
to_be_added = [
{ user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
{ user_id: user.id, project_id: project.id, access_level: Gitlab::Access::OWNER }
]
expect(service.execute).to eq([to_be_removed, to_be_added])
@ -143,16 +143,16 @@ RSpec.describe AuthorizedProjectUpdate::FindRecordsDueForRefreshService do
end
it 'sets the keys to the project IDs' do
expect(hash.keys).to eq([project.id])
expect(hash.keys).to match_array([project.id])
end
it 'sets the values to the access levels' do
expect(hash.values).to eq([Gitlab::Access::MAINTAINER])
expect(hash.values).to match_array([Gitlab::Access::OWNER])
end
context 'personal projects' do
it 'includes the project with the right access level' do
expect(hash[project.id]).to eq(Gitlab::Access::MAINTAINER)
expect(hash[project.id]).to eq(Gitlab::Access::OWNER)
end
end
@ -242,7 +242,7 @@ RSpec.describe AuthorizedProjectUpdate::FindRecordsDueForRefreshService do
value = hash.values[0]
expect(value.project_id).to eq(project.id)
expect(value.access_level).to eq(Gitlab::Access::MAINTAINER)
expect(value.access_level).to eq(Gitlab::Access::OWNER)
end
end
@ -267,7 +267,7 @@ RSpec.describe AuthorizedProjectUpdate::FindRecordsDueForRefreshService do
end
it 'includes the access level for every row' do
expect(row.access_level).to eq(Gitlab::Access::MAINTAINER)
expect(row.access_level).to eq(Gitlab::Access::OWNER)
end
end
end
@ -283,7 +283,7 @@ RSpec.describe AuthorizedProjectUpdate::FindRecordsDueForRefreshService do
rows = service.fresh_authorizations.to_a
expect(rows.length).to eq(1)
expect(rows.first.access_level).to eq(Gitlab::Access::MAINTAINER)
expect(rows.first.access_level).to eq(Gitlab::Access::OWNER)
end
context 'every returned row' do
@ -294,7 +294,7 @@ RSpec.describe AuthorizedProjectUpdate::FindRecordsDueForRefreshService do
end
it 'includes the access level' do
expect(row.access_level).to eq(Gitlab::Access::MAINTAINER)
expect(row.access_level).to eq(Gitlab::Access::OWNER)
end
end
end

View File

@ -9,8 +9,8 @@ RSpec.describe Members::Projects::CreatorService do
end
describe '.access_levels' do
it 'returns Gitlab::Access.sym_options' do
expect(described_class.access_levels).to eq(Gitlab::Access.sym_options)
it 'returns Gitlab::Access.sym_options_with_owner' do
expect(described_class.access_levels).to eq(Gitlab::Access.sym_options_with_owner)
end
end
end

View File

@ -3312,7 +3312,7 @@ RSpec.describe NotificationService, :mailer do
describe "##{sym}" do
subject(:notify!) { notification.send(sym, domain) }
it 'emails current watching maintainers' do
it 'emails current watching maintainers and owners' do
expect(Notify).to receive(:"#{sym}_email").at_least(:once).and_call_original
notify!
@ -3410,7 +3410,7 @@ RSpec.describe NotificationService, :mailer do
reset_delivered_emails!
end
it 'emails current watching maintainers' do
it 'emails current watching maintainers and owners' do
notification.remote_mirror_update_failed(remote_mirror)
should_only_email(u_maintainer1, u_maintainer2, u_owner)

View File

@ -116,14 +116,34 @@ RSpec.describe Projects::CreateService, '#execute' do
end
context 'user namespace' do
it 'creates a project in user namespace' do
project = create_project(user, opts)
context 'when personal_project_owner_with_owner_access feature flag is enabled' do
it 'creates a project in user namespace' do
project = create_project(user, opts)
expect(project).to be_valid
expect(project.first_owner).to eq(user)
expect(project.team.maintainers).to include(user)
expect(project.namespace).to eq(user.namespace)
expect(project.project_namespace).to be_in_sync_with_project(project)
expect(project).to be_valid
expect(project.first_owner).to eq(user)
expect(project.team.maintainers).not_to include(user)
expect(project.team.owners).to contain_exactly(user)
expect(project.namespace).to eq(user.namespace)
expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
context 'when personal_project_owner_with_owner_access feature flag is disabled' do
before do
stub_feature_flags(personal_project_owner_with_owner_access: false)
end
it 'creates a project in user namespace' do
project = create_project(user, opts)
expect(project).to be_valid
expect(project.first_owner).to eq(user)
expect(project.team.maintainers).to contain_exactly(user)
expect(project.team.owners).to contain_exactly(user)
expect(project.namespace).to eq(user.namespace)
expect(project.project_namespace).to be_in_sync_with_project(project)
end
end
end
@ -162,7 +182,7 @@ RSpec.describe Projects::CreateService, '#execute' do
expect(project).to be_persisted
expect(project.owner).to eq(user)
expect(project.first_owner).to eq(user)
expect(project.team.maintainers).to contain_exactly(user)
expect(project.team.owners).to contain_exactly(user)
expect(project.namespace).to eq(user.namespace)
expect(project.project_namespace).to be_in_sync_with_project(project)
end

View File

@ -52,7 +52,7 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
it 'is called' do
ProjectAuthorization.delete_all
expect(callback).to receive(:call).with(project.id, Gitlab::Access::MAINTAINER).once
expect(callback).to receive(:call).with(project.id, Gitlab::Access::OWNER).once
service.execute
end
@ -73,7 +73,7 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
to_be_removed = [project_authorization.project_id]
to_be_added = [
{ user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
{ user_id: user.id, project_id: project.id, access_level: Gitlab::Access::OWNER }
]
expect(service).to receive(:update_authorizations)
@ -83,14 +83,14 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
end
it 'removes duplicate entries' do
[Gitlab::Access::MAINTAINER, Gitlab::Access::REPORTER].each do |access_level|
[Gitlab::Access::OWNER, Gitlab::Access::REPORTER].each do |access_level|
user.project_authorizations.create!(project: project, access_level: access_level)
end
to_be_removed = [project.id]
to_be_added = [
{ user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
{ user_id: user.id, project_id: project.id, access_level: Gitlab::Access::OWNER }
]
expect(service).to(
receive(:update_authorizations)
@ -103,7 +103,7 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
project_authorization = ProjectAuthorization.where(
project_id: project.id,
user_id: user.id,
access_level: Gitlab::Access::MAINTAINER)
access_level: Gitlab::Access::OWNER)
expect(project_authorization).to exist
end
@ -116,7 +116,7 @@ RSpec.describe Users::RefreshAuthorizedProjectsService do
to_be_removed = [project_authorization.project_id]
to_be_added = [
{ user_id: user.id, project_id: project.id, access_level: Gitlab::Access::MAINTAINER }
{ user_id: user.id, project_id: project.id, access_level: Gitlab::Access::OWNER }
]
expect(service).to receive(:update_authorizations)

View File

@ -1436,15 +1436,15 @@
resolved "https://registry.yarnpkg.com/@popperjs/core/-/core-2.10.2.tgz#0798c03351f0dea1a5a4cabddf26a55a7cbee590"
integrity sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==
"@rails/actioncable@6.1.4-1":
version "6.1.4-1"
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.1.4-1.tgz#69982e7f352d732f71fda0cc01b7ba8269c9945b"
integrity sha512-b6sLoMop3gX22Wm2P5LPpKcZGwsf1ZoAGS+g1HrTrdlsZ/ENOKIBiSNnHOJajHwcYlF0TefBs7e7jIYZHVYihQ==
"@rails/actioncable@6.1.4-6":
version "6.1.4-6"
resolved "https://registry.yarnpkg.com/@rails/actioncable/-/actioncable-6.1.4-6.tgz#22dd0f60e634f237f2a19d031f4e7afa26a924b4"
integrity sha512-cGwo5AWlEg6Q5JeUl2r8cmgaSlJtgR9BOOGF7Yb1PyKOinuWod6PW6UeQLgXf+n2MNiWz+yqldb1m3+Aun/2lg==
"@rails/ujs@6.1.4-1":
version "6.1.4-1"
resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.1.4-1.tgz#37507fe288a1c7c3a593602aa4dea42e5cb5797f"
integrity sha512-Fewm2wHk1n6Kf4E86dzzHDJOFg4EWcSHH3FsMEGs59bTdmf7099mjkOssOQtBqju4R39iaAOQNui7r8P+Q5Dgg==
"@rails/ujs@6.1.4-6":
version "6.1.4-6"
resolved "https://registry.yarnpkg.com/@rails/ujs/-/ujs-6.1.4-6.tgz#244520a1580b5791cebc81471978bc6b3c8966c0"
integrity sha512-j2ejw0ShVHiDWtq1Yv1PGX/GFCDiXX+5YiUY2Z17eeMJhQkxXeg3maQZkkT5OT/YBOI+jiWqtp03GM1Hdp/arA==
"@sentry/browser@5.30.0":
version "5.30.0"