Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-03-04 15:13:49 +00:00
parent c312ea1c28
commit 902aff7fa5
33 changed files with 498 additions and 80 deletions

View File

@ -32,7 +32,9 @@ workflow:
QA_DOCKER_NETWORK: host
QA_GENERATE_ALLURE_REPORT: "true"
QA_CAN_TEST_PRAEFECT: "false"
QA_SUITE_STATUS_ENV_FILE: $CI_PROJECT_DIR/suite_status.env
before_script:
- echo "SUITE_RAN=true" > "$QA_SUITE_STATUS_ENV_FILE"
- export GITLAB_DOMAIN="$(getent hosts docker | awk '{ print $1 }' | head -n1).nip.io"
- export QA_GITLAB_URL="http://gitlab.${GITLAB_DOMAIN}"
- source scripts/qa/cng_deploy/cng-kind.sh
@ -44,6 +46,10 @@ workflow:
- echo "Running - '$QA_COMMAND'"
- eval "$QA_COMMAND"
after_script:
- |
if [ "$CI_JOB_STATUS" == "failed" ]; then
echo "SUITE_FAILED=true" >> "$QA_SUITE_STATUS_ENV_FILE"
fi
- source scripts/qa/cng_deploy/cng-kind.sh
- echo -e "\e[0Ksection_start:`date +%s`:log_deploy[collapsed=true]\r\e[0KDeployment info"
- save_install_logs
@ -53,8 +59,10 @@ workflow:
when: always
reports:
junit: qa/tmp/rspec-*.xml
dotenv: $QA_SUITE_STATUS_ENV_FILE
paths:
- "*.log"
- qa/tmp/test-metrics-*.json
- qa/tmp/allure-results
# ==========================================

View File

@ -1 +1 @@
b6ff186eba35d03b2055c2a0b0e92c65762a6d06
f508b901207c1e6d2d5bcb8da631b5ad815aa483

View File

@ -52,7 +52,7 @@ gem 'sprockets', '~> 3.7.0' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'view_component', '~> 3.11.0' # rubocop:todo Gemfile/MissingFeatureCategory
# Supported DBs
gem 'pg', '~> 1.5.5' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'pg', '~> 1.5.6' # rubocop:todo Gemfile/MissingFeatureCategory
gem 'neighbor', '~> 0.2.3' # rubocop:todo Gemfile/MissingFeatureCategory
@ -525,7 +525,7 @@ group :test do
# Moved in `test` because https://gitlab.com/gitlab-org/gitlab/-/issues/217527
gem 'derailed_benchmarks', require: false # rubocop:todo Gemfile/MissingFeatureCategory
gem 'gitlab_quality-test_tooling', '~> 1.15.0', require: false, feature_category: :tooling
gem 'gitlab_quality-test_tooling', '~> 1.17.0', require: false, feature_category: :tooling
end
gem 'octokit', '~> 8.0', feature_category: :importers

View File

