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

gitlab.com/gitlab-org/gitlab-foss.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGitLab Bot <gitlab-bot@gitlab.com>2021-07-01 12:07:33 +0300
committerGitLab Bot <gitlab-bot@gitlab.com>2021-07-01 12:07:33 +0300
commitf5eabcfa0e39e8212eb333d9e824294d14f530d5 (patch)
tree1a365d06c584e61b50ac3850b4058fd7826173c8
parent0537e77587de43e2b3c5cbd8610641b3003a9840 (diff)
Add latest changes from gitlab-org/gitlab@master
-rw-r--r--app/assets/javascripts/batch_comments/components/review_bar.vue2
-rw-r--r--app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js13
-rw-r--r--app/assets/stylesheets/components/batch_comments/review_bar.scss10
-rw-r--r--app/controllers/projects/forks_controller.rb2
-rw-r--r--app/finders/merge_requests_finder.rb7
-rw-r--r--app/helpers/nav_helper.rb2
-rw-r--r--app/models/concerns/approvable_base.rb13
-rw-r--r--app/models/plan_limits.rb4
-rw-r--r--app/services/projects/protect_default_branch_service.rb6
-rw-r--r--app/views/groups/_home_panel.html.haml4
-rw-r--r--app/views/projects/_home_panel.html.haml4
-rw-r--r--app/views/projects/forks/new.html.haml2
-rw-r--r--app/workers/all_queues.yml2
-rw-r--r--app/workers/authorized_project_update/user_refresh_from_replica_worker.rb48
-rw-r--r--config/feature_flags/development/fork_project_form.yml2
-rw-r--r--config/feature_flags/development/user_refresh_from_replica_worker_uses_replica_db.yml8
-rw-r--r--db/migrate/20210627204936_add_plan_limits_max_size_cluster_image_scanning_column.rb7
-rw-r--r--db/schema_migrations/202106272049361
-rw-r--r--db/structure.sql3
-rw-r--r--doc/administration/instance_limits.md2
-rw-r--r--doc/api/graphql/reference/index.md6
-rw-r--r--doc/development/migration_style_guide.md24
-rw-r--r--doc/development/usage_ping/dictionary.md72
-rw-r--r--lib/api/admin/ci/variables.rb2
-rw-r--r--lib/api/ci/runner.rb2
-rw-r--r--lib/api/variables.rb2
-rw-r--r--locale/gitlab.pot6
-rw-r--r--spec/features/merge_request/batch_comments_spec.rb4
-rw-r--r--spec/finders/merge_requests_finder_spec.rb38
-rw-r--r--spec/models/concerns/approvable_base_spec.rb21
-rw-r--r--spec/models/plan_limits_spec.rb2
-rw-r--r--spec/services/projects/protect_default_branch_service_spec.rb47
-rw-r--r--spec/views/groups/_home_panel.html.haml_spec.rb26
-rw-r--r--spec/views/projects/_home_panel.html.haml_spec.rb32
-rw-r--r--spec/workers/authorized_project_update/user_refresh_from_replica_worker_spec.rb90
35 files changed, 452 insertions, 64 deletions
diff --git a/app/assets/javascripts/batch_comments/components/review_bar.vue b/app/assets/javascripts/batch_comments/components/review_bar.vue
index 9ffc5ee34cf..080a5543e53 100644
--- a/app/assets/javascripts/batch_comments/components/review_bar.vue
+++ b/app/assets/javascripts/batch_comments/components/review_bar.vue
@@ -26,7 +26,7 @@ export default {
</script>
<template>
<div v-show="draftsCount > 0">
- <nav class="review-bar-component">
+ <nav class="review-bar-component" data-testid="review_bar_component">
<div
class="review-bar-content d-flex gl-justify-content-end"
data-qa-selector="review_bar_content"
diff --git a/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
index 38a5bdd4a71..d00e6e59cf5 100644
--- a/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
+++ b/app/assets/javascripts/filtered_search/add_extra_tokens_for_merge_requests.js
@@ -75,6 +75,13 @@ export default (IssuableTokenKeys, disableTargetBranchFilter = false) => {
icon: 'approval',
tag: '@approved-by',
},
+ tokenAlternative: {
+ formattedKey: __('Approved-By'),
+ key: 'approved-by',
+ type: 'string',
+ param: 'usernames',
+ symbol: '@',
+ },
condition: [
{
url: 'approved_by_usernames[]=None',
@@ -105,7 +112,11 @@ export default (IssuableTokenKeys, disableTargetBranchFilter = false) => {
const tokenPosition = 3;
IssuableTokenKeys.tokenKeys.splice(tokenPosition, 0, ...[approvedBy.token]);
- IssuableTokenKeys.tokenKeysWithAlternative.splice(tokenPosition, 0, ...[approvedBy.token]);
+ IssuableTokenKeys.tokenKeysWithAlternative.splice(
+ tokenPosition,
+ 0,
+ ...[approvedBy.token, approvedBy.tokenAlternative],
+ );
IssuableTokenKeys.conditions.push(...approvedBy.condition);
const environmentToken = {
diff --git a/app/assets/stylesheets/components/batch_comments/review_bar.scss b/app/assets/stylesheets/components/batch_comments/review_bar.scss
index d769ea73101..bcd06974813 100644
--- a/app/assets/stylesheets/components/batch_comments/review_bar.scss
+++ b/app/assets/stylesheets/components/batch_comments/review_bar.scss
@@ -2,13 +2,15 @@
position: fixed;
bottom: 0;
left: 0;
- width: 100%;
- background: $white;
z-index: $zindex-dropdown-menu;
- padding: 7px 0 6px; // to keep aligned with "collapse sidebar" button on the left sidebar
- border-top: 1px solid $border-color;
+ display: flex;
+ align-items: center;
+ width: 100%;
+ height: $toggle-sidebar-height;
padding-left: $contextual-sidebar-width;
padding-right: $gutter_collapsed_width;
+ background: $white;
+ border-top: 1px solid $border-color;
transition: padding $sidebar-transition-duration;
.page-with-icon-sidebar & {
diff --git a/app/controllers/projects/forks_controller.rb b/app/controllers/projects/forks_controller.rb
index 9e42d218ceb..0f00fda4687 100644
--- a/app/controllers/projects/forks_controller.rb
+++ b/app/controllers/projects/forks_controller.rb
@@ -17,7 +17,7 @@ class Projects::ForksController < Projects::ApplicationController
feature_category :source_code_management
before_action do
- push_frontend_feature_flag(:fork_project_form)
+ push_frontend_feature_flag(:fork_project_form, @project, default_enabled: :yaml)
end
def index
diff --git a/app/finders/merge_requests_finder.rb b/app/finders/merge_requests_finder.rb
index 19fcd91a5b8..e23fa3f7f68 100644
--- a/app/finders/merge_requests_finder.rb
+++ b/app/finders/merge_requests_finder.rb
@@ -76,6 +76,7 @@ class MergeRequestsFinder < IssuableFinder
def filter_negated_items(items)
items = super(items)
items = by_negated_reviewer(items)
+ items = by_negated_approved_by(items)
by_negated_target_branch(items)
end
@@ -119,6 +120,12 @@ class MergeRequestsFinder < IssuableFinder
end
# rubocop: enable CodeReuse/ActiveRecord
+ def by_negated_approved_by(items)
+ return items unless not_params[:approved_by_usernames]
+
+ items.not_approved_by_users_with_usernames(not_params[:approved_by_usernames])
+ end
+
def source_project_id
@source_project_id ||= params[:source_project_id].presence
end
diff --git a/app/helpers/nav_helper.rb b/app/helpers/nav_helper.rb
index 29887fb238b..6c57a31f3db 100644
--- a/app/helpers/nav_helper.rb
+++ b/app/helpers/nav_helper.rb
@@ -64,7 +64,7 @@ module NavHelper
end
def admin_analytics_nav_links
- %w(dev_ops_report)
+ %w(dev_ops_report usage_trends)
end
def group_issues_sub_menu_items
diff --git a/app/models/concerns/approvable_base.rb b/app/models/concerns/approvable_base.rb
index c2d94b50f8d..ef7ba7b1089 100644
--- a/app/models/concerns/approvable_base.rb
+++ b/app/models/concerns/approvable_base.rb
@@ -24,6 +24,19 @@ module ApprovableBase
.group(:id)
.having("COUNT(users.id) = ?", usernames.size)
end
+
+ scope :not_approved_by_users_with_usernames, -> (usernames) do
+ users = User.where(username: usernames).select(:id)
+ self_table = self.arel_table
+ app_table = Approval.arel_table
+
+ where(
+ Approval.where(approvals: { user_id: users })
+ .where(app_table[:merge_request_id].eq(self_table[:id]))
+ .select('true')
+ .arel.exists.not
+ )
+ end
end
class_methods do
diff --git a/app/models/plan_limits.rb b/app/models/plan_limits.rb
index f17078c0cab..bf08da6a1e1 100644
--- a/app/models/plan_limits.rb
+++ b/app/models/plan_limits.rb
@@ -1,6 +1,10 @@
# frozen_string_literal: true
class PlanLimits < ApplicationRecord
+ include IgnorableColumns
+
+ ignore_column :ci_max_artifact_size_running_container_scanning, remove_with: '14.3', remove_after: '2021-08-22'
+
LimitUndefinedError = Class.new(StandardError)
belongs_to :plan
diff --git a/app/services/projects/protect_default_branch_service.rb b/app/services/projects/protect_default_branch_service.rb
index 1d3fb523448..0111b9e377a 100644
--- a/app/services/projects/protect_default_branch_service.rb
+++ b/app/services/projects/protect_default_branch_service.rb
@@ -22,7 +22,7 @@ module Projects
# Ensure HEAD points to the default branch in case it is not master
project.change_head(default_branch)
- create_protected_branch if protect_branch?
+ create_protected_branch if protect_branch? && !protected_branch_exists?
end
def create_protected_branch
@@ -44,6 +44,10 @@ module Projects
!ProtectedBranch.protected?(project, default_branch)
end
+ def protected_branch_exists?
+ project.protected_branches.find_by_name(default_branch).present?
+ end
+
def default_branch
project.default_branch
end
diff --git a/app/views/groups/_home_panel.html.haml b/app/views/groups/_home_panel.html.haml
index 624d0a21b81..b7c2b4d86b2 100644
--- a/app/views/groups/_home_panel.html.haml
+++ b/app/views/groups/_home_panel.html.haml
@@ -23,6 +23,10 @@
.home-panel-buttons.col-md-12.col-lg-6
- if current_user
.gl-display-flex.gl-flex-wrap.gl-lg-justify-content-end.gl-mx-n2{ data: { testid: 'group-buttons' } }
+ - if current_user.admin?
+ = link_to [:admin, @group], class: 'btn btn-default gl-button btn-icon gl-mt-3 gl-mr-2', title: s_('View group in admin area'),
+ data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = sprite_icon('admin')
- if @notification_setting
.js-vue-notification-dropdown{ data: { disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(@notification_setting).to_json, notification_level: @notification_setting.level, help_page_path: help_page_path('user/profile/notifications'), group_id: @group.id, container_class: 'gl-mx-2 gl-mt-3 gl-vertical-align-top' } }
- if can_create_subgroups
diff --git a/app/views/projects/_home_panel.html.haml b/app/views/projects/_home_panel.html.haml
index 26291c0358e..86172499118 100644
--- a/app/views/projects/_home_panel.html.haml
+++ b/app/views/projects/_home_panel.html.haml
@@ -47,6 +47,10 @@
= cache_if(cache_enabled, [@project, :buttons, current_user, @notification_setting], expires_in: 1.day) do
.project-repo-buttons.gl-display-flex.gl-justify-content-md-end.gl-align-items-start.gl-flex-wrap.gl-mt-5
- if current_user
+ - if current_user.admin?
+ = link_to [:admin, @project], class: 'btn gl-button btn-icon gl-align-self-start gl-py-2! gl-mr-3', title: s_('View project in admin area'),
+ data: {toggle: 'tooltip', placement: 'bottom', container: 'body'} do
+ = sprite_icon('admin')
.gl-display-flex.gl-align-items-start.gl-mr-3
- if @notification_setting
.js-vue-notification-dropdown{ data: { button_size: "small", disabled: emails_disabled.to_s, dropdown_items: notification_dropdown_items(@notification_setting).to_json, notification_level: @notification_setting.level, help_page_path: help_page_path('user/profile/notifications'), project_id: @project.id } }
diff --git a/app/views/projects/forks/new.html.haml b/app/views/projects/forks/new.html.haml
index 0716eda79a8..8848fbae9cb 100644
--- a/app/views/projects/forks/new.html.haml
+++ b/app/views/projects/forks/new.html.haml
@@ -1,6 +1,6 @@
- page_title s_("ForkProject|Fork project")
-- if Feature.enabled?(:fork_project_form)
+- if Feature.enabled?(:fork_project_form, @project, default_enabled: :yaml)
#fork-groups-mount-element{ data: { fork_illustration: image_path('illustrations/project-create-new-sm.svg'),
endpoint: new_project_fork_path(@project, format: :json),
new_group_path: new_group_path,
diff --git a/app/workers/all_queues.yml b/app/workers/all_queues.yml
index eff33df665b..61edd4b91e3 100644
--- a/app/workers/all_queues.yml
+++ b/app/workers/all_queues.yml
@@ -37,7 +37,7 @@
:urgency: :low
:resource_boundary: :unknown
:weight: 1
- :idempotent: true
+ :idempotent:
:tags: []
- :name: authorized_project_update:authorized_project_update_user_refresh_over_user_range
:worker_name: AuthorizedProjectUpdate::UserRefreshOverUserRangeWorker
diff --git a/app/workers/authorized_project_update/user_refresh_from_replica_worker.rb b/app/workers/authorized_project_update/user_refresh_from_replica_worker.rb
index 5ca9de63fd7..dbd54ad2adf 100644
--- a/app/workers/authorized_project_update/user_refresh_from_replica_worker.rb
+++ b/app/workers/authorized_project_update/user_refresh_from_replica_worker.rb
@@ -1,15 +1,55 @@
# frozen_string_literal: true
module AuthorizedProjectUpdate
- class UserRefreshFromReplicaWorker < ::AuthorizedProjectsWorker
+ class UserRefreshFromReplicaWorker # rubocop:disable Scalability/IdempotentWorker
+ include ApplicationWorker
+
+ sidekiq_options retry: 3
feature_category :authentication_and_authorization
urgency :low
queue_namespace :authorized_project_update
+
+ # This job will not be deduplicated since it is marked with
+ # `data_consistency :delayed` and not `idempotent!`
+ # See https://gitlab.com/gitlab-org/gitlab/-/issues/325291
deduplicate :until_executing, including_scheduled: true
- idempotent!
+ data_consistency :delayed
+
+ def perform(user_id)
+ user = User.find_by_id(user_id)
+ return unless user
+
+ if Feature.enabled?(:user_refresh_from_replica_worker_uses_replica_db)
+ enqueue_project_authorizations_refresh(user) if project_authorizations_needs_refresh?(user)
+ else
+ use_primary_database
+ user.refresh_authorized_projects(source: self.class.name)
+ end
+ end
+
+ private
+
+ def use_primary_database
+ if ::Gitlab::Database::LoadBalancing.enable?
+ ::Gitlab::Database::LoadBalancing::Session.current.use_primary!
+ end
+ end
+
+ def project_authorizations_needs_refresh?(user)
+ AuthorizedProjectUpdate::FindRecordsDueForRefreshService.new(user).needs_refresh?
+ end
+
+ def enqueue_project_authorizations_refresh(user)
+ with_context(user: user, related_class: current_caller_id) do
+ AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker.perform_async(user.id)
+ end
+ end
- # This worker will start reading data from the replica database soon
- # Issue: https://gitlab.com/gitlab-org/gitlab/-/issues/333219
+ # We use this so that we can obtain the details of the original caller
+ # in the enqueued `AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker` job.
+ def current_caller_id
+ Gitlab::ApplicationContext.current_context_attribute('meta.caller_id').presence
+ end
end
end
diff --git a/config/feature_flags/development/fork_project_form.yml b/config/feature_flags/development/fork_project_form.yml
index 93bccc4f41b..90532c78c8a 100644
--- a/config/feature_flags/development/fork_project_form.yml
+++ b/config/feature_flags/development/fork_project_form.yml
@@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/321387
milestone: '13.10'
type: development
group: group::source code
-default_enabled: false
+default_enabled: true
diff --git a/config/feature_flags/development/user_refresh_from_replica_worker_uses_replica_db.yml b/config/feature_flags/development/user_refresh_from_replica_worker_uses_replica_db.yml
new file mode 100644
index 00000000000..6e3d8d315cd
--- /dev/null
+++ b/config/feature_flags/development/user_refresh_from_replica_worker_uses_replica_db.yml
@@ -0,0 +1,8 @@
+---
+name: user_refresh_from_replica_worker_uses_replica_db
+introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/64276
+rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/334766
+milestone: '14.1'
+type: development
+group: group::access
+default_enabled: false
diff --git a/db/migrate/20210627204936_add_plan_limits_max_size_cluster_image_scanning_column.rb b/db/migrate/20210627204936_add_plan_limits_max_size_cluster_image_scanning_column.rb
new file mode 100644
index 00000000000..322e6991d0b
--- /dev/null
+++ b/db/migrate/20210627204936_add_plan_limits_max_size_cluster_image_scanning_column.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class AddPlanLimitsMaxSizeClusterImageScanningColumn < ActiveRecord::Migration[6.0]
+ def change
+ add_column :plan_limits, :ci_max_artifact_size_cluster_image_scanning, :integer, null: false, default: 0
+ end
+end
diff --git a/db/schema_migrations/20210627204936 b/db/schema_migrations/20210627204936
new file mode 100644
index 00000000000..abc39339816
--- /dev/null
+++ b/db/schema_migrations/20210627204936
@@ -0,0 +1 @@
+b37bf7db9c00c8f54c0ccca2d418f1279e12ff7e5b71347966494dc5645eb648 \ No newline at end of file
diff --git a/db/structure.sql b/db/structure.sql
index a9f532e63b5..7a274ebfdf8 100644
--- a/db/structure.sql
+++ b/db/structure.sql
@@ -16352,7 +16352,8 @@ CREATE TABLE plan_limits (
ci_registered_project_runners integer DEFAULT 1000 NOT NULL,
web_hook_calls integer DEFAULT 0 NOT NULL,
ci_daily_pipeline_schedule_triggers integer DEFAULT 0 NOT NULL,
- ci_max_artifact_size_running_container_scanning integer DEFAULT 0 NOT NULL
+ ci_max_artifact_size_running_container_scanning integer DEFAULT 0 NOT NULL,
+ ci_max_artifact_size_cluster_image_scanning integer DEFAULT 0 NOT NULL
);
CREATE SEQUENCE plan_limits_id_seq
diff --git a/doc/administration/instance_limits.md b/doc/administration/instance_limits.md
index 300c107abc8..ea3348e6b75 100644
--- a/doc/administration/instance_limits.md
+++ b/doc/administration/instance_limits.md
@@ -426,6 +426,7 @@ setting is used:
| `ci_max_artifact_size_archive` | 0 |
| `ci_max_artifact_size_browser_performance` | 0 |
| `ci_max_artifact_size_cluster_applications` | 0 |
+| `ci_max_artifact_size_cluster_image_scanning` | 0 |
| `ci_max_artifact_size_cobertura` | 0 |
| `ci_max_artifact_size_codequality` | 0 |
| `ci_max_artifact_size_container_scanning` | 0 |
@@ -444,7 +445,6 @@ setting is used:
| `ci_max_artifact_size_network_referee` | 0 |
| `ci_max_artifact_size_performance` | 0 |
| `ci_max_artifact_size_requirements` | 0 |
-| `ci_max_artifact_size_running_container_scanning` | 0 |
| `ci_max_artifact_size_sast` | 0 |
| `ci_max_artifact_size_secret_detection` | 0 |
| `ci_max_artifact_size_terraform` | 5 MB ([introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/37018) in GitLab 13.3) |
diff --git a/doc/api/graphql/reference/index.md b/doc/api/graphql/reference/index.md
index 56dc130bdd2..4a9c75967a3 100644
--- a/doc/api/graphql/reference/index.md
+++ b/doc/api/graphql/reference/index.md
@@ -12627,11 +12627,11 @@ Represents summary of a security report.
| Name | Type | Description |
| ---- | ---- | ----------- |
| <a id="securityreportsummaryapifuzzing"></a>`apiFuzzing` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `api_fuzzing` scan. |
+| <a id="securityreportsummaryclusterimagescanning"></a>`clusterImageScanning` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `cluster_image_scanning` scan. |
| <a id="securityreportsummarycontainerscanning"></a>`containerScanning` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `container_scanning` scan. |
| <a id="securityreportsummarycoveragefuzzing"></a>`coverageFuzzing` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `coverage_fuzzing` scan. |
| <a id="securityreportsummarydast"></a>`dast` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `dast` scan. |
| <a id="securityreportsummarydependencyscanning"></a>`dependencyScanning` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `dependency_scanning` scan. |
-| <a id="securityreportsummaryrunningcontainerscanning"></a>`runningContainerScanning` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `running_container_scanning` scan. |
| <a id="securityreportsummarysast"></a>`sast` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `sast` scan. |
| <a id="securityreportsummarysecretdetection"></a>`secretDetection` | [`SecurityReportSummarySection`](#securityreportsummarysection) | Aggregated counts for the `secret_detection` scan. |
@@ -13486,7 +13486,7 @@ Represents a vulnerability.
| <a id="vulnerabilitynotes"></a>`notes` | [`NoteConnection!`](#noteconnection) | All notes on this noteable. (see [Connections](#connections)) |
| <a id="vulnerabilityprimaryidentifier"></a>`primaryIdentifier` | [`VulnerabilityIdentifier`](#vulnerabilityidentifier) | Primary identifier of the vulnerability. |
| <a id="vulnerabilityproject"></a>`project` | [`Project`](#project) | The project on which the vulnerability was found. |
-| <a id="vulnerabilityreporttype"></a>`reportType` | [`VulnerabilityReportType`](#vulnerabilityreporttype) | Type of the security report that found the vulnerability (SAST, DEPENDENCY_SCANNING, CONTAINER_SCANNING, DAST, SECRET_DETECTION, COVERAGE_FUZZING, API_FUZZING, RUNNING_CONTAINER_SCANNING). `Scan Type` in the UI. |
+| <a id="vulnerabilityreporttype"></a>`reportType` | [`VulnerabilityReportType`](#vulnerabilityreporttype) | Type of the security report that found the vulnerability (SAST, DEPENDENCY_SCANNING, CONTAINER_SCANNING, DAST, SECRET_DETECTION, COVERAGE_FUZZING, API_FUZZING, CLUSTER_IMAGE_SCANNING). `Scan Type` in the UI. |
| <a id="vulnerabilityresolvedat"></a>`resolvedAt` | [`Time`](#time) | Timestamp of when the vulnerability state was changed to resolved. |
| <a id="vulnerabilityresolvedby"></a>`resolvedBy` | [`UserCore`](#usercore) | The user that resolved the vulnerability. |
| <a id="vulnerabilityresolvedondefaultbranch"></a>`resolvedOnDefaultBranch` | [`Boolean!`](#boolean) | Indicates whether the vulnerability is fixed on the default branch or not. |
@@ -15162,11 +15162,11 @@ The type of the security scan that found the vulnerability.
| Value | Description |
| ----- | ----------- |
| <a id="vulnerabilityreporttypeapi_fuzzing"></a>`API_FUZZING` | |
+| <a id="vulnerabilityreporttypecluster_image_scanning"></a>`CLUSTER_IMAGE_SCANNING` | |
| <a id="vulnerabilityreporttypecontainer_scanning"></a>`CONTAINER_SCANNING` | |
| <a id="vulnerabilityreporttypecoverage_fuzzing"></a>`COVERAGE_FUZZING` | |
| <a id="vulnerabilityreporttypedast"></a>`DAST` | |
| <a id="vulnerabilityreporttypedependency_scanning"></a>`DEPENDENCY_SCANNING` | |
-| <a id="vulnerabilityreporttyperunning_container_scanning"></a>`RUNNING_CONTAINER_SCANNING` | |
| <a id="vulnerabilityreporttypesast"></a>`SAST` | |
| <a id="vulnerabilityreporttypesecret_detection"></a>`SECRET_DETECTION` | |
diff --git a/doc/development/migration_style_guide.md b/doc/development/migration_style_guide.md
index 7dd5dd74f0b..41b3b9ed428 100644
--- a/doc/development/migration_style_guide.md
+++ b/doc/development/migration_style_guide.md
@@ -205,6 +205,30 @@ def down
end
```
+**Multiple changes on the same table:**
+
+The helper `with_lock_retries` wraps all operations into a single transaction. When you have the lock,
+you should do as much as possible inside the transaction rather than trying to get another lock later.
+Be careful about running long database statements within the block. The acquired locks are kept until the transaction (block) finishes and depending on the lock type, it might block other database operations.
+
+```ruby
+include Gitlab::Database::MigrationHelpers
+
+def up
+ with_lock_retries do
+ add_column :users, :full_name, :string
+ add_column :users, :bio, :string
+ end
+end
+
+def down
+ with_lock_retries do
+ remove_column :users, :full_name
+ remove_column :users, :bio
+ end
+end
+```
+
**Removing a foreign key:**
```ruby
diff --git a/doc/development/usage_ping/dictionary.md b/doc/development/usage_ping/dictionary.md
index cfb97f565b4..b7ec3892f1e 100644
--- a/doc/development/usage_ping/dictionary.md
+++ b/doc/development/usage_ping/dictionary.md
@@ -17318,6 +17318,18 @@ Status: `data_available`
Tiers:
+### `usage_activity_by_stage.secure.cluster_image_scanning_scans`
+
+Counts cluster image scanning jobs
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210618124854_cluster_image_scanning_scans.yml)
+
+Group: `group::container security`
+
+Status: `implemented`
+
+Tiers: `ultimate`
+
### `usage_activity_by_stage.secure.container_scanning_scans`
Counts container scanning jobs
@@ -17366,18 +17378,6 @@ Status: `data_available`
Tiers: `ultimate`
-### `usage_activity_by_stage.secure.running_container_scanning_scans`
-
-Counts running container scanning jobs
-
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_all/20210618124854_running_container_scanning_scans.yml)
-
-Group: `group::container security`
-
-Status: `data_available`
-
-Tiers: `ultimate`
-
### `usage_activity_by_stage.secure.sast_scans`
Counts sast jobs
@@ -19394,6 +19394,30 @@ Status: `data_available`
Tiers: `free`
+### `usage_activity_by_stage_monthly.secure.cluster_image_scanning_pipeline`
+
+Pipelines containing a Cluster Image Scanning job
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210618125224_cluster_image_scanning_pipeline.yml)
+
+Group: `group::container security`
+
+Status: `implemented`
+
+Tiers: `ultimate`
+
+### `usage_activity_by_stage_monthly.secure.cluster_image_scanning_scans`
+
+Counts cluster image scanning jobs
+
+[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210618101233_cluster_image_scanning_scans.yml)
+
+Group: `group::container security`
+
+Status: `implemented`
+
+Tiers: `ultimate`
+
### `usage_activity_by_stage_monthly.secure.container_scanning_pipeline`
Pipelines containing a Container Scanning job
@@ -19490,30 +19514,6 @@ Status: `data_available`
Tiers: `ultimate`
-### `usage_activity_by_stage_monthly.secure.running_container_scanning_pipeline`
-
-Pipelines containing a Running Container Scanning job
-
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210618125224_running_container_scanning_pipeline.yml)
-
-Group: `group::container security`
-
-Status: `data_available`
-
-Tiers: `ultimate`
-
-### `usage_activity_by_stage_monthly.secure.running_container_scanning_scans`
-
-Counts running container scanning jobs
-
-[YAML definition](https://gitlab.com/gitlab-org/gitlab/-/blob/master/ee/config/metrics/counts_28d/20210618101233_running_container_scanning_scans.yml)
-
-Group: `group::container security`
-
-Status: `data_available`
-
-Tiers: `ultimate`
-
### `usage_activity_by_stage_monthly.secure.sast_pipeline`
Counts of Pipelines that have at least 1 SAST job
diff --git a/lib/api/admin/ci/variables.rb b/lib/api/admin/ci/variables.rb
index 654d3a48162..0462878c90c 100644
--- a/lib/api/admin/ci/variables.rb
+++ b/lib/api/admin/ci/variables.rb
@@ -8,7 +8,7 @@ module API
before { authenticated_as_admin! }
- feature_category :continuous_integration
+ feature_category :pipeline_authoring
namespace 'admin' do
namespace 'ci' do
diff --git a/lib/api/ci/runner.rb b/lib/api/ci/runner.rb
index b6efa0b04a1..ca165ab78af 100644
--- a/lib/api/ci/runner.rb
+++ b/lib/api/ci/runner.rb
@@ -7,7 +7,7 @@ module API
content_type :txt, 'text/plain'
- feature_category :continuous_integration
+ feature_category :runner
resource :runners do
desc 'Registers a new Runner' do
diff --git a/lib/api/variables.rb b/lib/api/variables.rb
index 8b0745c6b5b..75df0e050a6 100644
--- a/lib/api/variables.rb
+++ b/lib/api/variables.rb
@@ -7,7 +7,7 @@ module API
before { authenticate! }
before { authorize! :admin_build, user_project }
- feature_category :continuous_integration
+ feature_category :pipeline_authoring
helpers Helpers::VariablesHelpers
diff --git a/locale/gitlab.pot b/locale/gitlab.pot
index a13fd8486b6..f643a0e73ba 100644
--- a/locale/gitlab.pot
+++ b/locale/gitlab.pot
@@ -35860,6 +35860,9 @@ msgstr ""
msgid "View full log"
msgstr ""
+msgid "View group in admin area"
+msgstr ""
+
msgid "View group labels"
msgstr ""
@@ -35911,6 +35914,9 @@ msgstr ""
msgid "View project"
msgstr ""
+msgid "View project in admin area"
+msgstr ""
+
msgid "View project labels"
msgstr ""
diff --git a/spec/features/merge_request/batch_comments_spec.rb b/spec/features/merge_request/batch_comments_spec.rb
index a5094be2bcf..1fcb40df491 100644
--- a/spec/features/merge_request/batch_comments_spec.rb
+++ b/spec/features/merge_request/batch_comments_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
end
it 'has review bar' do
- expect(page).to have_css('.review-bar-component', visible: false)
+ expect(page).to have_selector('[data-testid="review_bar_component"]', visible: false)
end
it 'adds draft note' do
@@ -32,7 +32,7 @@ RSpec.describe 'Merge request > Batch comments', :js do
expect(find('.draft-note-component')).to have_content('Line is wrong')
- expect(page).to have_css('.review-bar-component')
+ expect(page).to have_selector('[data-testid="review_bar_component"]')
expect(find('.review-bar-content .btn-confirm')).to have_content('1')
end
diff --git a/spec/finders/merge_requests_finder_spec.rb b/spec/finders/merge_requests_finder_spec.rb
index 3b835d366db..c2ea918449c 100644
--- a/spec/finders/merge_requests_finder_spec.rb
+++ b/spec/finders/merge_requests_finder_spec.rb
@@ -520,6 +520,44 @@ RSpec.describe MergeRequestsFinder do
end
end
+ context 'filtering by approved by' do
+ let(:params) { { approved_by_usernames: user2.username } }
+
+ before do
+ create(:approval, merge_request: merge_request3, user: user2)
+ end
+
+ it 'returns merge requests approved by that user' do
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(merge_request3)
+ end
+
+ context 'not filter' do
+ let(:params) { { not: { approved_by_usernames: user2.username } } }
+
+ it 'returns merge requests not approved by that user' do
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request4, merge_request5)
+ end
+ end
+
+ context 'when filtering by author and not approved by' do
+ let(:params) { { not: { approved_by_usernames: user2.username }, author_username: user.username } }
+
+ before do
+ merge_request4.update!(author: user2)
+ end
+
+ it 'returns merge requests authored by user and not approved by user2' do
+ merge_requests = described_class.new(user, params).execute
+
+ expect(merge_requests).to contain_exactly(merge_request1, merge_request2, merge_request5)
+ end
+ end
+ end
+
context 'filtering by created_at/updated_at' do
let(:new_project) { create(:project, forked_from_project: project1) }
diff --git a/spec/models/concerns/approvable_base_spec.rb b/spec/models/concerns/approvable_base_spec.rb
index a9e944cf220..c7ea2631a24 100644
--- a/spec/models/concerns/approvable_base_spec.rb
+++ b/spec/models/concerns/approvable_base_spec.rb
@@ -59,4 +59,25 @@ RSpec.describe ApprovableBase do
end
end
end
+
+ describe '.not_approved_by_users_with_usernames' do
+ subject { MergeRequest.not_approved_by_users_with_usernames([user.username, user2.username]) }
+
+ let!(:merge_request2) { create(:merge_request) }
+ let!(:merge_request3) { create(:merge_request) }
+ let!(:merge_request4) { create(:merge_request) }
+ let(:user2) { create(:user) }
+ let(:user3) { create(:user) }
+
+ before do
+ create(:approval, merge_request: merge_request, user: user)
+ create(:approval, merge_request: merge_request2, user: user2)
+ create(:approval, merge_request: merge_request2, user: user3)
+ create(:approval, merge_request: merge_request4, user: user3)
+ end
+
+ it 'has the merge request that is not approved at all and not approved by either user' do
+ expect(subject).to contain_exactly(merge_request3, merge_request4)
+ end
+ end
end
diff --git a/spec/models/plan_limits_spec.rb b/spec/models/plan_limits_spec.rb
index 9078d72e044..72fda2280e5 100644
--- a/spec/models/plan_limits_spec.rb
+++ b/spec/models/plan_limits_spec.rb
@@ -185,7 +185,7 @@ RSpec.describe PlanLimits do
ci_max_artifact_size_junit
ci_max_artifact_size_sast
ci_max_artifact_size_dast
- ci_max_artifact_size_running_container_scanning
+ ci_max_artifact_size_cluster_image_scanning
ci_max_artifact_size_codequality
ci_max_artifact_size_license_management
ci_max_artifact_size_performance
diff --git a/spec/services/projects/protect_default_branch_service_spec.rb b/spec/services/projects/protect_default_branch_service_spec.rb
index a485a64ca35..c8aa421cdd4 100644
--- a/spec/services/projects/protect_default_branch_service_spec.rb
+++ b/spec/services/projects/protect_default_branch_service_spec.rb
@@ -99,6 +99,53 @@ RSpec.describe Projects::ProtectDefaultBranchService do
.not_to have_received(:create_protected_branch)
end
end
+
+ context 'when protected branch does not exist' do
+ before do
+ allow(service)
+ .to receive(:protected_branch_exists?)
+ .and_return(false)
+ allow(service)
+ .to receive(:protect_branch?)
+ .and_return(true)
+ end
+
+ it 'changes the HEAD of the project' do
+ service.protect_default_branch
+
+ expect(project)
+ .to have_received(:change_head)
+ end
+
+ it 'protects the default branch' do
+ service.protect_default_branch
+
+ expect(service)
+ .to have_received(:create_protected_branch)
+ end
+ end
+
+ context 'when protected branch already exists' do
+ before do
+ allow(service)
+ .to receive(:protected_branch_exists?)
+ .and_return(true)
+ end
+
+ it 'changes the HEAD of the project' do
+ service.protect_default_branch
+
+ expect(project)
+ .to have_received(:change_head)
+ end
+
+ it 'does not protect the default branch' do
+ service.protect_default_branch
+
+ expect(service)
+ .not_to have_received(:create_protected_branch)
+ end
+ end
end
describe '#create_protected_branch' do
diff --git a/spec/views/groups/_home_panel.html.haml_spec.rb b/spec/views/groups/_home_panel.html.haml_spec.rb
index b8168b20450..e76862cdaea 100644
--- a/spec/views/groups/_home_panel.html.haml_spec.rb
+++ b/spec/views/groups/_home_panel.html.haml_spec.rb
@@ -14,4 +14,30 @@ RSpec.describe 'groups/_home_panel' do
expect(rendered).to have_content("Group ID: #{group.id}")
end
+
+ context 'admin area link' do
+ it 'renders admin area link for admin' do
+ allow(view).to receive(:current_user).and_return(create(:admin))
+
+ render
+
+ expect(rendered).to have_link(href: admin_group_path(group))
+ end
+
+ it 'does not render admin area link for non-admin' do
+ allow(view).to receive(:current_user).and_return(create(:user))
+
+ render
+
+ expect(rendered).not_to have_link(href: admin_group_path(group))
+ end
+
+ it 'does not render admin area link for anonymous' do
+ allow(view).to receive(:current_user).and_return(nil)
+
+ render
+
+ expect(rendered).not_to have_link(href: admin_group_path(group))
+ end
+ end
end
diff --git a/spec/views/projects/_home_panel.html.haml_spec.rb b/spec/views/projects/_home_panel.html.haml_spec.rb
index d329c57af00..78131937d3c 100644
--- a/spec/views/projects/_home_panel.html.haml_spec.rb
+++ b/spec/views/projects/_home_panel.html.haml_spec.rb
@@ -5,6 +5,38 @@ require 'spec_helper'
RSpec.describe 'projects/_home_panel' do
include ProjectForksHelper
+ context 'admin area link' do
+ let(:project) { create(:project) }
+
+ before do
+ assign(:project, project)
+ end
+
+ it 'renders admin area link for admin' do
+ allow(view).to receive(:current_user).and_return(create(:admin))
+
+ render
+
+ expect(rendered).to have_link(href: admin_project_path(project))
+ end
+
+ it 'does not render admin area link for non-admin' do
+ allow(view).to receive(:current_user).and_return(create(:user))
+
+ render
+
+ expect(rendered).not_to have_link(href: admin_project_path(project))
+ end
+
+ it 'does not render admin area link for anonymous' do
+ allow(view).to receive(:current_user).and_return(nil)
+
+ render
+
+ expect(rendered).not_to have_link(href: admin_project_path(project))
+ end
+ end
+
context 'notifications' do
let(:project) { create(:project) }
diff --git a/spec/workers/authorized_project_update/user_refresh_from_replica_worker_spec.rb b/spec/workers/authorized_project_update/user_refresh_from_replica_worker_spec.rb
index cdf2cb493b0..198a16bc22e 100644
--- a/spec/workers/authorized_project_update/user_refresh_from_replica_worker_spec.rb
+++ b/spec/workers/authorized_project_update/user_refresh_from_replica_worker_spec.rb
@@ -3,9 +3,97 @@
require 'spec_helper'
RSpec.describe AuthorizedProjectUpdate::UserRefreshFromReplicaWorker do
+ let_it_be(:project) { create(:project) }
+ let_it_be(:user) { project.namespace.owner }
+
+ let(:execute_worker) { subject.perform(user.id) }
+
it 'is labeled as low urgency' do
expect(described_class.get_urgency).to eq(:low)
end
- it_behaves_like "refreshes user's project authorizations"
+ it_behaves_like 'worker with data consistency',
+ described_class,
+ data_consistency: :delayed
+
+ describe '#perform' do
+ it 'checks if a project_authorization refresh is needed for the user' do
+ expect(AuthorizedProjectUpdate::FindRecordsDueForRefreshService).to(
+ receive(:new).with(user).and_call_original)
+
+ execute_worker
+ end
+
+ context 'when there are project authorization records due for either removal or addition for a specific user' do
+ before do
+ user.project_authorizations.delete_all
+ end
+
+ it 'enqueues a new project authorization update job for the user' do
+ expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).to receive(:perform_async).with(user.id)
+
+ execute_worker
+ end
+
+ context 'setting `meta.caller_id` as `meta.related_class` in the context of the newly enqueued `UserRefreshWithLowUrgencyWorker` job' do
+ context 'when the `UserRefreshFromReplicaWorker` job has a `caller_id` set' do
+ it 'sets the same `caller_id` as `related_class`' do
+ expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).to receive(:perform_async).with(user.id) do
+ expect(Gitlab::ApplicationContext.current).to include('meta.related_class' => 'Foo')
+ end
+
+ Gitlab::ApplicationContext.with_context(caller_id: 'Foo') do
+ execute_worker
+ end
+ end
+ end
+
+ context 'when the `UserRefreshFromReplicaWorker` job does not have a `caller_id` set' do
+ it 'does not set the value of `related_class`' do
+ expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).to receive(:perform_async).with(user.id) do
+ expect(Gitlab::ApplicationContext.current).not_to include('meta.related_class')
+ end
+
+ execute_worker
+ end
+ end
+ end
+ end
+
+ context 'when there are no additions or removals to be made to project authorizations for a specific user' do
+ it 'does not enqueue a new project authorization update job for the user' do
+ expect(AuthorizedProjectUpdate::UserRefreshWithLowUrgencyWorker).not_to receive(:perform_async)
+
+ execute_worker
+ end
+ end
+
+ context 'when the feature flag `user_refresh_from_replica_worker_uses_replica_db` is disabled' do
+ before do
+ stub_feature_flags(user_refresh_from_replica_worker_uses_replica_db: false)
+ end
+
+ context 'when load balancing is enabled' do
+ before do
+ allow(Gitlab::Database::LoadBalancing).to receive(:enable?).and_return(true)
+ end
+
+ it 'reads from the primary database' do
+ expect(Gitlab::Database::LoadBalancing::Session.current)
+ .to receive(:use_primary!)
+
+ execute_worker
+ end
+ end
+
+ it 'calls Users::RefreshAuthorizedProjectsService' do
+ source = 'AuthorizedProjectUpdate::UserRefreshFromReplicaWorker'
+ expect_next_instance_of(Users::RefreshAuthorizedProjectsService, user, { source: source }) do |service|
+ expect(service).to receive(:execute)
+ end
+
+ execute_worker
+ end
+ end
+ end
end