Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2020-12-16 21:09:57 +00:00
parent d755061465
commit c47247f7cd
63 changed files with 438 additions and 65 deletions

View File

@ -138,6 +138,7 @@ export default {
snippetsAccessLevel: featureAccessLevel.EVERYONE,
pagesAccessLevel: featureAccessLevel.EVERYONE,
metricsDashboardAccessLevel: featureAccessLevel.PROJECT_MEMBERS,
analyticsAccessLevel: featureAccessLevel.EVERYONE,
requirementsAccessLevel: featureAccessLevel.EVERYONE,
containerRegistryEnabled: true,
lfsEnabled: true,
@ -241,6 +242,10 @@ export default {
featureAccessLevel.PROJECT_MEMBERS,
this.metricsDashboardAccessLevel,
);
this.analyticsAccessLevel = Math.min(
featureAccessLevel.PROJECT_MEMBERS,
this.analyticsAccessLevel,
);
this.requirementsAccessLevel = Math.min(
featureAccessLevel.PROJECT_MEMBERS,
this.requirementsAccessLevel,
@ -266,6 +271,8 @@ export default {
this.snippetsAccessLevel = featureAccessLevel.EVERYONE;
if (this.pagesAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.pagesAccessLevel = featureAccessLevel.EVERYONE;
if (this.analyticsAccessLevel > featureAccessLevel.NOT_ENABLED)
this.analyticsAccessLevel = featureAccessLevel.EVERYONE;
if (this.metricsDashboardAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
this.metricsDashboardAccessLevel = featureAccessLevel.EVERYONE;
if (this.requirementsAccessLevel === featureAccessLevel.PROJECT_MEMBERS)
@ -494,6 +501,17 @@ export default {
/>
</project-setting-row>
</div>
<project-setting-row
ref="analytics-settings"
:label="s__('ProjectSettings|Analytics')"
:help-text="s__('ProjectSettings|View project analytics')"
>
<project-feature-setting
v-model="analyticsAccessLevel"
:options="featureAccessLevelOptions"
name="project[project_feature_attributes][analytics_access_level]"
/>
</project-setting-row>
<project-setting-row
v-if="requirementsAvailable"
ref="requirements-settings"

View File

@ -49,6 +49,7 @@ function UsersSelect(currentUser, els, options = {}) {
options.todoStateFilter = $dropdown.data('todoStateFilter');
options.iid = $dropdown.data('iid');
options.issuableType = $dropdown.data('issuableType');
options.targetBranch = $dropdown.data('targetBranch');
const showNullUser = $dropdown.data('nullUser');
const defaultNullUser = $dropdown.data('nullUserDefault');
const showMenuAbove = $dropdown.data('showMenuAbove');
@ -582,7 +583,14 @@ function UsersSelect(currentUser, els, options = {}) {
img = `<img src='${avatar}' class='avatar avatar-inline m-0' width='32' />`;
}
return userSelect.renderRow(options.issuableType, user, selected, username, img);
return userSelect.renderRow(
options.issuableType,
user,
selected,
username,
img,
elsClassName,
);
},
});
});
@ -746,8 +754,17 @@ UsersSelect.prototype.users = function(query, options, callback) {
...getAjaxUsersSelectParams(options, AJAX_USERS_SELECT_PARAMS_MAP),
};
if (options.issuableType === 'merge_request') {
const isMergeRequest = options.issuableType === 'merge_request';
const isEditMergeRequest = !options.issuableType && (options.iid && options.targetBranch);
const isNewMergeRequest = !options.issuableType && (!options.iid && options.targetBranch);
if (isMergeRequest || isEditMergeRequest || isNewMergeRequest) {
params.merge_request_iid = options.iid || null;
params.approval_rules = true;
}
if (isNewMergeRequest) {
params.target_branch = options.targetBranch || null;
}
return axios.get(url, { params }).then(({ data }) => {
@ -762,7 +779,14 @@ UsersSelect.prototype.buildUrl = function(url) {
return url;
};
UsersSelect.prototype.renderRow = function(issuableType, user, selected, username, img) {
UsersSelect.prototype.renderRow = function(
issuableType,
user,
selected,
username,
img,
elsClassName,
) {
const tooltip = issuableType === 'merge_request' && !user.can_merge ? __('Cannot merge') : '';
const tooltipClass = tooltip ? `has-tooltip` : '';
const selectedClass = selected === true ? 'is-active' : '';
@ -776,10 +800,15 @@ UsersSelect.prototype.renderRow = function(issuableType, user, selected, usernam
<a href="#" class="dropdown-menu-user-link d-flex align-items-center ${linkClasses}" ${tooltipAttributes}>
${this.renderRowAvatar(issuableType, user, img)}
<span class="d-flex flex-column overflow-hidden">
<strong class="dropdown-menu-user-full-name">
<strong class="dropdown-menu-user-full-name gl-font-weight-bold">
${escape(user.name)}
</strong>
${username ? `<span class="dropdown-menu-user-username">${username}</span>` : ''}
${
username
? `<span class="dropdown-menu-user-username gl-text-gray-400">${username}</span>`
: ''
}
${this.renderApprovalRules(elsClassName, user.applicable_approval_rules)}
</span>
</a>
</li>
@ -802,4 +831,22 @@ UsersSelect.prototype.renderRowAvatar = function(issuableType, user, img) {
</span>`;
};
UsersSelect.prototype.renderApprovalRules = function(elsClassName, approvalRules = []) {
if (!gon.features?.reviewerApprovalRules || !elsClassName?.includes('reviewer')) {
return '';
}
const count = approvalRules.length;
const [rule] = approvalRules;
const countText = sprintf(__('(+%{count}&nbsp;rules)'), { count });
const renderApprovalRulesCount = count > 1 ? `<span class="ml-1">${countText}</span>` : '';
return count
? `<div class="gl-display-flex gl-font-sm">
<span class="gl-text-truncate" title="${rule.name}">${rule.name}</span>
${renderApprovalRulesCount}
</div>`
: '';
};
export default UsersSelect;

View File

@ -14,6 +14,7 @@ class Projects::MergeRequests::CreationsController < Projects::MergeRequests::Ap
before_action do
push_frontend_feature_flag(:merge_request_reviewers, @project, default_enabled: true)
push_frontend_feature_flag(:mr_collapsed_approval_rules, @project)
push_frontend_feature_flag(:reviewer_approval_rules, @project)
end
def new

View File

@ -53,6 +53,7 @@ class Projects::MergeRequestsController < Projects::MergeRequests::ApplicationCo
push_frontend_feature_flag(:vue_issuable_sidebar, @project.group)
push_frontend_feature_flag(:merge_request_reviewers, @project, default_enabled: true)
push_frontend_feature_flag(:mr_collapsed_approval_rules, @project)
push_frontend_feature_flag(:reviewer_approval_rules, @project)
end
around_action :allow_gitaly_ref_name_caching, only: [:index, :show, :discussions]

View File

@ -387,6 +387,7 @@ class ProjectsController < Projects::ApplicationController
wiki_access_level
pages_access_level
metrics_dashboard_access_level
analytics_access_level
operations_access_level
]
end

View File

@ -55,7 +55,7 @@ module FormHelper
dropdown_data
end
def reviewers_dropdown_options(issuable_type)
def reviewers_dropdown_options(issuable_type, iid = nil, target_branch = nil)
dropdown_data = {
toggle_class: 'js-reviewer-search js-multiselect js-save-user-data',
title: 'Request review from',
@ -78,6 +78,14 @@ module FormHelper
}
}
if iid
dropdown_data[:data][:iid] = iid
end
if target_branch
dropdown_data[:data][:target_branch] = target_branch
end
if merge_request_supports_multiple_reviewers?
dropdown_data = multiple_reviewers_dropdown_options(dropdown_data)
end

View File

@ -463,7 +463,8 @@ module ProjectsHelper
issues: :read_issue,
project_members: :read_project_member,
wiki: :read_wiki,
feature_flags: :read_feature_flag
feature_flags: :read_feature_flag,
analytics: :read_analytics
}
end
@ -625,6 +626,7 @@ module ProjectsHelper
wikiAccessLevel: feature.wiki_access_level,
snippetsAccessLevel: feature.snippets_access_level,
pagesAccessLevel: feature.pages_access_level,
analyticsAccessLevel: feature.analytics_access_level,
containerRegistryEnabled: !!project.container_registry_enabled,
lfsEnabled: !!project.lfs_enabled,
emailsDisabled: project.emails_disabled?,

View File

@ -70,6 +70,10 @@ module ProjectFeaturesCompatibility
write_feature_attribute_string(:metrics_dashboard_access_level, value)
end
def analytics_access_level=(value)
write_feature_attribute_string(:analytics_access_level, value)
end
def operations_access_level=(value)
write_feature_attribute_string(:operations_access_level, value)
end

View File

@ -385,10 +385,10 @@ class Project < ApplicationRecord
delegate :feature_available?, :builds_enabled?, :wiki_enabled?,
:merge_requests_enabled?, :forking_enabled?, :issues_enabled?,
:pages_enabled?, :snippets_enabled?, :public_pages?, :private_pages?,
:pages_enabled?, :analytics_enabled?, :snippets_enabled?, :public_pages?, :private_pages?,
:merge_requests_access_level, :forking_access_level, :issues_access_level,
:wiki_access_level, :snippets_access_level, :builds_access_level,
:repository_access_level, :pages_access_level, :metrics_dashboard_access_level,
:repository_access_level, :pages_access_level, :metrics_dashboard_access_level, :analytics_access_level,
:operations_enabled?, :operations_access_level, to: :project_feature, allow_nil: true
delegate :show_default_award_emojis, :show_default_award_emojis=,
:show_default_award_emojis?,

View File

@ -3,7 +3,7 @@
class ProjectFeature < ApplicationRecord
include Featurable
FEATURES = %i(issues forking merge_requests wiki snippets builds repository pages metrics_dashboard operations).freeze
FEATURES = %i(issues forking merge_requests wiki snippets builds repository pages metrics_dashboard analytics operations).freeze
set_available_features(FEATURES)
@ -44,6 +44,7 @@ class ProjectFeature < ApplicationRecord
default_value_for :snippets_access_level, value: ENABLED, allows_nil: false
default_value_for :wiki_access_level, value: ENABLED, allows_nil: false
default_value_for :repository_access_level, value: ENABLED, allows_nil: false
default_value_for :analytics_access_level, value: ENABLED, allows_nil: false
default_value_for :metrics_dashboard_access_level, value: PRIVATE, allows_nil: false
default_value_for :operations_access_level, value: ENABLED, allows_nil: false

View File

@ -73,8 +73,6 @@ class ProjectStatistics < ApplicationRecord
end
def update_uploads_size
return uploads_size unless Feature.enabled?(:count_uploads_size_in_storage_stats, project)
self.uploads_size = project.uploads.sum(:size)
end

View File

@ -44,6 +44,7 @@ class Snippet < ApplicationRecord
has_many :notes, as: :noteable, dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent
has_many :user_mentions, class_name: "SnippetUserMention", dependent: :delete_all # rubocop:disable Cop/ActiveRecordDependent
has_one :snippet_repository, inverse_of: :snippet
has_many :repository_storage_moves, class_name: 'SnippetRepositoryStorageMove', inverse_of: :container
# We need to add the `dependent` in order to call the after_destroy callback
has_one :statistics, class_name: 'SnippetStatistics', dependent: :destroy # rubocop:disable Cop/ActiveRecordDependent

View File

@ -0,0 +1,24 @@
# frozen_string_literal: true
# SnippetRepositoryStorageMove are details of repository storage moves for a
# snippet. For example, moving a snippet to another gitaly node to help
# balance storage capacity.
class SnippetRepositoryStorageMove < ApplicationRecord
extend ::Gitlab::Utils::Override
include RepositoryStorageMovable
belongs_to :container, class_name: 'Snippet', inverse_of: :repository_storage_moves, foreign_key: :snippet_id
alias_attribute :snippet, :container
override :schedule_repository_storage_update_worker
def schedule_repository_storage_update_worker
# TODO https://gitlab.com/gitlab-org/gitlab/-/issues/218991
end
private
override :error_key
def error_key
:snippet
end
end

View File

@ -151,6 +151,7 @@ class ProjectPolicy < BasePolicy
builds
pages
metrics_dashboard
analytics
operations
]
@ -216,6 +217,7 @@ class ProjectPolicy < BasePolicy
enable :award_emoji
enable :read_pages_content
enable :read_release
enable :read_analytics
end
# These abilities are not allowed to admins that are not members of the project,
@ -442,6 +444,10 @@ class ProjectPolicy < BasePolicy
prevent(*create_read_update_admin_destroy(:snippet))
end
rule { analytics_disabled }.policy do
prevent(:read_analytics)
end
rule { wiki_disabled }.policy do
prevent(*create_read_update_admin_destroy(:wiki))
prevent(:download_wiki_code)
@ -512,6 +518,7 @@ class ProjectPolicy < BasePolicy
enable :download_wiki_code
enable :read_cycle_analytics
enable :read_pages_content
enable :read_analytics
# NOTE: may be overridden by IssuePolicy
enable :read_issue

View File

@ -4,7 +4,7 @@
- if navbar_links.any?
= nav_link(path: all_paths) do
= link_to analytics_link.link, { data: { qa_selector: 'analytics_anchor' } } do
= link_to analytics_link.link, {class: 'shortcuts-analytics', data: { qa_selector: 'analytics_anchor' } } do
.nav-icon-container
= sprite_icon('chart')
%span.nav-item-name{ data: { qa_selector: 'analytics_link' } }

View File

@ -324,7 +324,8 @@
= render_if_exists 'layouts/nav/sidebar/project_packages_link'
= render 'layouts/nav/sidebar/analytics_links', links: project_analytics_navbar_links(@project, current_user)
- if project_nav_tab? :analytics
= render 'layouts/nav/sidebar/analytics_links', links: project_analytics_navbar_links(@project, current_user)
- if project_nav_tab?(:confluence)
- confluence_url = project_wikis_confluence_path(@project)

View File

@ -7,6 +7,6 @@
- if issuable.reviewers.empty?
= hidden_field_tag "#{issuable.to_ability_name}[reviewer_ids][]", 0, id: nil, data: { meta: '' }
= dropdown_tag(users_dropdown_label(issuable.reviewers), options: reviewers_dropdown_options(issuable.to_ability_name))
= dropdown_tag(users_dropdown_label(issuable.reviewers), options: reviewers_dropdown_options(issuable.to_ability_name, issuable.iid, issuable.target_branch))
- if Feature.enabled?(:mr_collapsed_approval_rules, @project)
= render_if_exists 'shared/issuable/approver_suggestion', issuable: issuable, presenter: presenter

View File

@ -0,0 +1,5 @@
---
title: Add toggle to remove Analytics left nav item
merge_request: 46011
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Removed count_uploads_size_in_storage_stats feature flag
merge_request: 49998
author:
type: other

View File

@ -0,0 +1,8 @@
---
name: reviewer_approval_rules
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46738
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/293742
milestone: '13.7'
type: development
group: group::code review
default_enabled: false

View File

@ -0,0 +1,8 @@
---
name: security_dast_site_profiles_additional_fields
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/46848
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/292897
milestone: '13.7'
type: development
group: group::dynamic analysis
default_enabled: false

View File

@ -0,0 +1,23 @@
# frozen_string_literal: true
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class AddAnalyticsAccessLevelToProjectFeatures < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
# Set this constant to true if this migration requires downtime.
DOWNTIME = false
def up
with_lock_retries do
add_column :project_features, :analytics_access_level, :integer, default: 20, null: false
end
end
def down
with_lock_retries do
remove_column :project_features, :analytics_access_level, :integer
end
end
end

View File

@ -0,0 +1 @@
d9151c8cafe7a62be9904cb05cc2a6f6e28c2910e69744df1ddd4ad587c83335

View File

@ -15439,7 +15439,8 @@ CREATE TABLE project_features (
forking_access_level integer,
metrics_dashboard_access_level integer,
requirements_access_level integer DEFAULT 20 NOT NULL,
operations_access_level integer DEFAULT 20 NOT NULL
operations_access_level integer DEFAULT 20 NOT NULL,
analytics_access_level integer DEFAULT 20 NOT NULL
);
CREATE SEQUENCE project_features_id_seq

View File

@ -13,7 +13,7 @@ to deploy features in an early stage of development so that they can be
incrementally rolled out.
Before making them permanently available, features can be deployed behind
flags for a [number of reasons](../development/feature_flags/process.md#when-to-use-feature-flags), such as:
flags for a [number of reasons](../development/feature_flags/index.md#when-to-use-feature-flags), such as:
- To test the feature.
- To get feedback from users and customers while in an early stage of the development of the feature.

View File

@ -6,7 +6,7 @@ info: To determine the technical writer assigned to the Stage/Group associated w
# Getting started with GitLab GraphQL API
This guide demonstrates basic usage of GitLab's GraphQL API.
This guide demonstrates basic usage of the GitLab GraphQL API.
See the [GraphQL API style guide](../../development/api_graphql_styleguide.md) for implementation details
aimed at developers who wish to work on developing the API itself.
@ -69,7 +69,7 @@ In the GitLab GraphQL API, `id` refers to a
[Global ID](https://graphql.org/learn/global-object-identification/),
which is an object identifier in the format of `"gid://gitlab/Issue/123"`.
[GitLab's GraphQL Schema](reference/index.md) outlines which objects and fields are
[GitLab GraphQL Schema](reference/index.md) outlines which objects and fields are
available for clients to query and their corresponding data types.
Example: Get only the names of all the projects the currently logged in user can access (up to a limit, more on that later)
@ -289,7 +289,7 @@ More about introspection:
## Sorting
Some of GitLab's GraphQL endpoints allow you to specify how you'd like a collection of
Some of the GitLab GraphQL endpoints allow you to specify how you'd like a collection of
objects to be sorted. You can only sort by what the schema allows you to.
Example: Issues can be sorted by creation date:
@ -314,7 +314,7 @@ Pagination is a way of only asking for a subset of the records (say, the first 1
If we want more of them, we can make another request for the next 10 from the server
(in the form of something like "please give me the next 10 records").
By default, GitLab's GraphQL API returns only the first 100 records of any collection.
By default, the GitLab GraphQL API returns only the first 100 records of any collection.
This can be changed by using `first` or `last` arguments. Both arguments take a value,
so `first: 10` returns the first 10 records, and `last: 10` the last 10 records.

View File

@ -16,7 +16,7 @@ For those new to the GitLab GraphQL API, see
### Quick Reference
- GitLab's GraphQL API endpoint is located at `/api/graphql`.
- The GitLab GraphQL API endpoint is located at `/api/graphql`.
- Get an [introduction to GraphQL from graphql.org](https://graphql.org/).
- GitLab supports a wide range of resources, listed in the [GraphQL API Reference](reference/index.md).
@ -115,9 +115,9 @@ library GitLab uses on the backend.
## Reference
GitLab's GraphQL reference [is available](reference/index.md).
The GitLab GraphQL reference [is available](reference/index.md).
It is automatically generated from GitLab's GraphQL schema and embedded in a Markdown file.
It is automatically generated from the GitLab GraphQL schema and embedded in a Markdown file.
Machine-readable versions are also available:

View File

@ -26,7 +26,7 @@ in [Removed Items](../removed_items.md).
## Object types
Object types represent the resources that GitLab's GraphQL API can return.
Object types represent the resources that the GitLab GraphQL API can return.
They contain _fields_. Each field has its own type, which will either be one of the
basic GraphQL [scalar types](https://graphql.org/learn/schema/#scalar-types)
(e.g.: `String` or `Boolean`) or other object types.

View File

@ -1045,6 +1045,7 @@ POST /projects
| Attribute | Type | Required | Description |
|-------------------------------------------------------------|---------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | no | One of `disabled`, `private` or `enabled` |
| `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). |
@ -1118,6 +1119,7 @@ POST /projects/user/:user_id
| Attribute | Type | Required | Description |
|-------------------------------------------------------------|---------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | no | One of `disabled`, `private` or `enabled` |
| `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge requests by default. |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual` or `timed_incremental`). |
@ -1190,6 +1192,7 @@ PUT /projects/:id
| Attribute | Type | Required | Description |
|-------------------------------------------------------------|----------------|------------------------|-------------|
| `allow_merge_on_skipped_pipeline` | boolean | **{dotted-circle}** No | Set whether or not merge requests can be merged with skipped jobs. |
| `analytics_access_level` | string | no | One of `disabled`, `private` or `enabled` |
| `approvals_before_merge` **(STARTER)** | integer | **{dotted-circle}** No | How many approvers should approve merge request by default. |
| `auto_cancel_pending_pipelines` | string | **{dotted-circle}** No | Auto-cancel pending pipelines. This isn't a boolean, but enabled/disabled. |
| `auto_devops_deploy_strategy` | string | **{dotted-circle}** No | Auto Deploy strategy (`continuous`, `manual`, or `timed_incremental`). |
@ -2374,6 +2377,7 @@ Example response:
"repository_access_level": "enabled",
"merge_requests_access_level": "enabled",
"forking_access_level": "enabled",
"analytics_access_level": "enabled",
"wiki_access_level": "enabled",
"builds_access_level": "enabled",
"snippets_access_level": "enabled",

View File

@ -53,7 +53,6 @@ problems, such as outages.
Please also read the [development guide for feature flags](development.md).
### Including a feature behind feature flag in the final release
In order to build a final release and present the feature for self-managed

View File

@ -88,6 +88,9 @@ in multiple ways:
## Features
NOTE:
Depending on your target platform, some features might not be available to you.
Comprised of a set of [stages](stages.md), Auto DevOps brings these best practices to your
project in a simple and automatic way:

View File

@ -11,6 +11,9 @@ Read them carefully to understand how each one works.
## Auto Build
NOTE:
Auto Build is not supported if Docker in Docker is not available for your GitLab Runners, like in OpenShift clusters. GitLab's OpenShift support is tracked [in a dedicated epic](https://gitlab.com/groups/gitlab-org/-/epics/2068).
Auto Build creates a build of the application using an existing `Dockerfile` or
Heroku buildpacks. The resulting Docker image is pushed to the
[Container Registry](../../user/packages/container_registry/index.md), and tagged

View File

@ -183,7 +183,7 @@ The following variables are used for configuring specific analyzers (used for a
| `PIP_REQUIREMENTS_FILE` | `gemnasium-python` | | Pip requirements file to be scanned. |
| `DS_PIP_VERSION` | `gemnasium-python` | | Force the install of a specific pip version (example: `"19.3"`), otherwise the pip installed in the Docker image is used. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12811) in GitLab 12.7) |
| `DS_PIP_DEPENDENCY_PATH` | `gemnasium-python` | | Path to load Python pip dependencies from. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12412) in GitLab 12.2) |
| `DS_PYTHON_VERSION` | `retire.js` | | Version of Python. If set to 2, dependencies are installed using Python 2.7 instead of Python 3.6. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12296) in GitLab 12.1)|
| `DS_PYTHON_VERSION` | `retire.js` | | Version of Python. If set to 2, dependencies are installed using Python 2.7 instead of Python 3.6. ([Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/12296) in GitLab 12.1, [removed](https://www.python.org/doc/sunset-python-2/) in GitLab 13.7)|
| `DS_JAVA_VERSION` | `gemnasium-maven` | `11` | Version of Java. Available versions: `8`, `11`, `13`, `14`. Maven and Gradle use the Java version specified by this value. |
| `MAVEN_CLI_OPTS` | `gemnasium-maven` | `"-DskipTests --batch-mode"` | List of command line arguments that are passed to `maven` by the analyzer. See an example for [using private repositories](../index.md#using-private-maven-repos). |
| `GRADLE_CLI_OPTS` | `gemnasium-maven` | | List of command line arguments that are passed to `gradle` by the analyzer. |
@ -520,3 +520,8 @@ uses the [`rules:exists`](../../../ci/yaml/README.md#rulesexists)
syntax. This directive is limited to 10000 checks and always returns `true` after reaching this
number. Because of this, and depending on the number of files in your repository, a dependency
scanning job might be triggered even if the scanner doesn't support your project.
### Issues building projects with npm or yarn packages relying on Python 2
Python 2 was removed (see: [Python 2 sunsetting](https://www.python.org/doc/sunset-python-2/)) from the `retire.js` analyzer in GitLab 13.7 (analyzer version 2.10.1). Projects using packages
with a dependency on this version of Python should use `retire.js` version 2.10.0 or lower (for example, `registry.gitlab.com/gitlab-org/security-products/analyzers/retire.js:2.10.0`).

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 42 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

View File

@ -211,6 +211,88 @@ To remove a member from a group:
1. (Optional) Select the **Also unassign this user from related issues and merge requests** checkbox.
1. Click **Remove member**.
## Filter and sort members in a group
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/21727) in GitLab 12.6.
> - [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/228675) in GitLab 13.7.
> - Improvements are [deployed behind a feature flag](../feature_flags.md), enabled by default.
> - Improvements are enabled on GitLab.com.
> - Improvements are recommended for production use.
> - For GitLab self-managed instances, GitLab administrators can opt to [disable improvements](#enable-or-disable-improvements-to-the-ability-to-filter-and-sort-group-members). **(CORE ONLY)**
The following sections illustrate how you can filter and sort members in a group. To view these options,
navigate to your desired group, go to **Members**, and include the noted search terms.
### Membership filter
By default, inherited and direct members are displayed. The [membership](subgroups/index.md#membership) filter can be used to display only inherited or only direct members.
#### Only display inherited members
Include `Membership` `=` `Inherited` in the search text box.
![Group members filter inherited](img/group_members_filter_inherited_13_7.png)
#### Only display direct members
Include `Membership` `=` `Direct` in the search text box.
![Group members filter direct](img/group_members_filter_direct_13_7.png)
### 2FA filter
[Owner](../permissions.md#group-members-permissions) permissions required.
By default, members with 2FA enabled and disabled are displayed. The 2FA filter can be used to display only members with 2FA enabled or only members with 2FA disabled.
#### Only display members with 2FA enabled
Include `2FA` `=` `Enabled` in the search text box.
![Group members filter 2FA enabled](img/group_members_filter_2fa_enabled_13_7.png)
#### Only display members with 2FA disabled
Include `2FA` `=` `Disabled` in the search text box.
![Group members filter 2FA disabled](img/group_members_filter_2fa_disabled_13_7.png)
### Search
You can search for members by name, username, or email.
![Group members search](img/group_members_search_13_7.png)
### Sort
You can sort members by **Account**, **Access granted**, **Max role**, or **Last sign-in** in ascending or descending order.
![Group members sort](img/group_members_sort_13_7.png)
### Enable or disable improvements to the ability to filter and sort group members **(CORE ONLY)**
Group member filtering and sorting improvements are deployed behind a feature flag that is **enabled by default**.
[GitLab administrators with access to the GitLab Rails console](../../administration/feature_flags.md)
can opt to disable the improvements.
To disable them:
```ruby
# For the instance
Feature.disable(:group_members_filtered_search)
# For a single group
Feature.disable(:group_members_filtered_search, Group.find(<group id>))
```
To enable them:
```ruby
# For the instance
Feature.enable(:group_members_filtered_search)
# For a single group
Feature.enable(:group_members_filtered_search, Group.find(<group id>))
```
## Changing the default branch protection of a group
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/7583) in GitLab 12.9.

View File

@ -192,6 +192,8 @@ If the information you need isn't listed above you may wish to check our [troubl
## User access and management
> [Improved](https://gitlab.com/gitlab-org/gitlab/-/issues/268142) in GitLab 13.7.
Once Group SSO is configured and enabled, users can access the GitLab.com group through the identity provider's dashboard. If [SCIM](scim_setup.md) is configured, please see the [user access and linking setup section on the SCIM page](scim_setup.md#user-access-and-linking-setup).
When a user tries to sign in with Group SSO, GitLab attempts to find or create a user based on the following:

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 58 KiB

View File

@ -116,9 +116,9 @@ Follow the same process to create any subsequent groups.
## Membership
When you add a member to a subgroup, they inherit the membership and permission
level from the parent group(s). This model allows access to nested groups if you
have membership in one of its parents.
When you add a member to a group, that member is also added to all subgroups.
Permission level is inherited from the groups parent. This model allows access to
subgroups if you have membership in one of its parents.
Jobs for pipelines in subgroups can use [runners](../../../ci/runners/README.md) registered to the parent group(s).
This means secrets configured for the parent group are available to subgroup jobs.
@ -131,31 +131,23 @@ the **Members** page of the group the member was added.
You can tell if a member has inherited the permissions from a parent group by
looking at the group's **Members** page.
![Group members page](img/group_members.png)
![Group members page](img/group_members_13_7.png)
From the image above, we can deduce the following things:
- There are 5 members that have access to the group `four`.
- User0 is a Reporter and has inherited their permissions from group `one`
- User 0 is a Reporter and has inherited their permissions from group `one`
which is above the hierarchy of group `four`.
- User1 is a Developer and has inherited their permissions from group
- User 1 is a Developer and has inherited their permissions from group
`one/two` which is above the hierarchy of group `four`.
- User2 is a Developer and has inherited their permissions from group
- User 2 is a Developer and has inherited their permissions from group
`one/two/three` which is above the hierarchy of group `four`.
- For User3 there is no indication of a parent group, therefore they belong to
- For User 3 the **Source** column indicates **Direct member**, therefore they belong to
group `four`, the one we're inspecting.
- Administrator is the Owner and member of **all** subgroups and for that reason,
as with User3, there is no indication of an ancestor group.
as with User 3, the **Source** column indicates **Direct member**.
[From](https://gitlab.com/gitlab-org/gitlab/-/issues/21727) GitLab 12.6, you can filter
this list using dropdown on the right side:
![Group members filter](img/group_members_filter_v12_6.png)
- **Show only direct members** displays only Administrator and User3, since these are
the only users that belong to group `four`, which is the one we're inspecting.
- **Show only inherited members** displays User0, User1 and User2, no matter which group
above the hierarchy is the source of inherited permissions.
Members can be [filtered by inherited or direct membership](../index.md#membership-filter).
### Overriding the ancestor group membership
@ -169,9 +161,9 @@ Therefore, you cannot reduce a user's permissions in a subgroup with respect to
To override a user's membership of an ancestor group (the first group they were
added to), add the user to the new subgroup again with a higher set of permissions.
For example, if User0 was first added to group `group-1/group-1-1` with Developer
For example, if User 1 was first added to group `one/two` with Developer
permissions, then they inherit those permissions in every other subgroup
of `group-1/group-1-1`. To give them Maintainer access to `group-1/group-1-1/group1-1-1`,
of `one/two`. To give them Maintainer access to group `one/two/three/four`,
you would add them again in that group as Maintainer. Removing them from that group,
the permissions fall back to those of the ancestor group.

View File

@ -289,6 +289,7 @@ group.
| View Value Stream analytics | ✓ | ✓ | ✓ | ✓ | ✓ |
| View Billing **(FREE ONLY)** | | | | | ✓ (4) |
| View Usage Quotas **(FREE ONLY)** | | | | | ✓ (4) |
| Filter members by 2FA status | | | | | ✓ |
1. Groups can be set to [allow either Owners or Owners and
Maintainers to create subgroups](group/subgroups/index.md#creating-a-subgroup)

View File

@ -35,7 +35,7 @@ you can also view all the issues collectively at the group level.
See also [Always start a discussion with an issue](https://about.gitlab.com/blog/2016/03/03/start-with-an-issue/).
<i class="fa fa-youtube-play youtube" aria-hidden="true"></i>
To learn how the GitLab Strategic Marketing department uses GitLab issues with [labels](../labels.md) and
To learn how our Strategic Marketing department uses GitLab issues with [labels](../labels.md) and
[issue boards](../issue_board.md), see the video on
[Managing Commitments with Issues](https://www.youtube.com/watch?v=cuIHNintg1o&t=3).

View File

@ -68,6 +68,7 @@ Use the switches to enable or disable the following features:
| **Container Registry** | | Activates a [registry](../../packages/container_registry/) for your Docker images |
| **Git Large File Storage** | | Enables the use of [large files](../../../topics/git/lfs/index.md#git-large-file-storage-lfs) |
| **Packages** | | Supports configuration of a [package registry](../../../administration/packages/index.md#gitlab-package-registry-administration) functionality |
| **Analytics** | ✓ | Enables [analytics](../../analytics/) |
| **Wiki** | ✓ | Enables a separate system for [documentation](../wiki/) |
| **Snippets** | ✓ | Enables [sharing of code and text](../../snippets.md) |
| **Pages** | ✓ | Allows you to [publish static websites](../pages/) |

View File

@ -68,6 +68,7 @@ module API
expose(:snippets_access_level) { |project, options| project.project_feature.string_access_level(:snippets) }
expose(:pages_access_level) { |project, options| project.project_feature.string_access_level(:pages) }
expose(:operations_access_level) { |project, options| project.project_feature.string_access_level(:operations) }
expose(:analytics_access_level) { |project, options| project.project_feature.string_access_level(:analytics) }
expose :emails_disabled
expose :shared_runners_enabled

View File

@ -33,6 +33,7 @@ module API
optional :snippets_access_level, type: String, values: %w(disabled private enabled), desc: 'Snippets access level. One of `disabled`, `private` or `enabled`'
optional :pages_access_level, type: String, values: %w(disabled private enabled public), desc: 'Pages access level. One of `disabled`, `private`, `enabled` or `public`'
optional :operations_access_level, type: String, values: %w(disabled private enabled), desc: 'Operations access level. One of `disabled`, `private` or `enabled`'
optional :analytics_access_level, type: String, values: %w(disabled private enabled), desc: 'Analytics access level. One of `disabled`, `private` or `enabled`'
optional :emails_disabled, type: Boolean, desc: 'Disable email notifications'
optional :show_default_award_emojis, type: Boolean, desc: 'Show default award emojis'

View File

@ -21,7 +21,7 @@
:plain
## Object types
Object types represent the resources that GitLab's GraphQL API can return.
Object types represent the resources that the GitLab GraphQL API can return.
They contain _fields_. Each field has its own type, which will either be one of the
basic GraphQL [scalar types](https://graphql.org/learn/schema/#scalar-types)
(e.g.: `String` or `Boolean`) or other object types.

View File

@ -962,6 +962,9 @@ msgstr ""
msgid "(%{value}) has already been taken"
msgstr ""
msgid "(+%{count}&nbsp;rules)"
msgstr ""
msgid "(No changes)"
msgstr ""
@ -8680,6 +8683,9 @@ msgstr ""
msgid "DastProfiles|Error Details"
msgstr ""
msgid "DastProfiles|Excluded URLs"
msgstr ""
msgid "DastProfiles|Hide debug messages"
msgstr ""
@ -8728,6 +8734,9 @@ msgstr ""
msgid "DastProfiles|Profile name"
msgstr ""
msgid "DastProfiles|Request headers"
msgstr ""
msgid "DastProfiles|Run the AJAX spider, in addition to the traditional spider, to crawl the target site."
msgstr ""
@ -21754,6 +21763,9 @@ msgstr ""
msgid "ProjectSettings|Allow users to request access"
msgstr ""
msgid "ProjectSettings|Analytics"
msgstr ""
msgid "ProjectSettings|Automatically resolve merge request diff discussions when they become outdated"
msgstr ""
@ -21997,6 +22009,9 @@ msgstr ""
msgid "ProjectSettings|View and edit files in this project. Non-project members will only have read access"
msgstr ""
msgid "ProjectSettings|View project analytics"
msgstr ""
msgid "ProjectSettings|When approved for merge, merge requests are queued and pipelines validate the combined results of the source and target branches before merge."
msgstr ""

View File

@ -0,0 +1,29 @@
# frozen_string_literal: true
FactoryBot.define do
factory :snippet_repository_storage_move, class: 'SnippetRepositoryStorageMove' do
container { association(:snippet) }
source_storage_name { 'default' }
trait :scheduled do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:scheduled].value }
end
trait :started do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:started].value }
end
trait :replicated do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:replicated].value }
end
trait :finished do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:finished].value }
end
trait :failed do
state { SnippetRepositoryStorageMove.state_machines[:state].states[:failed].value }
end
end
end

View File

@ -14,7 +14,7 @@ RSpec.describe 'Edit Project Settings' do
sign_in(member)
end
tools = { builds: "pipelines", issues: "issues", wiki: "wiki", snippets: "snippets", merge_requests: "merge_requests" }
tools = { builds: "pipelines", issues: "issues", wiki: "wiki", snippets: "snippets", merge_requests: "merge_requests", analytics: "analytics" }
tools.each do |tool_name, shortcut_name|
describe "feature #{tool_name}" do

View File

@ -21,6 +21,7 @@ const defaultProps = {
wikiAccessLevel: 20,
snippetsAccessLevel: 20,
pagesAccessLevel: 10,
analyticsAccessLevel: 20,
containerRegistryEnabled: true,
lfsEnabled: true,
emailsDisabled: false,
@ -79,6 +80,8 @@ describe('Settings Panel', () => {
const findRepositoryFeatureSetting = () =>
findRepositoryFeatureProjectRow().find(projectFeatureSetting);
const findAnalyticsRow = () => wrapper.find({ ref: 'analytics-settings' });
beforeEach(() => {
wrapper = mountComponent();
});
@ -557,4 +560,12 @@ describe('Settings Panel', () => {
});
});
});
describe('Analytics', () => {
it('should show the analytics toggle', async () => {
await wrapper.vm.$nextTick();
expect(findAnalyticsRow().exists()).toBe(true);
});
});
});

View File

@ -107,6 +107,7 @@ snippets:
- user_mentions
- snippet_repository
- statistics
- repository_storage_moves
releases:
- author
- project

View File

@ -578,6 +578,7 @@ ProjectFeature:
- pages_access_level
- metrics_dashboard_access_level
- requirements_access_level
- analytics_access_level
- operations_access_level
- created_at
- updated_at

View File

@ -3,11 +3,33 @@
require 'spec_helper'
RSpec.describe ProjectRepositoryStorageMove, type: :model do
it_behaves_like 'handles repository moves' do
let_it_be_with_refind(:container) { create(:project) }
let_it_be_with_refind(:project) { create(:project) }
it_behaves_like 'handles repository moves' do
let(:container) { project }
let(:repository_storage_factory_key) { :project_repository_storage_move }
let(:error_key) { :project }
let(:repository_storage_worker) { ProjectUpdateRepositoryStorageWorker }
end
describe 'state transitions' do
let(:storage) { 'test_second_storage' }
before do
stub_storage_settings(storage => { 'path' => 'tmp/tests/extra_storage' })
end
context 'when started' do
subject(:storage_move) { create(:project_repository_storage_move, :started, container: project, destination_storage_name: storage) }
context 'and transits to replicated' do
it 'sets the repository storage and marks the container as writable' do
storage_move.finish_replication!
expect(project.repository_storage).to eq(storage)
expect(project).not_to be_repository_read_only
end
end
end
end
end

View File

@ -313,17 +313,6 @@ RSpec.describe ProjectStatistics do
it 'stores the size of related uploaded files' do
expect(statistics.update_uploads_size).to eq(3.megabytes)
end
context 'with feature flag disabled' do
before do
statistics.update_columns(uploads_size: 0)
stub_feature_flags(count_uploads_size_in_storage_stats: false)
end
it 'does not store the size of related uploaded files' do
expect(statistics.update_uploads_size).to eq(0)
end
end
end
describe '#update_storage_size' do

View File

@ -0,0 +1,13 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe SnippetRepositoryStorageMove, type: :model do
it_behaves_like 'handles repository moves' do
let_it_be_with_refind(:container) { create(:snippet) }
let(:repository_storage_factory_key) { :snippet_repository_storage_move }
let(:error_key) { :snippet }
let(:repository_storage_worker) { nil } # TODO set to SnippetUpdateRepositoryStorageWorker after https://gitlab.com/gitlab-org/gitlab/-/issues/218991 is implemented
end
end

View File

@ -21,6 +21,7 @@ RSpec.describe Snippet do
it { is_expected.to have_many(:user_mentions).class_name("SnippetUserMention") }
it { is_expected.to have_one(:snippet_repository) }
it { is_expected.to have_one(:statistics).class_name('SnippetStatistics').dependent(:destroy) }
it { is_expected.to have_many(:repository_storage_moves).class_name('SnippetRepositoryStorageMove').inverse_of(:container) }
end
describe 'validation' do

View File

@ -977,6 +977,34 @@ RSpec.describe ProjectPolicy do
end
end
describe 'read_analytics' do
context 'anonymous user' do
let(:current_user) { anonymous }
it { is_expected.to be_allowed(:read_analytics) }
end
context 'project member' do
let(:project) { private_project }
%w(guest reporter developer maintainer).each do |role|
context role do
let(:current_user) { send(role) }
it { is_expected.to be_allowed(:read_analytics) }
context "without access to Analytics" do
before do
project.project_feature.update!(analytics_access_level: ProjectFeature::DISABLED)
end
it { is_expected.to be_disallowed(:read_analytics) }
end
end
end
end
end
it_behaves_like 'Self-managed Core resource access tokens'
describe 'operations feature' do

View File

@ -873,6 +873,7 @@ RSpec.describe API::Projects do
jobs_enabled: false,
merge_requests_enabled: false,
forking_access_level: 'disabled',
analytics_access_level: 'disabled',
wiki_enabled: false,
resolve_outdated_diff_discussions: false,
remove_source_branch_after_merge: true,
@ -903,6 +904,7 @@ RSpec.describe API::Projects do
expect(project.project_feature.merge_requests_access_level).to eq(ProjectFeature::DISABLED)
expect(project.project_feature.wiki_access_level).to eq(ProjectFeature::DISABLED)
expect(project.operations_access_level).to eq(ProjectFeature::DISABLED)
expect(project.project_feature.analytics_access_level).to eq(ProjectFeature::DISABLED)
end
it 'creates a project using a template' do
@ -1623,6 +1625,7 @@ RSpec.describe API::Projects do
expect(json_response['issues_access_level']).to be_present
expect(json_response['merge_requests_access_level']).to be_present
expect(json_response['forking_access_level']).to be_present
expect(json_response['analytics_access_level']).to be_present
expect(json_response['wiki_access_level']).to be_present
expect(json_response['builds_access_level']).to be_present
expect(json_response['operations_access_level']).to be_present

View File

@ -63,6 +63,7 @@ RSpec.shared_examples 'handles repository moves' do
context 'and transits to scheduled' do
it 'triggers the corresponding repository storage worker' do
skip unless repository_storage_worker # TODO remove after https://gitlab.com/gitlab-org/gitlab/-/issues/218991 is implemented
expect(repository_storage_worker).to receive(:perform_async).with(container.id, 'test_second_storage', storage_move.id)
storage_move.schedule!
@ -72,6 +73,7 @@ RSpec.shared_examples 'handles repository moves' do
context 'when the transition fails' do
it 'does not trigger ProjectUpdateRepositoryStorageWorker and adds an error' do
skip unless repository_storage_worker # TODO remove after https://gitlab.com/gitlab-org/gitlab/-/issues/218991 is implemented
allow(storage_move.container).to receive(:set_repository_read_only!).and_raise(StandardError, 'foobar')
expect(repository_storage_worker).not_to receive(:perform_async)
@ -94,10 +96,9 @@ RSpec.shared_examples 'handles repository moves' do
subject(:storage_move) { create(repository_storage_factory_key, :started, container: container, destination_storage_name: 'test_second_storage') }
context 'and transits to replicated' do
it 'sets the repository storage and marks the container as writable' do
it 'marks the container as writable' do
storage_move.finish_replication!
expect(container.repository_storage).to eq('test_second_storage')
expect(container).not_to be_repository_read_only
end
end