@ -227,7 +227,7 @@
{"name":"gitlab-styles","version":"11.0.0","platform":"ruby","checksum":"0dd8ec066ce9955ac51d3616c6bfded30f75bb526f39ff392ece6f43d5b9406b"},
{"name":"gitlab_chronic_duration","version":"0.12.0","platform":"ruby","checksum":"0d766944d415b5c831f176871ee8625783fc0c5bfbef2d79a3a616f207ffc16d"},
{"name":"gitlab_omniauth-ldap","version":"2.2.0","platform":"ruby","checksum":"bb4d20acb3b123ed654a8f6a47d3fac673ece7ed0b6992edb92dca14bad2838c"},
{"name":"gitlab_quality-test_tooling","version":"1.15.0","platform":"ruby","checksum":"33416dce2d6a686ea95643eb650a249e94f696731e7f7c5bc552b369b2ba0bb5"},
{"name":"gitlab_quality-test_tooling","version":"1.17.0","platform":"ruby","checksum":"64d495e93b777bbc05d84fa54cf8752934d24a21fd40e9ceaf73230f5899a9b4"},
{"name":"globalid","version":"1.1.0","platform":"ruby","checksum":"b337e1746f0c8cb0a6c918234b03a1ddeb4966206ce288fbb57779f59b2d154f"},
{"name":"gon","version":"6.4.0","platform":"ruby","checksum":"e3a618d659392890f1aa7db420f17c75fd7d35aeb5f8fe003697d02c4b88d2f0"},
{"name":"google-apis-androidpublisher_v3","version":"0.34.0","platform":"ruby","checksum":"d7e1d7dd92f79c498fe2082222a1740d788e022e660c135564b3fd299cab5425"},
@ -460,10 +460,7 @@
{"name":"parslet","version":"1.8.2","platform":"ruby","checksum":"08d1ab3721cd3f175bfbee8788b2ddff71f92038f2d69bd65454c22bb9fbd98a"},
{"name":"pastel","version":"0.8.0","platform":"ruby","checksum":"481da9fb7d2f6e6b1a08faf11fa10363172dc40fd47848f096ae21209f805a75"},
{"name":"peek","version":"1.1.0","platform":"ruby","checksum":"d6501ead8cde46d8d8ed0d59eb6f0ba713d0a41c11a2c4a81447b2dce37b3ecc"},
{"name":"pg","version":"1.5.5","platform":"ruby","checksum":"7e4baa3395619424fe0e82d0b0489e54d3015c6ee5896dd007b3bce6d7d49b68"},
{"name":"pg","version":"1.5.5","platform":"x64-mingw-ucrt","checksum":"1adad3a4b4631e3676891639bab5aed68ac7c6a379d8314b768f74e6bdf0375e"},
{"name":"pg","version":"1.5.5","platform":"x64-mingw32","checksum":"98b1480a04e3f8aca9c7fc06dec5662117cec540e5c5058cb3a0812e8261adcc"},
{"name":"pg","version":"1.5.5","platform":"x86-mingw32","checksum":"4fd1e309c5d227ecb1704fc2b3f1168b13748a8d8b0eb7c09d834b28069b9433"},
{"name":"pg","version":"1.5.6","platform":"ruby","checksum":"4bc3ad2438825eea68457373555e3fd4ea1a82027b8a6be98ef57c0d57292b1c"},
{"name":"pg_query","version":"5.1.0","platform":"ruby","checksum":"b7f7f47c864f08ccbed46a8244906fb6ee77ee344fd27250717963928c93145d"},
{"name":"plist","version":"3.7.0","platform":"ruby","checksum":"703ca90a7cb00e8263edd03da2266627f6741d280c910abbbac07c95ffb2f073"},
{"name":"png_quantizator","version":"0.2.1","platform":"ruby","checksum":"6023d4d064125c3a7e02929c95b7320ed6ac0d7341f9e8de0c9ea6576ef3106b"},

View File

@ -741,7 +741,7 @@ GEM
omniauth (>= 1.3, < 3)
pyu-ruby-sasl (>= 0.0.3.3, < 0.1)
rubyntlm (~> 0.5)
gitlab_quality-test_tooling (1.15.0)
gitlab_quality-test_tooling (1.17.0)
activesupport (>= 6.1, < 7.1)
amatch (~> 0.4.1)
gitlab (~> 4.19)
@ -1270,7 +1270,7 @@ GEM
tty-color (~> 0.5)
peek (1.1.0)
railties (>= 4.0.0)
pg (1.5.5)
pg (1.5.6)
pg_query (5.1.0)
google-protobuf (>= 3.22.3)
plist (3.7.0)
@ -1929,7 +1929,7 @@ DEPENDENCIES
gitlab-utils!
gitlab_chronic_duration (~> 0.12)
gitlab_omniauth-ldap (~> 2.2.0)
gitlab_quality-test_tooling (~> 1.15.0)
gitlab_quality-test_tooling (~> 1.17.0)
gon (~> 6.4.0)
google-apis-androidpublisher_v3 (~> 0.34.0)
google-apis-cloudbilling_v1 (~> 0.21.0)
@ -2042,7 +2042,7 @@ DEPENDENCIES
parser (~> 3.3, >= 3.3.0.2)
parslet (~> 1.8)
peek (~> 1.1)
pg (~> 1.5.5)
pg (~> 1.5.6)
pg_query (~> 5.1.0)
png_quantizator (~> 0.2.1)
premailer-rails (~> 1.10.3)

View File

@ -3,10 +3,18 @@
module Organizations
class OrganizationsController < ApplicationController
include PreviewMarkdown
include FiltersEvents
DEFAULT_RESOURCE_LIMIT = 1000
feature_category :cell
skip_before_action :authenticate_user!, only: [:show, :groups_and_projects]
before_action :event_filter, only: [:activity]
before_action :authorize_read_organization!, only: [:activity, :show, :groups_and_projects]
skip_before_action :authenticate_user!, only: [:activity, :show, :groups_and_projects]
urgency :low, [:activity]
def index; end
@ -14,16 +22,37 @@ module Organizations
authorize_create_organization!
end
def show
authorize_read_organization!
def show; end
def activity
respond_to do |format|
format.html
format.json do
load_events
@events = @events.select { |event| event.visible_to_user?(current_user) }
render json: ::Profile::EventSerializer.new(current_user: current_user).represent(@events)
end
end
end
def groups_and_projects
authorize_read_organization!
end
def groups_and_projects; end
def users
authorize_read_organization_user!
end
private
def load_events
@events = EventCollection.new(
organization.projects.limit(DEFAULT_RESOURCE_LIMIT).sorted_by_activity,
offset: params[:offset].to_i,
filter: event_filter,
groups: organization.groups.limit(DEFAULT_RESOURCE_LIMIT)
).to_a.map(&:present)
Events::RenderService.new(current_user).execute(@events)
end
end
end

View File

@ -115,43 +115,12 @@ module Ci
validates :ref, presence: true
scope :unstarted, -> { where(runner_id: nil) }
scope :with_any_artifacts, -> do
where('EXISTS (?)',
Ci::JobArtifact.select(1).where("#{Ci::Build.quoted_table_name}.id = #{Ci::JobArtifact.quoted_table_name}.job_id")
)
end
scope :with_downloadable_artifacts, -> do
where('EXISTS (?)',
Ci::JobArtifact.select(1)
.where("#{Ci::Build.quoted_table_name}.id = #{Ci::JobArtifact.quoted_table_name}.job_id")
.where(file_type: Ci::JobArtifact::DOWNLOADABLE_TYPES)
)
end
scope :with_erasable_artifacts, -> do
where('EXISTS (?)',
Ci::JobArtifact.select(1)
.where("#{Ci::Build.quoted_table_name}.id = #{Ci::JobArtifact.quoted_table_name}.job_id")
.where(file_type: Ci::JobArtifact.erasable_file_types)
)
end
scope :in_pipelines, ->(pipelines) do
where(pipeline: pipelines)
end
scope :with_existing_job_artifacts, ->(query) do
where('EXISTS (?)', ::Ci::JobArtifact.select(1).where("#{Ci::Build.quoted_table_name}.id = #{Ci::JobArtifact.quoted_table_name}.job_id").merge(query))
end
scope :with_any_artifacts, -> { where_exists(Ci::JobArtifact.scoped_build) }
scope :with_downloadable_artifacts, -> { where_exists(Ci::JobArtifact.scoped_build.downloadable) }
scope :with_erasable_artifacts, -> { where_exists(Ci::JobArtifact.scoped_build.erasable) }
scope :with_existing_job_artifacts, ->(query) { where_exists(Ci::JobArtifact.scoped_build.erasable.merge(query)) }
scope :without_archived_trace, -> { where_not_exists(Ci::JobArtifact.scoped_build.trace) }
scope :with_artifacts, ->(artifact_scope) do
with_existing_job_artifacts(artifact_scope)
.eager_load_job_artifacts
end
scope :with_artifacts, ->(artifact_scope) { with_existing_job_artifacts(artifact_scope).eager_load_job_artifacts }
scope :eager_load_job_artifacts, -> { includes(:job_artifacts) }
scope :eager_load_tags, -> { includes(:tags) }

View File

@ -311,8 +311,8 @@ class IssuableBaseService < ::BaseContainerService
GraphqlTriggers.issuable_description_updated(issuable)
end
def update(issuable) # rubocop:disable Metrics/AbcSize -- remove with the FF `use_primary_for_update_computations`
::Gitlab::Database::LoadBalancing::Session.current.use_primary! if Feature.enabled?(:use_primary_for_update_computations, issuable.try(:resource_parent))
def update(issuable)
::Gitlab::Database::LoadBalancing::Session.current.use_primary!
old_associations = associations_before_update(issuable)

View File

@ -0,0 +1 @@
- page_title _("Activity")

View File

@ -1,10 +0,0 @@
---
name: use_primary_for_update_computations
feature_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/416207
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/145792
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/443293
milestone: '16.10'
group: group::project management
type: gitlab_com_derisk
default_enabled: false

View File

@ -1,16 +1,12 @@
# frozen_string_literal: true
resources(
:organizations,
only: [:show, :index, :new],
param: :organization_path,
module: :organizations
) do
resources(:organizations, only: [:show, :index, :new], param: :organization_path, module: :organizations) do
collection do
post :preview_markdown
end
member do
get :activity
get :groups_and_projects
get :users

View File

@ -0,0 +1,9 @@
---
migration_job_name: BackfillArchivedAndTraversalIdsToVulnerabilityReads
description: Backfill project.archived and project.namespace.traversal_ids values to the denormalized columns of the same name on vulnerability_reads
feature_category: vulnerability_management
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144765
milestone: '16.10'
queued_migration_version: 20240214163238
finalize_after: '2024-03-15'
finalized_by:

View File

@ -0,0 +1,32 @@
# 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 EnsureMemberRolesNamesUniq < Gitlab::Database::Migration[2.2]
milestone '16.10'
disable_ddl_transaction!
restrict_gitlab_migration gitlab_schema: :gitlab_main
def up
sql = <<~SQL
UPDATE member_roles SET name = CONCAT(name, ' (', id, ')')
WHERE id IN (
SELECT mr.id FROM member_roles mr
WHERE EXISTS (SELECT mr_duplicates.id
FROM member_roles mr_duplicates
WHERE mr_duplicates.name = mr.name
AND (
mr_duplicates.namespace_id = mr.namespace_id
OR (mr_duplicates.namespace_id IS NULL AND mr.namespace_id IS NULL)
)
AND mr_duplicates.id < mr.id))
SQL
execute(sql)
end
def down; end
end

View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
class QueueBackfillArchivedAndTraversalIdsToVulnerabilityReads < Gitlab::Database::Migration[2.2]
milestone '16.10'
restrict_gitlab_migration gitlab_schema: :gitlab_main
MIGRATION = "BackfillArchivedAndTraversalIdsToVulnerabilityReads"
DELAY_INTERVAL = 2.minutes
BATCH_SIZE = 10_000
SUB_BATCH_SIZE = 100
def up
queue_batched_background_migration(
MIGRATION,
:vulnerability_reads,
:id,
job_interval: DELAY_INTERVAL,
batch_size: BATCH_SIZE,
sub_batch_size: SUB_BATCH_SIZE
)
end
def down
delete_batched_background_migration(MIGRATION, :vulnerability_reads, :id, [])
end
end

View File

@ -0,0 +1,21 @@
# frozen_string_literal: true
class AddNameUniqueIndexToMemberRoles < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
milestone '16.10'
INDEX_WITH_NAMESPACE_NAME = 'index_member_roles_on_namespace_id_name_unique'
INDEX_NO_NAMESPACE_NAME = 'index_member_roles_on_name_unique'
def up
add_concurrent_index :member_roles, [:namespace_id, :name], name: INDEX_WITH_NAMESPACE_NAME,
unique: true, where: 'namespace_id IS NOT NULL'
add_concurrent_index :member_roles, [:name], name: INDEX_NO_NAMESPACE_NAME,
unique: true, where: 'namespace_id IS NULL'
end
def down
remove_concurrent_index_by_name :member_roles, INDEX_WITH_NAMESPACE_NAME
remove_concurrent_index_by_name :member_roles, INDEX_NO_NAMESPACE_NAME
end
end

View File

@ -0,0 +1 @@
3eb5dbfdae669848eaf552cd6eb097fb139b41d18b614095ac8de67737b7c796

View File

@ -0,0 +1 @@
3b6c1f5d12ab7c97d8bc72064b1ef66b64ba8131c8a37a368d0ea58472e60fc8

View File

@ -0,0 +1 @@
e73649f6285a6ede1741169c62eecb474da9ddaa3c8c03e4f571d4621e3471d2

View File

@ -25556,8 +25556,12 @@ CREATE INDEX index_member_approval_on_requested_by_id ON member_approvals USING
CREATE INDEX index_member_approval_on_reviewed_by_id ON member_approvals USING btree (reviewed_by_id);
CREATE UNIQUE INDEX index_member_roles_on_name_unique ON member_roles USING btree (name) WHERE (namespace_id IS NULL);
CREATE INDEX index_member_roles_on_namespace_id ON member_roles USING btree (namespace_id);
CREATE UNIQUE INDEX index_member_roles_on_namespace_id_name_unique ON member_roles USING btree (namespace_id, name) WHERE (namespace_id IS NOT NULL);
CREATE INDEX index_member_roles_on_occupies_seat ON member_roles USING btree (occupies_seat);
CREATE INDEX index_members_on_access_level ON members USING btree (access_level);

View File

@ -1044,7 +1044,9 @@ See the limits in the [Add a design to an issue](../user/project/issues/design_m
### Max push size
The maximum allowed [push size](../administration/settings/account_and_limit_settings.md#max-push-size) is set to 5 GB.
The maximum allowed [push size](../administration/settings/account_and_limit_settings.md#max-push-size).
Not set by default on self-managed instances. For GitLab.com, see [Account and limit settings](../user/gitlab_com/index.md#account-and-limit-settings)
### Webhooks and Project Services

View File

@ -254,6 +254,7 @@ the default value [is the same as for self-managed instances](../../administrati
| [Maximum download file size when importing from source GitLab instances by direct transfer](../../administration/settings/import_and_export_settings.md#maximum-download-file-size-for-imports-by-direct-transfer) | 5 GiB |
| Maximum attachment size | 100 MiB |
| [Maximum decompressed file size for imported archives](../../administration/settings/import_and_export_settings.md#maximum-decompressed-file-size-for-imported-archives) | 25 GiB |
| [Maximum push size](../../administration/settings/account_and_limit_settings.md#max-push-size) | 5 GB |
If you are near or over the repository size limit, you can either:

View File

@ -0,0 +1,34 @@
# frozen_string_literal: true
module Gitlab
module BackgroundMigration
class BackfillArchivedAndTraversalIdsToVulnerabilityReads < BatchedMigrationJob
operation_name :backfill_archived_and_traversal_ids_in_vulnerability_reads_table
feature_category :vulnerability_management
def perform
each_sub_batch do |sub_batch|
connection.exec_update(update_sql(sub_batch))
end
end
private
def update_sql(sub_batch)
<<~SQL
UPDATE
vulnerability_reads
SET
traversal_ids = namespaces.traversal_ids,
archived = projects.archived
FROM
projects
INNER JOIN namespaces ON namespaces.id = projects.namespace_id
WHERE
vulnerability_reads.id IN (#{sub_batch.select(:id).to_sql}) AND
vulnerability_reads.project_id = projects.id
SQL
end
end
end
end

View File

@ -9,3 +9,5 @@ module Gitlab
end
end
end
Gitlab::ClickHouse.prepend_mod_with('Gitlab::ClickHouse')

View File

@ -21,12 +21,25 @@ module Sidebars
override :configure_menu_items
def configure_menu_items
activity_menu_item
groups_and_projects_menu_item
users_menu_item
end
private
def activity_menu_item
add_item(
::Sidebars::MenuItem.new(
title: _('Activity'),
link: activity_organization_path(context.container),
super_sidebar_parent: ::Sidebars::Organizations::Menus::ManageMenu,
active_routes: { path: 'organizations/organizations#activity' },
item_id: :organization_activity
)
)
end
def groups_and_projects_menu_item
add_item(
::Sidebars::MenuItem.new(

View File

@ -3,7 +3,7 @@
source 'https://rubygems.org'
gem 'gitlab-qa', '~> 14', '>= 14.2.1', require: 'gitlab/qa'
gem 'gitlab_quality-test_tooling', '~> 1.11.0', require: false
gem 'gitlab_quality-test_tooling', '~> 1.17.0', require: false
gem 'gitlab-utils', path: '../gems/gitlab-utils'
gem 'activesupport', '~> 7.0.8.1' # This should stay in sync with the root's Gemfile
gem 'allure-rspec', '~> 2.24.1'

View File

@ -128,14 +128,15 @@ GEM
rainbow (>= 3, < 4)
table_print (= 1.5.7)
zeitwerk (>= 2, < 3)
gitlab_quality-test_tooling (1.11.0)
activesupport (>= 6.1, < 7.2)
gitlab_quality-test_tooling (1.17.0)
activesupport (>= 6.1, < 7.1)
amatch (~> 0.4.1)
gitlab (~> 4.19)
http (~> 5.0)
nokogiri (~> 1.10)
parallel (>= 1, < 2)
rainbow (>= 3, < 4)
rspec-parameterized (~> 1.0.0)
table_print (= 1.5.7)
zeitwerk (>= 2, < 3)
google-apis-compute_v1 (0.51.0)
@ -296,7 +297,8 @@ GEM
ruby-debug-ide (0.7.3)
rake (>= 0.8.1)
ruby2_keywords (0.0.5)
ruby_parser (3.20.3)
ruby_parser (3.21.0)
racc (~> 1.5)
sexp_processor (~> 4.16)
rubyzip (2.3.2)
sawyer (0.9.2)
@ -307,7 +309,7 @@ GEM
rexml (~> 3.2, >= 3.2.5)
rubyzip (>= 1.2.2, < 3.0)
websocket (~> 1.0)
sexp_processor (4.17.0)
sexp_processor (4.17.1)
signet (0.17.0)
addressable (~> 2.8)
faraday (>= 0.17.5, < 3.a)
@ -360,7 +362,7 @@ DEPENDENCIES
fog-google (~> 1.19)
gitlab-qa (~> 14, >= 14.2.1)
gitlab-utils!
gitlab_quality-test_tooling (~> 1.11.0)
gitlab_quality-test_tooling (~> 1.17.0)
influxdb-client (~> 3.1)
knapsack (~> 4.0)
nokogiri (~> 1.16, >= 1.16.2)

View File

@ -128,6 +128,14 @@ module QA
page.within_frame(iframe, &block)
end
def within_vscode_duo_chat(&block)
within_vscode_editor do
within_frame(all(:frame, class: 'webview', visible: false).last) do
within_frame(:frame, &block)
end
end
end
def switch_to_original_window
page.driver.browser.switch_to.window(page.driver.browser.window_handles.first)
end
@ -156,7 +164,7 @@ module QA
end
Support::WaitForRequests.wait_for_requests(finish_loading_wait: 30)
Support::Waiter.wait_until(max_duration: 10, reload_page: page, retry_on_exception: true) do
Support::Waiter.wait_until(max_duration: 60, reload_page: page, retry_on_exception: true) do
within_vscode_editor do
# Check for webide file_explorer element
has_file_explorer?
@ -304,6 +312,12 @@ module QA
end
end
def open_duo_chat
within_vscode_editor do
click_element('a[aria-label="GitLab Duo Chat"]', wait: 60)
end
end
private
def create_item(click_item, item_name)

View File

@ -0,0 +1,137 @@
# frozen_string_literal: true
require 'spec_helper'
RSpec.describe Gitlab::BackgroundMigration::BackfillArchivedAndTraversalIdsToVulnerabilityReads,
feature_category: :vulnerability_management do
let(:vulnerability_identifiers) { table(:vulnerability_identifiers) }
let(:vulnerability_findings) { table(:vulnerability_occurrences) }
let(:vulnerabilities) { table(:vulnerabilities) }
let(:vulnerability_reads) { table(:vulnerability_reads) }
let(:projects) { table(:projects) }
let(:users) { table(:users) }
let(:namespaces) { table(:namespaces) }
let(:scanners) { table(:vulnerability_scanners) }
let(:user) { users.create!(username: 'john_doe', email: 'johndoe@gitlab.com', projects_limit: 1) }
let(:args) do
min, max = vulnerability_reads.pick('MIN(id)', 'MAX(id)')
{
start_id: min,
end_id: max,
batch_table: 'vulnerability_reads',
batch_column: 'id',
sub_batch_size: 100,
pause_ms: 0,
connection: ApplicationRecord.connection
}
end
let!(:group_namespace) do
namespaces.create!(
name: 'gitlab-org',
path: 'gitlab-org',
type: 'Group'
).tap { |namespace| namespace.update!(traversal_ids: [namespace.id]) }
end
let!(:other_group_namespace) do
namespaces.create!(
name: 'gitlab-com',
path: 'gitlab-com',
type: 'Group'
).tap { |namespace| namespace.update!(traversal_ids: [namespace.id]) }
end
let!(:project) { create_project('gitlab', group_namespace) }
let!(:other_project) { create_project('www-gitlab-com', other_group_namespace) }
subject(:perform_migration) { described_class.new(**args).perform }
before do
[project, other_project].each do |p|
create_vulnerability_read(project_id: p.id)
end
end
it 'backfills traversal_ids and archived', :aggregate_failures do
perform_migration
vulnerability_reads.find_each do |vulnerability_read|
project = projects.find(vulnerability_read.project_id)
namespace = namespaces.find(project.namespace_id)
expect(vulnerability_read.traversal_ids).to eq(namespace.traversal_ids)
expect(vulnerability_read.archived).to eq(project.archived)
end
end
def create_vulnerability_read(project_id:)
scanner = scanners.create!(project_id: project_id, external_id: 'foo', name: 'bar')
identifier = vulnerability_identifiers.create!(
project_id: project_id,
external_id: "CVE-2018-1234",
external_type: "CVE",
name: "CVE-2018-1234",
fingerprint: SecureRandom.hex(20)
)
finding = vulnerability_findings.create!(
project_id: project_id,
scanner_id: scanner.id,
severity: 5, # medium
confidence: 2, # unknown,
report_type: 99, # generic
primary_identifier_id: identifier.id,
project_fingerprint: SecureRandom.hex(20),
location_fingerprint: SecureRandom.hex(20),
uuid: SecureRandom.uuid,
name: "CVE-2018-1234",
raw_metadata: "{}",
metadata_version: "test:1.0"
)
vulnerability = vulnerabilities.create!(
project_id: project_id,
author_id: user.id,
title: 'Vulnerability 1',
severity: 1,
confidence: 1,
report_type: 1,
state: 1,
finding_id: finding.id
)
vulnerability_reads.create!(
vulnerability_id: vulnerability.id,
namespace_id: project.namespace_id,
project_id: project_id,
scanner_id: scanner.id,
report_type: 1,
severity: 1,
state: 1,
uuid: SecureRandom.uuid,
archived: false,
traversal_ids: []
)
end
def create_project(name, group)
project_namespace = namespaces.create!(
name: name,
path: name,
type: 'Project'
)
projects.create!(
namespace_id: group.id,
project_namespace_id: project_namespace.id,
name: name,
path: name,
archived: true
)
end
end

View File

@ -17,6 +17,12 @@ RSpec.describe Sidebars::Organizations::Menus::ManageMenu, feature_category: :na
describe 'Menu items' do
subject(:item) { menu.renderable_items.find { |e| e.item_id == item_id } }
describe 'Activity' do
let(:item_id) { :organization_activity }
it { is_expected.not_to be_nil }
end
describe 'Groups and projects' do
let(:item_id) { :organization_groups_and_projects }

View File

@ -0,0 +1,49 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe EnsureMemberRolesNamesUniq, feature_category: :permissions do
let(:migration) { described_class.new }
let(:namespaces) { table(:namespaces) }
let(:member_roles) { table(:member_roles) }
let(:namespace) { namespaces.create!(name: 'foo', path: 'foo') }
let!(:member_role_1) { member_roles.create!(name: 'foo', namespace_id: namespace.id, base_access_level: 10) }
let!(:member_role_2) { member_roles.create!(name: 'other', namespace_id: namespace.id, base_access_level: 10) }
let!(:member_role_3) { member_roles.create!(name: 'other', namespace_id: nil, base_access_level: 10) }
let!(:member_role_4) { member_roles.create!(name: 'no namespace', namespace_id: nil, base_access_level: 10) }
let!(:member_role_1_duplicated) do
member_roles.create!(name: 'foo', namespace_id: namespace.id, base_access_level: 10)
end
let!(:member_role_4_duplicated) do
member_roles.create!(name: 'no namespace', namespace_id: nil, base_access_level: 10)
end
describe '#up' do
it 'updates the duplicated names with higher id', :aggregate_failures do
migration.up
expect(member_role_1.reload.name).to eq('foo')
expect(member_role_1_duplicated.reload.name).to eq("foo (#{member_role_1_duplicated.id})")
expect(member_role_2.reload.name).to eq('other')
expect(member_role_3.reload.name).to eq('other')
expect(member_role_4.reload.name).to eq('no namespace')
expect(member_role_4_duplicated.reload.name).to eq("no namespace (#{member_role_4_duplicated.id})")
migration.down
migration.up
expect(member_role_1.reload.name).to eq('foo')
expect(member_role_1_duplicated.reload.name).to eq("foo (#{member_role_1_duplicated.id})")
expect(member_role_2.reload.name).to eq('other')
expect(member_role_3.reload.name).to eq('other')
expect(member_role_4.reload.name).to eq('no namespace')
expect(member_role_4_duplicated.reload.name).to eq("no namespace (#{member_role_4_duplicated.id})")
end
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
require 'spec_helper'
require_migration!
RSpec.describe QueueBackfillArchivedAndTraversalIdsToVulnerabilityReads, feature_category: :vulnerability_management do
let!(:batched_migration) { described_class::MIGRATION }
it 'schedules a new batched migration' do
reversible_migration do |migration|
migration.before -> {
expect(batched_migration).not_to have_scheduled_batched_migration
}
migration.after -> {
expect(batched_migration).to have_scheduled_batched_migration(
table_name: :vulnerability_reads,
column_name: :id,
interval: described_class::DELAY_INTERVAL,
batch_size: described_class::BATCH_SIZE,
sub_batch_size: described_class::SUB_BATCH_SIZE
)
}
end
end
end

View File

@ -96,6 +96,47 @@ RSpec.describe Organizations::OrganizationsController, feature_category: :cell d
it_behaves_like 'controller action that does not require authentication'
end
describe 'GET #activity' do
subject(:gitlab_request) { get activity_organization_path(organization) }
it_behaves_like 'controller action that does not require authentication'
context 'when requested in json format' do
let_it_be(:user) { create(:organization_user, organization: organization).user }
context 'without activities' do
before do
sign_in(user)
end
it 'renders empty array' do
get activity_organization_path(organization, format: :json)
expect(response.media_type).to eq('application/json')
expect(json_response).to be_an(Array)
expect(json_response.size).to eq(0)
end
end
context 'with activities' do
let_it_be(:project) { create(:project, organization: organization) }
before_all do
project.add_developer(user)
sign_in(user)
end
it 'loads events' do
get activity_organization_path(organization, format: :json)
expect(response.media_type).to eq('application/json')
expect(json_response).to be_an(Array)
expect(json_response.size).to eq(1)
end
end
end
end
describe 'GET #groups_and_projects' do
subject(:gitlab_request) { get groups_and_projects_organization_path(organization) }

View File

@ -20,6 +20,11 @@ RSpec.describe Organizations::OrganizationsController, :routing, feature_categor
.to route_to('organizations/organizations#index')
end
it 'routes to #activity' do
expect(get("/-/organizations/#{organization.path}/activity"))
.to route_to('organizations/organizations#activity', organization_path: organization.path)
end
it 'routes to #groups_and_projects' do
expect(get("/-/organizations/#{organization.path}/groups_and_projects"))
.to route_to('organizations/organizations#groups_and_projects', organization_path: organization.path)