Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
606d784b5b
commit
ba7e516994
|
|
@ -1 +1 @@
|
|||
c29c5ba968d141237000185734baa95e122db80b
|
||||
1a16fa05c2645a0abba4e2f028e1fdbe5d85be2f
|
||||
|
|
|
|||
|
|
@ -180,7 +180,6 @@ export default {
|
|||
return {
|
||||
'is-replying gl-pt-0!': this.isReplying,
|
||||
'internal-note': this.isDiscussionInternal,
|
||||
'public-note': !this.isDiscussionInternal,
|
||||
'gl-pt-0!': !this.discussion.diff_discussion && this.isReplying,
|
||||
};
|
||||
},
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import { padWithZeros } from '~/lib/utils/datetime/date_format_utility';
|
||||
import { isValidDate, differenceInMinutes } from '~/lib/utils/datetime_utility';
|
||||
import { mergeUrlParams } from '~/lib/utils/url_utility';
|
||||
|
||||
import {
|
||||
CUSTOM_DATE_RANGE_OPTION,
|
||||
|
|
@ -193,3 +194,9 @@ export function isTracingDateRangeOutOfBounds({ value, startDate, endDate }) {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function urlWithStringifiedPayloadParam(url, payload, paramName) {
|
||||
return mergeUrlParams({ [paramName]: JSON.stringify(payload) }, url, {
|
||||
spreadArrays: true,
|
||||
});
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@
|
|||
background-color: $line-target-blue;
|
||||
}
|
||||
|
||||
+ .public-note.discussion-reply-holder {
|
||||
+ .discussion-reply-holder {
|
||||
padding-top: $gl-padding-12 !important;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,10 +27,20 @@ module Ci
|
|||
record = find_by(build_id: build_id, partition_id: partition_id)
|
||||
return record if record
|
||||
|
||||
upsert({ build_id: build_id, partition_id: partition_id }, unique_by: :build_id)
|
||||
upsert({ build_id: build_id, partition_id: partition_id }, unique_by: unique_by_columns_for_upsert)
|
||||
find_by!(build_id: build_id, partition_id: partition_id)
|
||||
end
|
||||
|
||||
# Temporary fix to correctly identify an unique index for upsert
|
||||
# should be replaced with `%w[build_id partition_id]` in %17.5
|
||||
def self.unique_by_columns_for_upsert
|
||||
unique_indexes = connection.schema_cache.indexes(table_name).select(&:unique)
|
||||
columns = %w[partition_id build_id]
|
||||
return columns if unique_indexes.any? { |index| index.columns == columns }
|
||||
|
||||
columns.reverse
|
||||
end
|
||||
|
||||
# The job is retried around 5 times during the 7 days retention period for
|
||||
# trace chunks as defined in `Ci::BuildTraceChunks::RedisBase::CHUNK_REDIS_TTL`
|
||||
def can_attempt_archival_now?
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ module VirtualRegistries
|
|||
prevent(*create_read_update_admin_destroy(:virtual_registry))
|
||||
end
|
||||
|
||||
rule { can?(:read_group) }.policy do
|
||||
rule { group.guest | admin | group.has_projects }.policy do
|
||||
enable :read_virtual_registry
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -60,16 +60,13 @@ module WorkItems
|
|||
def interpret_quick_actions!(work_item, widget_params, attributes = {})
|
||||
return unless work_item.has_widget?(:description)
|
||||
|
||||
widget_description_param = widget_params[::WorkItems::Widgets::Description.api_symbol]
|
||||
return unless widget_description_param
|
||||
description_widget_params = widget_params[::WorkItems::Widgets::Description.api_symbol]
|
||||
return unless description_widget_params
|
||||
|
||||
merge_quick_actions_into_params!(work_item, params: widget_description_param)
|
||||
merge_quick_actions_into_params!(work_item, params: description_widget_params)
|
||||
|
||||
# cleanup `description` param so that it is not passed into common params after transform_quick_action_params
|
||||
quick_action_params = widget_description_param.dup
|
||||
quick_action_params.delete(:description)
|
||||
|
||||
parsed_params = work_item.transform_quick_action_params(quick_action_params)
|
||||
# exclude `description` param so that it is not passed into common params after transform_quick_action_params
|
||||
parsed_params = work_item.transform_quick_action_params(description_widget_params.except(:description))
|
||||
|
||||
widget_params.merge!(parsed_params[:widgets])
|
||||
attributes.merge!(parsed_params[:common])
|
||||
|
|
|
|||
|
|
@ -217,42 +217,24 @@ class IssuableBaseService < ::BaseContainerService
|
|||
# If the description has not been edited, then just remove any quick actions
|
||||
# in the current description.
|
||||
def merge_quick_actions_into_params!(issuable, params:, only: nil)
|
||||
interpret_params = quick_action_options
|
||||
unedited_description = issuable.description
|
||||
edited_description = params.fetch(:description, issuable.description)
|
||||
target_description = params.fetch(:description, issuable.description)
|
||||
|
||||
target_text = issuable.new_record? || params[:description] ? edited_description : unedited_description
|
||||
|
||||
# only set the original_text if we're editing the issuable
|
||||
original_text = params[:description] && !issuable.new_record? ? unedited_description : nil
|
||||
|
||||
sanitized_description, sanitized_command_params = interpret_quick_actions(target_text, issuable, params: interpret_params, only: only, original_text: original_text)
|
||||
|
||||
unless issuable.new_record? || params[:description]
|
||||
edited_description = unedited_description
|
||||
sanitized_command_params = nil
|
||||
end
|
||||
description, command_params = QuickActions::InterpretService.new(
|
||||
container: container,
|
||||
current_user: current_user,
|
||||
params: quick_action_options
|
||||
).execute_with_original_text(target_description, issuable, only: only, original_text: issuable.description_was)
|
||||
|
||||
# Avoid a description already set on an issuable to be overwritten by a nil
|
||||
params[:description] = sanitized_description if sanitized_description && sanitized_description != edited_description
|
||||
params[:description] = description if description && description != target_description
|
||||
|
||||
params.merge!(sanitized_command_params) if sanitized_command_params
|
||||
params.merge!(command_params)
|
||||
end
|
||||
|
||||
def quick_action_options
|
||||
{}
|
||||
end
|
||||
|
||||
def interpret_quick_actions(new_text, issuable, params:, only:, original_text: nil)
|
||||
sanitized_new_text, new_command_params = QuickActions::InterpretService.new(
|
||||
container: container,
|
||||
current_user: current_user,
|
||||
params: params
|
||||
).execute_with_original_text(new_text, issuable, only: only, original_text: original_text)
|
||||
|
||||
[sanitized_new_text, new_command_params]
|
||||
end
|
||||
|
||||
def create(issuable, skip_system_notes: false)
|
||||
initialize_callbacks!(issuable)
|
||||
|
||||
|
|
|
|||
|
|
@ -212,6 +212,10 @@ dast_site_validations:
|
|||
- table: projects
|
||||
column: project_id
|
||||
on_delete: async_delete
|
||||
dast_sites:
|
||||
- table: projects
|
||||
column: project_id
|
||||
on_delete: async_delete
|
||||
deployment_clusters:
|
||||
- table: clusters
|
||||
column: cluster_id
|
||||
|
|
|
|||
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateCiFinishedPipelinesHourly < ClickHouse::Migration
|
||||
def up
|
||||
execute <<~SQL
|
||||
CREATE TABLE IF NOT EXISTS ci_finished_pipelines_hourly
|
||||
(
|
||||
`path` String DEFAULT '0/',
|
||||
|
||||
`status` LowCardinality(String) DEFAULT '',
|
||||
`source` LowCardinality(String) DEFAULT '',
|
||||
`ref` String DEFAULT '',
|
||||
`started_at_bucket` DateTime64(6, 'UTC') DEFAULT now64(),
|
||||
|
||||
count_pipelines AggregateFunction(count)
|
||||
)
|
||||
ENGINE = AggregatingMergeTree()
|
||||
ORDER BY (started_at_bucket, path, status, source, ref)
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
execute <<~SQL
|
||||
DROP TABLE IF EXISTS ci_finished_pipelines_hourly
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreateCiFinishedPipelinesHourlyMv < ClickHouse::Migration
|
||||
def up
|
||||
execute <<~SQL
|
||||
CREATE MATERIALIZED VIEW IF NOT EXISTS ci_finished_pipelines_hourly_mv
|
||||
TO ci_finished_pipelines_hourly
|
||||
AS
|
||||
SELECT
|
||||
path,
|
||||
status,
|
||||
source,
|
||||
ref,
|
||||
toStartOfInterval(started_at, INTERVAL 1 hour) AS started_at_bucket,
|
||||
|
||||
countState() AS count_pipelines
|
||||
FROM ci_finished_pipelines
|
||||
GROUP BY path, status, source, ref, started_at_bucket
|
||||
SQL
|
||||
end
|
||||
|
||||
def down
|
||||
execute <<~SQL
|
||||
DROP VIEW ci_finished_pipelines_hourly_mv
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
|
@ -7,7 +7,7 @@ feature_categories:
|
|||
description: Site to run dast scan on
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/36659
|
||||
milestone: '13.2'
|
||||
gitlab_schema: gitlab_main_cell
|
||||
gitlab_schema: gitlab_sec
|
||||
allow_cross_foreign_keys:
|
||||
- gitlab_main_clusterwide
|
||||
sharding_key:
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
---
|
||||
table_name: p_ci_build_trace_metadata
|
||||
classes:
|
||||
- Ci::BuildTraceMetadata
|
||||
feature_categories:
|
||||
- continuous_integration
|
||||
description: Routing table for ci_build_trace_metadata
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/162310
|
||||
milestone: '14.2'
|
||||
gitlab_schema: gitlab_ci
|
||||
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/458479
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class CreatePCiBuildTraceMetadata < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.4'
|
||||
|
||||
# rubocop:disable Migration/EnsureFactoryForTable -- No factory needed
|
||||
def change
|
||||
create_table(:p_ci_build_trace_metadata, primary_key: [:build_id, :partition_id],
|
||||
options: 'PARTITION BY LIST (partition_id)', if_not_exists: true) do |t|
|
||||
t.bigint :build_id, null: false
|
||||
t.bigint :partition_id, null: false
|
||||
t.bigint :trace_artifact_id
|
||||
t.datetime_with_timezone :last_archival_attempt_at
|
||||
t.datetime_with_timezone :archived_at
|
||||
t.integer :archival_attempts, default: 0, null: false, limit: 2
|
||||
t.binary :checksum
|
||||
t.binary :remote_checksum
|
||||
|
||||
t.index :trace_artifact_id
|
||||
end
|
||||
end
|
||||
# rubocop:enable Migration/EnsureFactoryForTable -- No factory needed
|
||||
end
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class DropIdxVulnerabilityOccurrencesDedup < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.4'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
TABLE = :vulnerability_occurrences
|
||||
INDEX_NAME = 'index_vulnerability_occurrences_deduplication'
|
||||
COLUMNS = %i[project_id report_type project_fingerprint]
|
||||
|
||||
def up
|
||||
remove_concurrent_index TABLE, COLUMNS, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_index TABLE, COLUMNS, name: INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveProjectsDastSitesProjectIdFk < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.4'
|
||||
disable_ddl_transaction!
|
||||
|
||||
FOREIGN_KEY_NAME = "fk_rails_6febb6ea9c"
|
||||
|
||||
def up
|
||||
with_lock_retries do
|
||||
remove_foreign_key_if_exists(:dast_sites, :projects,
|
||||
name: FOREIGN_KEY_NAME, reverse_lock_order: true)
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
add_concurrent_foreign_key(:dast_sites, :projects,
|
||||
name: FOREIGN_KEY_NAME, column: :project_id,
|
||||
target_column: :id, on_delete: :cascade)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class FkCiBuildsCiBuildTraceMetadata < Gitlab::Database::Migration[2.2]
|
||||
include Gitlab::Database::PartitioningMigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
milestone '17.4'
|
||||
|
||||
def up
|
||||
add_concurrent_partitioned_foreign_key(
|
||||
:p_ci_build_trace_metadata, :p_ci_builds,
|
||||
name: :fk_rails_aebc78111f_p,
|
||||
column: [:partition_id, :build_id],
|
||||
target_column: [:partition_id, :id],
|
||||
on_update: :cascade,
|
||||
on_delete: :cascade,
|
||||
reverse_lock_order: true
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key_if_exists :p_ci_build_trace_metadata, :p_ci_builds,
|
||||
name: :fk_rails_aebc78111f_p, reverse_lock_order: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class FkCiJobsArtifactsCiBuildTraceMetadata < Gitlab::Database::Migration[2.2]
|
||||
include Gitlab::Database::PartitioningMigrationHelpers
|
||||
|
||||
disable_ddl_transaction!
|
||||
milestone '17.4'
|
||||
|
||||
def up
|
||||
add_concurrent_partitioned_foreign_key(
|
||||
:p_ci_build_trace_metadata, :p_ci_job_artifacts,
|
||||
name: :fk_21d25cac1a_p,
|
||||
column: [:partition_id, :trace_artifact_id],
|
||||
target_column: [:partition_id, :id],
|
||||
on_update: :cascade,
|
||||
on_delete: :cascade,
|
||||
reverse_lock_order: true
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key_if_exists :p_ci_build_trace_metadata, :p_ci_job_artifacts,
|
||||
name: :fk_21d25cac1a_p, reverse_lock_order: true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class PartitionCiBuildTraceMetadata < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.4'
|
||||
disable_ddl_transaction!
|
||||
|
||||
# rubocop:disable Migration/SchemaAdditionMethodsNoPost -- recreates the table in the same transaction
|
||||
def up
|
||||
with_lock_retries do
|
||||
lock_tables(:p_ci_builds, :p_ci_job_artifacts, :ci_build_trace_metadata, mode: :access_exclusive)
|
||||
|
||||
drop_table(:ci_build_trace_metadata)
|
||||
|
||||
connection.execute(<<~SQL)
|
||||
CREATE TABLE IF NOT EXISTS ci_build_trace_metadata
|
||||
PARTITION OF p_ci_build_trace_metadata
|
||||
FOR VALUES IN (100, 101, 102);
|
||||
SQL
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
drop_table(:ci_build_trace_metadata, if_exists: true)
|
||||
|
||||
create_table(:ci_build_trace_metadata, id: false, if_not_exists: true) do |t|
|
||||
t.bigint :build_id, null: false, default: nil, primary_key: true
|
||||
t.bigint :trace_artifact_id
|
||||
t.integer :archival_attempts, default: 0, null: false, limit: 2
|
||||
t.binary :checksum
|
||||
t.binary :remote_checksum
|
||||
t.datetime_with_timezone :last_archival_attempt_at
|
||||
t.datetime_with_timezone :archived_at
|
||||
t.bigint :partition_id, null: false
|
||||
|
||||
t.index [:trace_artifact_id, :partition_id],
|
||||
name: :index_ci_build_trace_metadata_on_trace_artifact_id_partition_id
|
||||
t.index [:partition_id, :build_id], unique: true,
|
||||
name: :index_ci_build_trace_metadata_on_partition_id_build_id
|
||||
end
|
||||
|
||||
add_concurrent_foreign_key(
|
||||
:ci_build_trace_metadata, :p_ci_builds,
|
||||
column: [:partition_id, :build_id],
|
||||
target_column: [:partition_id, :id],
|
||||
on_update: :cascade,
|
||||
on_delete: :cascade,
|
||||
reverse_lock_order: true,
|
||||
name: :fk_rails_aebc78111f_p
|
||||
)
|
||||
|
||||
add_concurrent_foreign_key(
|
||||
:ci_build_trace_metadata, :p_ci_job_artifacts,
|
||||
column: [:partition_id, :trace_artifact_id],
|
||||
target_column: [:partition_id, :id],
|
||||
on_update: :cascade,
|
||||
on_delete: :cascade,
|
||||
reverse_lock_order: true,
|
||||
name: :fk_21d25cac1a_p
|
||||
)
|
||||
end
|
||||
# rubocop:enable Migration/SchemaAdditionMethodsNoPost
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
519360df6518a135db8b7f543819bfa1984ec0fc3f12cbf3324e0f99602c2987
|
||||
|
|
@ -0,0 +1 @@
|
|||
3711a08edad1fa122bfce2c5c1183e6514430c1ea3253c707dbdf7c84eebeee2
|
||||
|
|
@ -0,0 +1 @@
|
|||
76ac52c3eeb536a7a0393bf52d0dfe10029d70927cd28697b7bb57969b3ec47b
|
||||
|
|
@ -0,0 +1 @@
|
|||
24f8129c565f649626fb34a05075a3c43acb3336020add263d0595facd45fc25
|
||||
|
|
@ -0,0 +1 @@
|
|||
c7e5dc7f7ca4dbbf62ae0d53eef6beba539ddd75a556a1b20e3f8612997c1204
|
||||
|
|
@ -0,0 +1 @@
|
|||
bf7bd395aac7d28c0982682b5356383d0de4d7b868fa5690c79adc6da4b70022
|
||||
|
|
@ -7743,15 +7743,27 @@ CREATE SEQUENCE ci_build_trace_chunks_id_seq
|
|||
|
||||
ALTER SEQUENCE ci_build_trace_chunks_id_seq OWNED BY ci_build_trace_chunks.id;
|
||||
|
||||
CREATE TABLE ci_build_trace_metadata (
|
||||
CREATE TABLE p_ci_build_trace_metadata (
|
||||
build_id bigint NOT NULL,
|
||||
partition_id bigint NOT NULL,
|
||||
trace_artifact_id bigint,
|
||||
archival_attempts smallint DEFAULT 0 NOT NULL,
|
||||
checksum bytea,
|
||||
remote_checksum bytea,
|
||||
last_archival_attempt_at timestamp with time zone,
|
||||
archived_at timestamp with time zone,
|
||||
partition_id bigint NOT NULL
|
||||
archival_attempts smallint DEFAULT 0 NOT NULL,
|
||||
checksum bytea,
|
||||
remote_checksum bytea
|
||||
)
|
||||
PARTITION BY LIST (partition_id);
|
||||
|
||||
CREATE TABLE ci_build_trace_metadata (
|
||||
build_id bigint NOT NULL,
|
||||
partition_id bigint NOT NULL,
|
||||
trace_artifact_id bigint,
|
||||
last_archival_attempt_at timestamp with time zone,
|
||||
archived_at timestamp with time zone,
|
||||
archival_attempts smallint DEFAULT 0 NOT NULL,
|
||||
checksum bytea,
|
||||
remote_checksum bytea
|
||||
);
|
||||
|
||||
CREATE TABLE ci_builds (
|
||||
|
|
@ -20970,6 +20982,8 @@ ALTER TABLE ONLY namespace_descendants ATTACH PARTITION gitlab_partitions_static
|
|||
|
||||
ALTER TABLE ONLY namespace_descendants ATTACH PARTITION gitlab_partitions_static.namespace_descendants_31 FOR VALUES WITH (modulus 32, remainder 31);
|
||||
|
||||
ALTER TABLE ONLY p_ci_build_trace_metadata ATTACH PARTITION ci_build_trace_metadata FOR VALUES IN ('100', '101', '102');
|
||||
|
||||
ALTER TABLE ONLY p_ci_builds ATTACH PARTITION ci_builds FOR VALUES IN ('100');
|
||||
|
||||
ALTER TABLE ONLY p_ci_builds_metadata ATTACH PARTITION ci_builds_metadata FOR VALUES IN ('100');
|
||||
|
|
@ -23143,8 +23157,11 @@ ALTER TABLE ONLY ci_build_report_results
|
|||
ALTER TABLE ONLY ci_build_trace_chunks
|
||||
ADD CONSTRAINT ci_build_trace_chunks_pkey PRIMARY KEY (id);
|
||||
|
||||
ALTER TABLE ONLY p_ci_build_trace_metadata
|
||||
ADD CONSTRAINT p_ci_build_trace_metadata_pkey PRIMARY KEY (build_id, partition_id);
|
||||
|
||||
ALTER TABLE ONLY ci_build_trace_metadata
|
||||
ADD CONSTRAINT ci_build_trace_metadata_pkey PRIMARY KEY (build_id);
|
||||
ADD CONSTRAINT ci_build_trace_metadata_pkey PRIMARY KEY (build_id, partition_id);
|
||||
|
||||
ALTER TABLE ONLY p_ci_builds_metadata
|
||||
ADD CONSTRAINT p_ci_builds_metadata_pkey PRIMARY KEY (id, partition_id);
|
||||
|
|
@ -26196,6 +26213,10 @@ CREATE INDEX ca_aggregations_last_full_run_at ON analytics_cycle_analytics_aggre
|
|||
|
||||
CREATE INDEX ca_aggregations_last_incremental_run_at ON analytics_cycle_analytics_aggregations USING btree (last_incremental_run_at NULLS FIRST) WHERE (enabled IS TRUE);
|
||||
|
||||
CREATE INDEX index_p_ci_build_trace_metadata_on_trace_artifact_id ON ONLY p_ci_build_trace_metadata USING btree (trace_artifact_id);
|
||||
|
||||
CREATE INDEX ci_build_trace_metadata_trace_artifact_id_idx ON ci_build_trace_metadata USING btree (trace_artifact_id);
|
||||
|
||||
CREATE INDEX p_ci_builds_status_created_at_project_id_idx ON ONLY p_ci_builds USING btree (status, created_at, project_id) WHERE ((type)::text = 'Ci::Build'::text);
|
||||
|
||||
CREATE INDEX ci_builds_gitlab_monitor_metrics ON ci_builds USING btree (status, created_at, project_id) WHERE ((type)::text = 'Ci::Build'::text);
|
||||
|
|
@ -27022,10 +27043,6 @@ CREATE UNIQUE INDEX index_ci_build_trace_chunks_on_build_id_and_chunk_index ON c
|
|||
|
||||
CREATE INDEX index_ci_build_trace_chunks_on_partition_id_build_id ON ci_build_trace_chunks USING btree (partition_id, build_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_ci_build_trace_metadata_on_partition_id_build_id ON ci_build_trace_metadata USING btree (partition_id, build_id);
|
||||
|
||||
CREATE INDEX index_ci_build_trace_metadata_on_trace_artifact_id_partition_id ON ci_build_trace_metadata USING btree (trace_artifact_id, partition_id);
|
||||
|
||||
CREATE INDEX p_ci_builds_metadata_build_id_idx ON ONLY p_ci_builds_metadata USING btree (build_id) WHERE (has_exposed_artifacts IS TRUE);
|
||||
|
||||
CREATE INDEX index_ci_builds_metadata_on_build_id_and_has_exposed_artifacts ON ci_builds_metadata USING btree (build_id) WHERE (has_exposed_artifacts IS TRUE);
|
||||
|
|
@ -30380,8 +30397,6 @@ CREATE INDEX index_vulnerability_occurrence_pipelines_occurrence_id_and_id ON vu
|
|||
|
||||
CREATE INDEX index_vulnerability_occurrence_pipelines_on_pipeline_id ON vulnerability_occurrence_pipelines USING btree (pipeline_id);
|
||||
|
||||
CREATE INDEX index_vulnerability_occurrences_deduplication ON vulnerability_occurrences USING btree (project_id, report_type, project_fingerprint);
|
||||
|
||||
CREATE INDEX index_vulnerability_occurrences_for_override_uuids_logic ON vulnerability_occurrences USING btree (project_id, report_type, location_fingerprint);
|
||||
|
||||
CREATE INDEX index_vulnerability_occurrences_on_initial_pipeline_id ON vulnerability_occurrences USING btree (initial_pipeline_id);
|
||||
|
|
@ -32254,6 +32269,10 @@ ALTER INDEX index_on_namespace_descendants_outdated ATTACH PARTITION gitlab_part
|
|||
|
||||
ALTER INDEX namespace_descendants_pkey ATTACH PARTITION gitlab_partitions_static.namespace_descendants_31_pkey;
|
||||
|
||||
ALTER INDEX p_ci_build_trace_metadata_pkey ATTACH PARTITION ci_build_trace_metadata_pkey;
|
||||
|
||||
ALTER INDEX index_p_ci_build_trace_metadata_on_trace_artifact_id ATTACH PARTITION ci_build_trace_metadata_trace_artifact_id_idx;
|
||||
|
||||
ALTER INDEX p_ci_builds_status_created_at_project_id_idx ATTACH PARTITION ci_builds_gitlab_monitor_metrics;
|
||||
|
||||
ALTER INDEX p_ci_builds_metadata_pkey ATTACH PARTITION ci_builds_metadata_pkey;
|
||||
|
|
@ -32844,7 +32863,7 @@ ALTER TABLE ONLY coverage_fuzzing_corpuses
|
|||
ALTER TABLE ONLY namespace_settings
|
||||
ADD CONSTRAINT fk_20cf0eb2f9 FOREIGN KEY (default_compliance_framework_id) REFERENCES compliance_management_frameworks(id) ON DELETE SET NULL;
|
||||
|
||||
ALTER TABLE ONLY ci_build_trace_metadata
|
||||
ALTER TABLE p_ci_build_trace_metadata
|
||||
ADD CONSTRAINT fk_21d25cac1a_p FOREIGN KEY (partition_id, trace_artifact_id) REFERENCES p_ci_job_artifacts(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY users_star_projects
|
||||
|
|
@ -35028,9 +35047,6 @@ ALTER TABLE ONLY project_compliance_framework_settings
|
|||
ALTER TABLE ONLY users_security_dashboard_projects
|
||||
ADD CONSTRAINT fk_rails_6f6cf8e66e FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY dast_sites
|
||||
ADD CONSTRAINT fk_rails_6febb6ea9c FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY analytics_dashboards_pointers
|
||||
ADD CONSTRAINT fk_rails_7027b7eaa9 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
|
||||
|
||||
|
|
@ -35502,7 +35518,7 @@ ALTER TABLE ONLY analytics_cycle_analytics_group_stages
|
|||
ALTER TABLE ONLY metrics_dashboard_annotations
|
||||
ADD CONSTRAINT fk_rails_aeb11a7643 FOREIGN KEY (environment_id) REFERENCES environments(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY ci_build_trace_metadata
|
||||
ALTER TABLE p_ci_build_trace_metadata
|
||||
ADD CONSTRAINT fk_rails_aebc78111f_p FOREIGN KEY (partition_id, build_id) REFERENCES p_ci_builds(partition_id, id) ON UPDATE CASCADE ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY bulk_import_trackers
|
||||
|
|
|
|||
|
|
@ -669,8 +669,7 @@ WARNING:
|
|||
[very specific cases](https://handbook.gitlab.com/handbook/engineering/workflow/#criteria-for-merging-during-broken-master).
|
||||
For other cases, follow these [handbook instructions](https://handbook.gitlab.com/handbook/engineering/workflow/#merging-during-broken-master).
|
||||
- If the latest pipeline was created before the merge request was approved, start a new pipeline to ensure that full RSpec suite has been run. You may skip this step only if the merge request does not contain any backend change.
|
||||
- If the **latest [merged results pipeline](../ci/pipelines/merged_results_pipelines.md)** was **created less than 8 hours ago**, you
|
||||
may merge without starting a new pipeline as the merge request is close enough to the target branch.
|
||||
- If the **latest [merged results pipeline](../ci/pipelines/merged_results_pipelines.md)** was **created less than 8 hours ago (72 hours for stable branches)**, you may merge without starting a new pipeline as the merge request is close enough to the target branch.
|
||||
- When you set the MR to auto-merge, you should take over
|
||||
subsequent revisions for anything that would be spotted after that.
|
||||
- For merge requests that have had [Squash and merge](../user/project/merge_requests/squash_and_merge.md) set,
|
||||
|
|
|
|||
|
|
@ -246,7 +246,7 @@ Merge train pipelines run a single `pre-merge-checks` job which ensures the late
|
|||
|
||||
1. A [Merged Results pipeline](../../ci/pipelines/merged_results_pipelines.md)
|
||||
1. A [`tier-3` pipeline](#pipeline-tiers) (i.e. full pipeline, not predictive one)
|
||||
1. Created at most 8 hours ago
|
||||
1. Created at most 8 hours ago (72 hours for stable branches)
|
||||
|
||||
We opened [a feedback issue](https://gitlab.com/gitlab-org/quality/engineering-productivity/team/-/issues/513)
|
||||
to iterate on this solution.
|
||||
|
|
|
|||
|
|
@ -102,3 +102,23 @@ The following table shows what type of aggregation is used for each search perio
|
|||
### Data retention
|
||||
|
||||
GitLab has a retention limit of 30 days for all ingested metrics.
|
||||
|
||||
### Create an issue for a metric
|
||||
|
||||
You can create an issue to track any action taken to resolve or investigate a metric. To create an issue for a metric:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project.
|
||||
1. Select **Monitor > Metrics**.
|
||||
1. From the list of metrics, select a metric.
|
||||
1. Select **Create issue**.
|
||||
|
||||
The issue is created in the selected project and pre-filled with information from the metric.
|
||||
You can edit the issue title and description.
|
||||
|
||||
### View issues related to a metric
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project.
|
||||
1. Select **Monitor > Metrics**.
|
||||
1. From the list of metrics, select a metric.
|
||||
1. Scroll to **Related issues**.
|
||||
1. Optional. To view the issue details, select an issue.
|
||||
|
|
|
|||
|
|
@ -277,7 +277,11 @@ A job is queued. When the job finishes, the subscription details are updated.
|
|||
|
||||
## View your subscription
|
||||
|
||||
If you are an administrator, you can view the status of your subscription:
|
||||
Prerequisites:
|
||||
|
||||
- You must be an administrator.
|
||||
|
||||
You can view the status of your subscription:
|
||||
|
||||
1. On the left sidebar, at the bottom, select **Admin**.
|
||||
1. Select **Subscription**.
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ platform for software development. GitLab adds many powerful
|
|||
|
||||
| | | |
|
||||
|--|--|--|
|
||||
| [**Get started**](get_started.md) **{chevron-right}** | [**Install Git**](how_to_install_git/index.md) **{chevron-right}** | [**Tutorial: Create your first commit**](../../tutorials/make_first_git_commit/index.md) **{chevron-right}** |
|
||||
| [**Clone a repository to your local machine**](clone.md) **{chevron-right}** | [**Create a branch for your changes**](branch.md) **{chevron-right}** | [**Add files to your branch**](../../gitlab-basics/add-file.md) **{chevron-right}** |
|
||||
| [**Stash changes for later**](stash.md) **{chevron-right}** | [**Undo changes**](undo.md) **{chevron-right}** | [**Tutorial: Update Git commit messages**](../../tutorials/update_commit_messages/index.md) **{chevron-right}** |
|
||||
| [**Rebase to address merge conflicts**](git_rebase.md) **{chevron-right}** | [**Common Git commands**](../../gitlab-basics/start-using-git.md) **{chevron-right}** | [**Troubleshooting**](troubleshooting_git.md) **{chevron-right}** |
|
||||
| [**Get started**](get_started.md) **{chevron-right}**<br><br>Overview of how features fit together. | [**Install Git**](how_to_install_git/index.md) **{chevron-right}**<br><br>Download, configuration, system requirements. | [**Tutorial: Create your first commit**](../../tutorials/make_first_git_commit/index.md) **{chevron-right}**<br><br>Initial commit, Git basics, repository setup. |
|
||||
| [**Clone a repository to your local machine**](clone.md) **{chevron-right}**<br><br>Local repository, clone, remote repository, SSH. | [**Create a branch for your changes**](branch.md) **{chevron-right}**<br><br>Branching, branch switch, checkout. | [**Add files to your branch**](../../gitlab-basics/add-file.md) **{chevron-right}**<br><br>Git add, staging changes, file management, commits. |
|
||||
| [**Stash changes for later**](stash.md) **{chevron-right}**<br><br>Temporary storage, work in progress, context switching. | [**Undo changes**](undo.md) **{chevron-right}**<br><br>Reverting commits, removing changes, Git reset, unstage. | [**Tutorial: Update Git commit messages**](../../tutorials/update_commit_messages/index.md) **{chevron-right}**<br><br>Commit message editing, version history, best practices. |
|
||||
| [**Rebase to address merge conflicts**](git_rebase.md) **{chevron-right}**<br><br>Conflict resolution, rebase, branch management. | [**Common Git commands**](../../gitlab-basics/start-using-git.md) **{chevron-right}**<br><br>Git cheatsheet, basic operations, command line. | [**Troubleshooting**](troubleshooting_git.md) **{chevron-right}**<br><br>Error resolution, common issues, debugging, Git problems. |
|
||||
|
|
|
|||
|
|
@ -336,10 +336,13 @@ return this error:
|
|||
|
||||
To resolve this issue, you can update the password expiration by either:
|
||||
|
||||
- Using the `gitlab-rails console`:
|
||||
- Using the [GitLab Rails console](../../administration/operations/rails_console.md)
|
||||
to check and update the user data:
|
||||
|
||||
```ruby
|
||||
gitlab-rails console
|
||||
user = User.find_by_username('<USERNAME>')
|
||||
user.password_expired?
|
||||
user.password_expires_at
|
||||
user.update!(password_expires_at: nil)
|
||||
```
|
||||
|
||||
|
|
|
|||
|
|
@ -11,5 +11,5 @@ Store your source files in a repository and create merge requests. Write, debug,
|
|||
|
||||
| | | |
|
||||
|--|--|--|
|
||||
| [**Getting started**](../user/get_started/get_started_managing_code.md) **{chevron-right}** | [**Repositories**](../user/project/repository/index.md) **{chevron-right}** | [**Merge requests**](../user/project/merge_requests/index.md) **{chevron-right}** |
|
||||
| [**Remote development**](../user/project/remote_development/index.md) **{chevron-right}** | | |
|
||||
| [**Getting started**](../user/get_started/get_started_managing_code.md) **{chevron-right}**<br><br>Overview of how features fit together. | [**Repositories**](../user/project/repository/index.md) **{chevron-right}**<br><br>Version control, code storage, Git repositories, repository monitoring. | [**Merge requests**](../user/project/merge_requests/index.md) **{chevron-right}**<br><br>Code review, collaboration, branch merging, commits. |
|
||||
| [**Remote development**](../user/project/remote_development/index.md) **{chevron-right}**<br><br>Web IDE, workspaces. | | |
|
||||
|
|
|
|||
|
|
@ -24,11 +24,11 @@ with [Scaled Agile Framework (SAFe)](https://handbook.gitlab.com/handbook/market
|
|||
|
||||
| | | |
|
||||
|--|--|--|
|
||||
| [**Getting started**](../user/get_started/get_started_planning_work.md) **{chevron-right}** | [**Tutorial: Use GitLab for scrum**](../tutorials/scrum_events/index.md) **{chevron-right}** | [**Tutorial: Use GitLab for Kanban**](../tutorials/kanban/index.md) **{chevron-right}** |
|
||||
| [**Labels**](../user/project/labels.md) **{chevron-right}** | [**Iterations**](../user/group/iterations/index.md) **{chevron-right}** | [**Milestones**](../user/project/milestones/index.md) **{chevron-right}** |
|
||||
| [**Issues**](../user/project/issues/index.md) **{chevron-right}** | [**Issue boards**](../user/project/issue_board.md) **{chevron-right}** | [**Comments and threads**](../user/discussions/index.md) **{chevron-right}** |
|
||||
| [**Tasks**](../user/tasks.md) **{chevron-right}** | [**Requirements**](../user/project/requirements/index.md) **{chevron-right}** | [**Time tracking**](../user/project/time_tracking.md) **{chevron-right}** |
|
||||
| [**CRM**](../user/crm/index.md) **{chevron-right}** | [**Wikis**](../user/project/wiki/index.md) **{chevron-right}** | [**Epics**](../user/group/epics/index.md) **{chevron-right}** |
|
||||
| [**Roadmaps**](../user/group/roadmap/index.md) **{chevron-right}** | [**Planning hierarchies**](../user/group/planning_hierarchy/index.md) **{chevron-right}** | [**Objectives and key results**](../user/okrs.md) **{chevron-right}** |
|
||||
| [**Keyboard shortcuts**](../user/shortcuts.md) **{chevron-right}** | [**Quick actions**](../user/project/quick_actions.md) **{chevron-right}** | [**Markdown**](../user/markdown.md) **{chevron-right}** |
|
||||
| [**To-Do List**](../user/todos.md) **{chevron-right}** | | |
|
||||
| [**Getting started**](../user/get_started/get_started_planning_work.md) **{chevron-right}** <br><br>Overview of how features fit together. | [**Tutorial: Use GitLab for scrum**](../tutorials/scrum_events/index.md) **{chevron-right}** <br><br>Sprints, backlog, user stories, scrum lifecycle. | [**Tutorial: Use GitLab for Kanban**](../tutorials/kanban/index.md) **{chevron-right}** <br><br>Kanban board, columns, work in progress, flow, distribution. |
|
||||
| [**Labels**](../user/project/labels.md) **{chevron-right}** <br><br>Project labels, group labels, nested scopes, filtering. | [**Iterations**](../user/group/iterations/index.md) **{chevron-right}** <br><br>Time-boxed workflow, program increments, cadence, sprints. | [**Milestones**](../user/project/milestones/index.md) **{chevron-right}** <br><br>Burndown charts, goals, progress tracking, releases. |
|
||||
| [**Issues**](../user/project/issues/index.md) **{chevron-right}** <br><br>Tasks, bug reports, feature requests, tracking. | [**Issue boards**](../user/project/issue_board.md) **{chevron-right}** <br><br>Visualization, workflow, Kanban, prioritization. | [**Comments and threads**](../user/discussions/index.md) **{chevron-right}** <br><br> Mentions, locked discussions, internal notes, thread resolution. |
|
||||
| [**Tasks**](../user/tasks.md) **{chevron-right}** <br><br>Task labels, confidential tasks, linked items, task weights. | [**Requirements**](../user/project/requirements/index.md) **{chevron-right}** <br><br>Acceptance criteria, requirements test reports, CSV import. | [**Time tracking**](../user/project/time_tracking.md) **{chevron-right}** <br><br>Estimates, time spent, reporting. |
|
||||
| [**CRM**](../user/crm/index.md) **{chevron-right}** <br><br>Customer management, organizations, contacts, permissions. | [**Wikis**](../user/project/wiki/index.md) **{chevron-right}** <br><br>Documentation, external wikis, wiki events, history. | [**Epics**](../user/group/epics/index.md) **{chevron-right}** <br><br>Roadmaps, hierarchies, planning, issue progress. |
|
||||
| [**Roadmaps**](../user/group/roadmap/index.md) **{chevron-right}** <br><br>Epic progress, timelines, milestones, goals. | [**Planning hierarchies**](../user/group/planning_hierarchy/index.md) **{chevron-right}** <br><br>Organization, structure, multi-level epics, nesting. | [**Objectives and key results**](../user/okrs.md) **{chevron-right}** <br><br>Goal setting, performance tracking, child objectives, health status. |
|
||||
| [**Keyboard shortcuts**](../user/shortcuts.md) **{chevron-right}** <br><br>Global shortcuts, navigation, quick access. | [**Quick actions**](../user/project/quick_actions.md) **{chevron-right}** <br><br>Commands, shortcuts, inline actions. | [**Markdown**](../user/markdown.md) **{chevron-right}** <br><br>Formatting, inline HTML, GitLab-specific references, diagrams and flowcharts. |
|
||||
| [**To-Do List**](../user/todos.md) **{chevron-right}** <br><br>Task management, actions, access changes. | | |
|
||||
|
|
|
|||
|
|
@ -12,7 +12,7 @@ and give everyone access to the projects they need.
|
|||
|
||||
| | | |
|
||||
|--|--|--|
|
||||
| [**Tutorial: Set up your organization**](../tutorials/manage_user/index.md) **{chevron-right}** | [**Namespaces**](../user/namespace/index.md) **{chevron-right}** | [**Members**](../user/project/members/index.md) **{chevron-right}** |
|
||||
| [**Organization** (in development)](../user/organization/index.md) **{chevron-right}** | [**Groups**](../user/group/index.md) **{chevron-right}** | [**Sharing projects and groups**](../user/project/members/sharing_projects_groups.md) **{chevron-right}** |
|
||||
| [**Compliance**](../administration/compliance.md) **{chevron-right}** | [**Enterprise users**](../user/enterprise_user/index.md) **{chevron-right}** | [**Service accounts**](../user/profile/service_accounts.md) **{chevron-right}** |
|
||||
| [**User account options**](../user/profile/index.md) **{chevron-right}** | [**SSH keys**](../user/ssh.md) **{chevron-right}** | [**GitLab.com settings**](../user/gitlab_com/index.md) **{chevron-right}** |
|
||||
| [**Tutorial: Set up your organization**](../tutorials/manage_user/index.md) **{chevron-right}**<br><br>Setup, configuration, onboarding, organization structure. | [**Namespaces**](../user/namespace/index.md) **{chevron-right}**<br><br>Organization, hierarchy, project grouping. | [**Members**](../user/project/members/index.md) **{chevron-right}**<br><br>User management, roles, permissions, access levels. |
|
||||
| [**Organization** (in development)](../user/organization/index.md) **{chevron-right}**<br><br>Namespace hierarchy. | [**Groups**](../user/group/index.md) **{chevron-right}**<br><br>Project management, access control, client groups, team groups. | [**Sharing projects and groups**](../user/project/members/sharing_projects_groups.md) **{chevron-right}**<br><br>Invitations, group inheritance, project visibility. |
|
||||
| [**Compliance**](../administration/compliance.md) **{chevron-right}**<br><br>Compliance center, audit events, security policies, compliance frameworks. | [**Enterprise users**](../user/enterprise_user/index.md) **{chevron-right}**<br><br>Domain verification, two-factor authentication, enterprise user management, SAML response. | [**Service accounts**](../user/profile/service_accounts.md) **{chevron-right}**<br><br>Machine user, rate limits, personal access tokens. |
|
||||
| [**User account options**](../user/profile/index.md) **{chevron-right}**<br><br>Profile settings, preferences, authentication, notifications. | [**SSH keys**](../user/ssh.md) **{chevron-right}**<br><br>Authentication, permissions, key types, ownership. | [**GitLab.com settings**](../user/gitlab_com/index.md) **{chevron-right}**<br><br>Instance configurations. |
|
||||
|
|
|
|||
|
|
@ -61,7 +61,7 @@ DETAILS:
|
|||
- Helps you understand the selected code by explaining it more clearly.
|
||||
- LLM: Anthropic [Claude 3.5 Sonnet](https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-5-sonnet)
|
||||
- View documentation for explaining code in:
|
||||
- [The IDE](../gitlab_duo_chat/examples.md#explain-code).
|
||||
- [The IDE](../gitlab_duo_chat/examples.md#explain-selected-code).
|
||||
- [A file](../../user/project/repository/code_explain.md).
|
||||
- [A merge request](../../user/project/merge_requests/changes.md#explain-code-in-a-merge-request).
|
||||
|
||||
|
|
|
|||
|
|
@ -34,10 +34,46 @@ its knowledge base is updated daily.
|
|||
- On GitLab.com the, the most recent version of the documentation is used.
|
||||
- On Self-managed and GitLab Dedicated, the documentation for the version of the instance is used.
|
||||
|
||||
## Ask about code
|
||||
## Explain selected code
|
||||
|
||||
DETAILS:
|
||||
**Tier GitLab.com and Self-managed:** Premium or Ultimate for a limited time. In the future, Premium with GitLab Duo Pro or Ultimate with [GitLab Duo Pro or Enterprise](../../subscriptions/subscription-add-ons.md). **GitLab Dedicated:** GitLab Duo Pro or Enterprise.
|
||||
**Tier: GitLab.com and Self-managed:** Premium or Ultimate for a limited time. In the future, Premium with GitLab Duo Pro or Ultimate with [GitLab Duo Pro or Enterprise](../../subscriptions/subscription-add-ons.md). **GitLab Dedicated:** GitLab Duo Pro or Enterprise.
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
**Editors:** GitLab UI, Web IDE, VS Code, JetBrains IDEs
|
||||
**LLMs:** Anthropic: [`claude-3-5-sonnet-20240620`](https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-5-sonnet)
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/429915) for GitLab.com in GitLab 16.7.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/429915) for self-managed and GitLab Dedicated in GitLab 16.8.
|
||||
|
||||
You can ask GitLab Duo Chat to explain selected code:
|
||||
|
||||
1. Select some code in your IDE.
|
||||
1. In Duo Chat, type `/explain`.
|
||||
|
||||

|
||||
|
||||
You can also add additional instructions to be considered, for example:
|
||||
|
||||
- `/explain the performance`
|
||||
- `/explain focus on the algorithm`
|
||||
- `/explain the performance gains or losses using this code`
|
||||
- `/explain the object inheritance` (classes, object-oriented)
|
||||
- `/explain why a static variable is used here` (C++)
|
||||
- `/explain how this function would cause a segmentation fault` (C)
|
||||
- `/explain how concurrency works in this context` (Go)
|
||||
- `/explain how the request reaches the client` (REST API, database)
|
||||
|
||||
For more information, see [Use GitLab Duo Chat in VS Code](index.md#use-gitlab-duo-chat-in-vs-code).
|
||||
|
||||
In the GitLab UI, you can also explain code in:
|
||||
|
||||
- A [file](../project/repository/code_explain.md).
|
||||
- A [merge request](../project/merge_requests/changes.md#explain-code-in-a-merge-request).
|
||||
|
||||
## Ask about or generate code
|
||||
|
||||
DETAILS:
|
||||
**Tier: GitLab.com and Self-managed:** Premium or Ultimate for a limited time. In the future, Premium with GitLab Duo Pro or Ultimate with [GitLab Duo Pro or Enterprise](../../subscriptions/subscription-add-ons.md). **GitLab Dedicated:** GitLab Duo Pro or Enterprise.
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
**Editors:** GitLab UI, Web IDE, VS Code, JetBrains IDEs
|
||||
**LLMs:** Anthropic: [`claude-3-5-sonnet-20240620`](https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-5-sonnet)
|
||||
|
|
@ -45,7 +81,15 @@ DETAILS:
|
|||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122235) for GitLab.com in GitLab 16.1.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/122235) for self-managed and GitLab Dedicated in GitLab 16.8.
|
||||
|
||||
You can also ask GitLab Duo Chat to generate code:
|
||||
You can ask GitLab Duo Chat questions about code by pasting that code into
|
||||
the Duo Chat window. For example:
|
||||
|
||||
```plaintext
|
||||
Provide a clear explanation of this Ruby code: def sum(a, b) a + b end.
|
||||
Describe what this code does and how it works.
|
||||
```
|
||||
|
||||
You can also ask Chat to generate code. For example:
|
||||
|
||||
- `Write a Ruby function that prints 'Hello, World!' when called.`
|
||||
- `Develop a JavaScript program that simulates a two-player Tic-Tac-Toe game. Provide both game logic and user interface, if applicable.`
|
||||
|
|
@ -54,11 +98,45 @@ You can also ask GitLab Duo Chat to generate code:
|
|||
- `Create a product-consumer example with threads and shared memory in C++. Use atomic locks when possible.`
|
||||
- `Generate Rust code for high performance gRPC calls. Provide a source code example for a server and client.`
|
||||
|
||||
And you can ask GitLab Duo Chat to explain code:
|
||||
## Refactor code in the IDE
|
||||
|
||||
- `Provide a clear explanation of the given Ruby code: def sum(a, b) a + b end. Describe what this code does and how it works.`
|
||||
DETAILS:
|
||||
**Tier: GitLab.com and Self-managed:** Premium or Ultimate for a limited time. In the future, Premium with GitLab Duo Pro or Ultimate with [GitLab Duo Pro or Enterprise](../../subscriptions/subscription-add-ons.md). **GitLab Dedicated:** GitLab Duo Pro or Enterprise.
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
**Editors:** Web IDE, VS Code, JetBrains IDEs
|
||||
**LLMs:** Anthropic: [`claude-3-5-sonnet-20240620`](https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-5-sonnet)
|
||||
|
||||
Alternatively, you can use the [`/explain` command](examples.md#explain-code) to explain the selected code in your editor.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/429915) for GitLab.com in GitLab 16.7.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/429915) for self-managed and GitLab Dedicated in GitLab 16.8.
|
||||
|
||||
`/refactor` is a special command to generate a refactoring suggestion for the selected code in your editor.
|
||||
You can include additional instructions to be considered. For example:
|
||||
|
||||
- Use a specific coding pattern, for example `/refactor with ActiveRecord` or `/refactor into a class providing static functions`.
|
||||
- Use a specific library, for example `/refactor using mysql`.
|
||||
- Use a specific function/algorithm, for example `/refactor into a stringstream with multiple lines` in C++.
|
||||
- Refactor to a different programming language, for example `/refactor to TypeScript`.
|
||||
- Focus on performance, for example `/refactor improving performance`.
|
||||
- Focus on potential vulnerabilities, for example `/refactor avoiding memory leaks and exploits`.
|
||||
|
||||
## Fix code in the IDE
|
||||
|
||||
DETAILS:
|
||||
**Tier: GitLab.com and Self-managed:** Premium or Ultimate for a limited time. In the future, Premium with GitLab Duo Pro or Ultimate with [GitLab Duo Pro or Enterprise](../../subscriptions/subscription-add-ons.md). **GitLab Dedicated:** GitLab Duo Pro or Enterprise.
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
**Editors:** Web IDE, VS Code, JetBrains IDEs
|
||||
**LLMs:** Anthropic: [`claude-3-5-sonnet-20240620`](https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-5-sonnet)
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/429915) for GitLab.com, self-managed and GitLab Dedicated in GitLab 17.3.
|
||||
|
||||
`/fix` is a special command to generate a fix suggestion for the selected code in your editor.
|
||||
You can include additional instructions to be considered. For example:
|
||||
|
||||
- Focus on grammar and typos, for example, `/fix grammar mistakes and typos`.
|
||||
- Focus on a concrete algorithm or problem description, for example, `/fix duplicate database inserts` or `/fix race conditions`.
|
||||
- Focus on potential bugs that are not directly visible, for example, `/fix potential bugs`.
|
||||
- Focus on code performance problems, for example, `/fix performance problems`.
|
||||
- Focus on fixing the build when the code does not compile, for example, `/fix the build`.
|
||||
|
||||
## Ask about CI/CD
|
||||
|
||||
|
|
@ -128,74 +206,6 @@ DETAILS:
|
|||
|
||||
[Learn more](../application_security/vulnerabilities/index.md#explaining-a-vulnerability).
|
||||
|
||||
## Explain code
|
||||
|
||||
DETAILS:
|
||||
**Tier: GitLab.com and Self-managed:** Premium or Ultimate for a limited time. In the future, Premium with GitLab Duo Pro or Ultimate with [GitLab Duo Pro or Enterprise](../../subscriptions/subscription-add-ons.md). **GitLab Dedicated:** GitLab Duo Pro or Enterprise.
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
**Editors:** GitLab UI, Web IDE, VS Code, JetBrains IDEs
|
||||
**LLMs:** Anthropic: [`claude-3-5-sonnet-20240620`](https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-5-sonnet)
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/429915) for GitLab.com in GitLab 16.7.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/429915) for self-managed and GitLab Dedicated in GitLab 16.8.
|
||||
|
||||
`/explain` is a special command to explain the selected code in your editor.
|
||||
You can also add additional instructions to be considered, for example: `/explain the performance`
|
||||
See [Use GitLab Duo Chat in VS Code](index.md#use-gitlab-duo-chat-in-vs-code) for more information.
|
||||
|
||||
- `/explain focus on the algorithm`
|
||||
- `/explain the performance gains or losses using this code`
|
||||
- `/explain the object inheritance` (classes, object-oriented)
|
||||
- `/explain why a static variable is used here` (C++)
|
||||
- `/explain how this function would cause a segmentation fault` (C)
|
||||
- `/explain how concurrency works in this context` (Go)
|
||||
- `/explain how the request reaches the client` (REST API, database)
|
||||
|
||||
You can also use the Web UI to explain code in:
|
||||
|
||||
- A [file](../project/repository/code_explain.md).
|
||||
- A [merge request](../project/merge_requests/changes.md#explain-code-in-a-merge-request).
|
||||
|
||||
## Refactor code in the IDE
|
||||
|
||||
DETAILS:
|
||||
**Tier: GitLab.com and Self-managed:** Premium or Ultimate for a limited time. In the future, Premium with GitLab Duo Pro or Ultimate with [GitLab Duo Pro or Enterprise](../../subscriptions/subscription-add-ons.md). **GitLab Dedicated:** GitLab Duo Pro or Enterprise.
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
**Editors:** Web IDE, VS Code, JetBrains IDEs
|
||||
**LLMs:** Anthropic: [`claude-3-5-sonnet-20240620`](https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-5-sonnet)
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/429915) for GitLab.com in GitLab 16.7.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/429915) for self-managed and GitLab Dedicated in GitLab 16.8.
|
||||
|
||||
`/refactor` is a special command to generate a refactoring suggestion for the selected code in your editor.
|
||||
You can include additional instructions to be considered. For example:
|
||||
|
||||
- Use a specific coding pattern, for example `/refactor with ActiveRecord` or `/refactor into a class providing static functions`.
|
||||
- Use a specific library, for example `/refactor using mysql`.
|
||||
- Use a specific function/algorithm, for example `/refactor into a stringstream with multiple lines` in C++.
|
||||
- Refactor to a different programming language, for example `/refactor to TypeScript`.
|
||||
- Focus on performance, for example `/refactor improving performance`.
|
||||
- Focus on potential vulnerabilities, for example `/refactor avoiding memory leaks and exploits`.
|
||||
|
||||
## Fix code in the IDE
|
||||
|
||||
DETAILS:
|
||||
**Tier: GitLab.com and Self-managed:** Premium or Ultimate for a limited time. In the future, Premium with GitLab Duo Pro or Ultimate with [GitLab Duo Pro or Enterprise](../../subscriptions/subscription-add-ons.md). **GitLab Dedicated:** GitLab Duo Pro or Enterprise.
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
**Editors:** Web IDE, VS Code, JetBrains IDEs
|
||||
**LLMs:** Anthropic: [`claude-3-5-sonnet-20240620`](https://console.cloud.google.com/vertex-ai/publishers/anthropic/model-garden/claude-3-5-sonnet)
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/429915) for GitLab.com, self-managed and GitLab Dedicated in GitLab 17.3.
|
||||
|
||||
`/fix` is a special command to generate a fix suggestion for the selected code in your editor.
|
||||
You can include additional instructions to be considered. For example:
|
||||
|
||||
- Focus on grammar and typos, for example, `/fix grammar mistakes and typos`.
|
||||
- Focus on a concrete algorithm or problem description, for example, `/fix duplicate database inserts` or `/fix race conditions`.
|
||||
- Focus on potential bugs that are not directly visible, for example, `/fix potential bugs`.
|
||||
- Focus on code performance problems, for example, `/fix performance problems`.
|
||||
- Focus on fixing the build when the code does not compile, for example, `/fix the build`.
|
||||
|
||||
## Write tests in the IDE
|
||||
|
||||
DETAILS:
|
||||
|
|
@ -307,8 +317,8 @@ Use the following commands to quickly accomplish specific tasks.
|
|||
| /clear | [Delete all conversations permanently and clear the chat window](#delete-or-reset-the-conversation) |
|
||||
| /reset | [Start a new conversation, but keep the previous conversations visible in the chat window](#delete-or-reset-the-conversation) |
|
||||
| /tests | [Write tests](#write-tests-in-the-ide) |
|
||||
| /explain | [Explain code](../gitlab_duo_chat/examples.md#explain-code) |
|
||||
| /vulnerability_explain | [Explain current vulnerability](../gitlab_duo/index.md#vulnerability-explanation) |
|
||||
| /refactor | [Refactor the code](../gitlab_duo_chat/examples.md#refactor-code-in-the-ide) |
|
||||
| /explain | [Explain code](#explain-selected-code) |
|
||||
| /vulnerability_explain | [Explain current vulnerability](../application_security/vulnerabilities/index.md#explaining-a-vulnerability) |
|
||||
| /refactor | [Refactor the code](#refactor-code-in-the-ide) |
|
||||
| /troubleshoot | [Troubleshoot failed CI/CD jobs with root cause analysis](#troubleshoot-failed-cicd-jobs-with-root-cause-analysis) |
|
||||
| /fix | [Fix the code](../gitlab_duo_chat/examples.md#fix-code-in-the-ide) |
|
||||
| /fix | [Fix the code](#fix-code-in-the-ide) |
|
||||
|
|
|
|||
Binary file not shown.
|
After Width: | Height: | Size: 56 KiB |
|
|
@ -82,7 +82,7 @@ For more information about slash commands, refer to the documentation:
|
|||
- [/tests](../gitlab_duo_chat/examples.md#write-tests-in-the-ide)
|
||||
- [/refactor](../gitlab_duo_chat/examples.md#refactor-code-in-the-ide)
|
||||
- [/fix](../gitlab_duo_chat/examples.md#fix-code-in-the-ide)
|
||||
- [/explain](../gitlab_duo_chat/examples.md#explain-code)
|
||||
- [/explain](../gitlab_duo_chat/examples.md#explain-selected-code)
|
||||
|
||||
## `Error M4001`
|
||||
|
||||
|
|
|
|||
|
|
@ -261,7 +261,7 @@ We cannot guarantee that the large language model produces results that are corr
|
|||
You can also explain code in:
|
||||
|
||||
- A [file](../../../user/project/repository/code_explain.md).
|
||||
- The [IDE](../../../user/gitlab_duo_chat/examples.md#explain-code).
|
||||
- The [IDE](../../../user/gitlab_duo_chat/examples.md#explain-selected-code).
|
||||
|
||||
## Expand or collapse comments
|
||||
|
||||
|
|
|
|||
|
|
@ -17,10 +17,10 @@ GitLab does not limit the number of private projects you can create.
|
|||
|
||||
| | | |
|
||||
|--|--|--|
|
||||
| [**Getting started**](../../user/get_started/get_started_projects.md) **{chevron-right}** | [**Create a project**](index.md) **{chevron-right}** | [**Manage projects**](working_with_projects.md) **{chevron-right}** |
|
||||
| [**Project visibility**](../public_access.md) **{chevron-right}** | [**Project settings**](working_with_projects.md) **{chevron-right}** | [**Description templates**](../../user/project/description_templates.md) **{chevron-right}** |
|
||||
| [**Project access tokens**](../project/settings/project_access_tokens.md) **{chevron-right}** | [**Deploy keys**](../../user/project/deploy_keys/index.md) **{chevron-right}** | [**Deploy tokens**](../../user/project/deploy_tokens/index.md) **{chevron-right}** |
|
||||
| [**Share projects**](../project/members/share_project_with_groups.md) **{chevron-right}** | [**Reserved project and group names**](../../user/reserved_names.md) **{chevron-right}** | [**Search**](../../user/search/index.md) **{chevron-right}** |
|
||||
| [**Badges**](../../user/project/badges.md) **{chevron-right}** | [**Project topics**](../../user/project/project_topics.md) **{chevron-right}** | [**Code intelligence**](../../user/project/code_intelligence.md) **{chevron-right}** |
|
||||
| [**Import and migrate**](../../user/project/import/index.md) **{chevron-right}** | [**System notes**](../../user/project/system_notes.md) **{chevron-right}** | [**Transfer a project to another namespace**](../../user/project/import/index.md) **{chevron-right}** |
|
||||
| [**Use a project as a Go package**](../../user/project/use_project_as_go_package.md) **{chevron-right}** | [**Tutorial: Build a protected workflow for your project**](../../tutorials/protected_workflow/index.md) **{chevron-right}** | [**Troubleshooting**](../../user/project/troubleshooting.md) **{chevron-right}** |
|
||||
| [**Getting started**](../../user/get_started/get_started_projects.md) **{chevron-right}**<br><br>Overview of how features fit together. | [**Create a project**](index.md) **{chevron-right}**<br><br>New project, project templates. | [**Manage projects**](working_with_projects.md) **{chevron-right}**<br><br>Settings, configuration, project activity, project deletion. |
|
||||
| [**Project visibility**](../public_access.md) **{chevron-right}****<br><br>Public, private, internal. | [**Project settings**](working_with_projects.md) **{chevron-right}**<br><br>Project features, analytics, project permissions. | [**Description templates**](../../user/project/description_templates.md) **{chevron-right}**<br><br>Issue templates, merge request templates, instance and group templates. |
|
||||
| [**Project access tokens**](../project/settings/project_access_tokens.md) **{chevron-right}**<br><br>Authentication, create, revoke, token expiration. | [**Deploy keys**](../../user/project/deploy_keys/index.md) **{chevron-right}**<br><br>Public SSH keys, repository access, bot users, read-only access. | [**Deploy tokens**](../../user/project/deploy_tokens/index.md) **{chevron-right}**<br><br>Repository cloning, token creation, container registry. |
|
||||
| [**Share projects**](../project/members/share_project_with_groups.md)**{chevron-right}**<br><br>Member roles, invitations, group access. | [**Reserved project and group names**](../../user/reserved_names.md) **{chevron-right}**<br><br>Naming conventions, restrictions, reserved names. | [**Search**](../../user/search/index.md) **{chevron-right}**<br><br>Basic, advanced, exact, search scope, commit SHA search. |
|
||||
| [**Badges**](../../user/project/badges.md) **{chevron-right}**<br><br>Pipeline status, group, project, custom badges. | [**Project topics**](../../user/project/project_topics.md) **{chevron-right}**<br><br>Project organization, subscribe, view. | [**Code intelligence**](../../user/project/code_intelligence.md) **{chevron-right}**<br><br>Type signatures, symbol documentation, go-to definition. |
|
||||
| [**Import and migrate**](../../user/project/import/index.md) **{chevron-right}**<br><br>Repository migration, third-party repositories, user contribution mapping. | [**System notes**](../../user/project/system_notes.md) **{chevron-right}**<br><br>Event history, activity log, comments history. | [**Transfer a project to another namespace**](../../user/project/import/index.md) **{chevron-right}**<br><br>Namespace transfer, subscription transfer. |
|
||||
| [**Use a project as a Go package**](../../user/project/use_project_as_go_package.md) **{chevron-right}**<br><br>Go modules, import calls. | [**Tutorial: Build a protected workflow for your project**](../../tutorials/protected_workflow/index.md) **{chevron-right}**<br><br>Security, approval rules, branch protection. | [**Troubleshooting**](../../user/project/troubleshooting.md) **{chevron-right}**<br><br>Problem solving, common issues, debugging, error resolution. |
|
||||
|
|
|
|||
|
|
@ -42,4 +42,4 @@ We cannot guarantee that the large language model produces results that are corr
|
|||
You can also explain code in:
|
||||
|
||||
- A [merge request](../../../user/project/merge_requests/changes.md#explain-code-in-a-merge-request).
|
||||
- The [IDE](../../../user/gitlab_duo_chat/examples.md#explain-code).
|
||||
- The [IDE](../../../user/gitlab_duo_chat/examples.md#explain-selected-code).
|
||||
|
|
|
|||
|
|
@ -199,6 +199,13 @@ e.send(:design_repo_saver).send(:save)
|
|||
# The following line should show you the export_path similar to /var/opt/gitlab/gitlab-rails/shared/tmp/gitlab_exports/@hashed/49/94/4994....
|
||||
s = Gitlab::ImportExport::Saver.new(exportable: p, shared: p.import_export_shared, user: u)
|
||||
|
||||
# Prior to GitLab 17.0, the `user` parameter was not supported. If you encounter an
|
||||
# error with the above or are unsure whether or not to supply the `user`
|
||||
# argument, use the following check:
|
||||
Gitlab::ImportExport::Saver.instance_method(:initialize).parameters.include?([:keyreq, :user])
|
||||
# If the preceding check returns false, omit the user argument:
|
||||
s = Gitlab::ImportExport::Saver.new(exportable: p, shared: p.import_export_shared)
|
||||
|
||||
# To try and upload use:
|
||||
s.send(:compress_and_save)
|
||||
s.send(:save_upload)
|
||||
|
|
|
|||
|
|
@ -32,6 +32,10 @@ module ClickHouse
|
|||
self.class.new(@query_builder.offset(count))
|
||||
end
|
||||
|
||||
def group(...)
|
||||
self.class.new(@query_builder.group(...))
|
||||
end
|
||||
|
||||
def select(...)
|
||||
self.class.new(@query_builder.select(...))
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,41 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module ClickHouse # rubocop:disable Gitlab/BoundedContexts -- Existing module
|
||||
module Models
|
||||
module Ci
|
||||
class FinishedPipelinesHourly < ClickHouse::Models::BaseModel
|
||||
def self.table_name
|
||||
'ci_finished_pipelines_hourly'
|
||||
end
|
||||
|
||||
def self.for_project(project)
|
||||
new.for_project(project)
|
||||
end
|
||||
|
||||
def self.by_status(statuses)
|
||||
new.by_status(statuses)
|
||||
end
|
||||
|
||||
def self.group_by_status
|
||||
new.group_by_status
|
||||
end
|
||||
|
||||
def for_project(project)
|
||||
where(path: project.project_namespace.traversal_path)
|
||||
end
|
||||
|
||||
def by_status(statuses)
|
||||
where(status: statuses)
|
||||
end
|
||||
|
||||
def group_by_status
|
||||
group([@query_builder.table[:status]])
|
||||
end
|
||||
|
||||
def count_pipelines_function
|
||||
Arel::Nodes::NamedFunction.new('countMerge', [@query_builder.table[:count_pipelines]])
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -90,6 +90,14 @@ module ClickHouse
|
|||
new_instance
|
||||
end
|
||||
|
||||
def group(*columns)
|
||||
new_instance = deep_clone
|
||||
|
||||
new_instance.manager.group(*columns)
|
||||
|
||||
new_instance
|
||||
end
|
||||
|
||||
def limit(count)
|
||||
manager.take(count)
|
||||
self
|
||||
|
|
|
|||
|
|
@ -14,12 +14,14 @@ end
|
|||
require 'time'
|
||||
|
||||
class PreMergeChecks
|
||||
DEFAULT_API_ENDPOINT = "https://gitlab.com/api/v4"
|
||||
MERGE_TRAIN_REF_REGEX = %r{\Arefs/merge-requests/\d+/train\z}
|
||||
TIER_IDENTIFIER_REGEX = /tier:\d/
|
||||
REQUIRED_TIER_IDENTIFIER = 'tier:3'
|
||||
PREDICTIVE_PIPELINE_IDENTIFIER = 'predictive'
|
||||
PIPELINE_FRESHNESS_THRESHOLD_IN_HOURS = 8
|
||||
DEFAULT_API_ENDPOINT = "https://gitlab.com/api/v4"
|
||||
MERGE_TRAIN_REF_REGEX = %r{\Arefs/merge-requests/\d+/train\z}
|
||||
PIPELINE_FRESHNESS_DEFAULT_THRESHOLD_IN_HOURS = 8
|
||||
PIPELINE_FRESHNESS_STABLE_BRANCHES_THRESHOLD_IN_HOURS = 72
|
||||
PREDICTIVE_PIPELINE_IDENTIFIER = 'predictive'
|
||||
REQUIRED_TIER_IDENTIFIER = 'tier:3'
|
||||
STABLE_BRANCH_SUFFIX = '-stable-ee'
|
||||
TIER_IDENTIFIER_REGEX = /tier:\d/
|
||||
|
||||
PreMergeChecksFailedError = Class.new(StandardError)
|
||||
PreMergeChecksStatus = Struct.new(:exitstatus, :message) do
|
||||
|
|
@ -31,10 +33,12 @@ class PreMergeChecks
|
|||
def initialize(
|
||||
api_endpoint: ENV.fetch('CI_API_V4_URL', DEFAULT_API_ENDPOINT),
|
||||
project_id: ENV['CI_PROJECT_ID'],
|
||||
merge_request_iid: ENV['CI_MERGE_REQUEST_IID'])
|
||||
merge_request_iid: ENV['CI_MERGE_REQUEST_IID'],
|
||||
target_branch: ENV['CI_MERGE_REQUEST_TARGET_BRANCH_NAME'])
|
||||
@api_endpoint = api_endpoint
|
||||
@project_id = project_id
|
||||
@merge_request_iid = merge_request_iid.to_i
|
||||
@target_branch = target_branch
|
||||
end
|
||||
|
||||
def execute
|
||||
|
|
@ -62,7 +66,7 @@ class PreMergeChecks
|
|||
|
||||
private
|
||||
|
||||
attr_reader :api_endpoint, :project_id, :merge_request_iid
|
||||
attr_reader :api_endpoint, :project_id, :merge_request_iid, :target_branch
|
||||
|
||||
def api_client
|
||||
@api_client ||= begin
|
||||
|
|
@ -77,6 +81,7 @@ class PreMergeChecks
|
|||
def check_required_ids!
|
||||
fail_check!("Missing project_id!") unless project_id
|
||||
fail_check!("Missing merge_request_iid!") if merge_request_iid == 0
|
||||
fail_check!("Missing target_branch!") unless target_branch
|
||||
end
|
||||
|
||||
def check_pipeline_for_merged_results!(pipeline)
|
||||
|
|
@ -101,10 +106,17 @@ class PreMergeChecks
|
|||
|
||||
def check_pipeline_freshness!(pipeline)
|
||||
hours_ago = ((Time.now - Time.parse(pipeline.created_at)) / 3600).ceil(2)
|
||||
return if hours_ago < PIPELINE_FRESHNESS_THRESHOLD_IN_HOURS
|
||||
threshold =
|
||||
if target_branch_is_stable_branch?
|
||||
PIPELINE_FRESHNESS_STABLE_BRANCHES_THRESHOLD_IN_HOURS
|
||||
else
|
||||
PIPELINE_FRESHNESS_DEFAULT_THRESHOLD_IN_HOURS
|
||||
end
|
||||
|
||||
return if hours_ago < threshold
|
||||
|
||||
fail_check! <<~TEXT
|
||||
Expected latest pipeline (#{pipeline.web_url}) to be created within the last #{PIPELINE_FRESHNESS_THRESHOLD_IN_HOURS} hours (it was created #{hours_ago} hours ago)!
|
||||
Expected latest pipeline (#{pipeline.web_url}) to be created within the last #{threshold} hours (it was created #{hours_ago} hours ago)!
|
||||
|
||||
Please start a new pipeline.
|
||||
TEXT
|
||||
|
|
@ -126,6 +138,10 @@ class PreMergeChecks
|
|||
end
|
||||
end
|
||||
|
||||
def target_branch_is_stable_branch?
|
||||
target_branch.end_with?(STABLE_BRANCH_SUFFIX)
|
||||
end
|
||||
|
||||
def fail_check!(text)
|
||||
raise PreMergeChecksFailedError, text
|
||||
end
|
||||
|
|
@ -144,12 +160,18 @@ if $PROGRAM_NAME == __FILE__
|
|||
options[:merge_request_iid] = value
|
||||
end
|
||||
|
||||
opts.on("-t", "--target-branch [string]", String, "Target branch name") do |value|
|
||||
options[:target_branch] = value
|
||||
end
|
||||
|
||||
opts.on("-h", "--help") do
|
||||
puts "Usage: #{File.basename(__FILE__)} [--project_id <PROJECT_ID>] [--merge_request_iid <MERGE_REQUEST_IID>]"
|
||||
puts "Usage: #{File.basename(__FILE__)} [--project_id <PROJECT_ID>] " \
|
||||
"[--merge_request_iid <MERGE_REQUEST_IID>] [--target-branch <TARGET_BRANCH>]"
|
||||
puts
|
||||
puts "Examples:"
|
||||
puts
|
||||
puts "#{File.basename(__FILE__)} --project_id \"gitlab-org/gitlab\" --merge_request_iid \"1\""
|
||||
puts "#{File.basename(__FILE__)} --project_id \"gitlab-org/gitlab\" " \
|
||||
"--merge_request_iid \"1\" --target-branch \"master\""
|
||||
|
||||
exit
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,31 +10,33 @@ RSpec.describe 'Database schema', feature_category: :database do
|
|||
let(:columns_name_with_jsonb) { retrieve_columns_name_with_jsonb }
|
||||
|
||||
IGNORED_INDEXES_ON_FKS = {
|
||||
ai_testing_terms_acceptances: %w[user_id], # testing terms only have 1 entry, and if the user is deleted the record should remain
|
||||
application_settings: %w[instance_administration_project_id instance_administrators_group_id],
|
||||
ci_build_trace_metadata: [%w[partition_id build_id], %w[partition_id trace_artifact_id]], # the index on build_id is enough
|
||||
ci_builds: [%w[partition_id stage_id], %w[partition_id execution_config_id], %w[auto_canceled_by_partition_id auto_canceled_by_id], %w[upstream_pipeline_partition_id upstream_pipeline_id], %w[partition_id commit_id]], # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142804#note_1745483081
|
||||
ci_daily_build_group_report_results: [%w[partition_id last_pipeline_id]], # index on last_pipeline_id is sufficient
|
||||
ci_pipeline_artifacts: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
ci_pipeline_chat_data: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
ci_pipeline_messages: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
ci_pipeline_metadata: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
ci_pipeline_variables: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
ci_pipelines: [%w[auto_canceled_by_partition_id auto_canceled_by_id]], # index on auto_canceled_by_id is sufficient
|
||||
ci_pipelines_config: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
ci_sources_pipelines: [%w[source_partition_id source_pipeline_id], %w[partition_id pipeline_id]],
|
||||
ci_sources_projects: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
ci_stages: [%w[partition_id pipeline_id]], # the index on pipeline_id is sufficient
|
||||
notes: %w[namespace_id], # this index is added in an async manner, hence it needs to be ignored in the first phase.
|
||||
p_ci_build_trace_metadata: [%w[partition_id build_id], %w[partition_id trace_artifact_id]], # the index on build_id is enough
|
||||
p_ci_builds: [%w[partition_id stage_id], %w[partition_id execution_config_id], %w[auto_canceled_by_partition_id auto_canceled_by_id], %w[upstream_pipeline_partition_id upstream_pipeline_id], %w[partition_id commit_id]], # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142804#note_1745483081
|
||||
p_ci_builds_execution_configs: [%w[partition_id pipeline_id]], # the index on pipeline_id is enough
|
||||
p_ci_pipeline_variables: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
p_ci_stages: [%w[partition_id pipeline_id]], # the index on pipeline_id is sufficient
|
||||
# `search_index_id index_type` is the composite foreign key configured for `search_namespace_index_assignments`,
|
||||
# but in Search::NamespaceIndexAssignment model, only `search_index_id` is used as foreign key and indexed
|
||||
search_namespace_index_assignments: [%w[search_index_id index_type]],
|
||||
slack_integrations_scopes: [%w[slack_api_scope_id]],
|
||||
notes: %w[namespace_id], # this index is added in an async manner, hence it needs to be ignored in the first phase.
|
||||
users: [%w[accepted_term_id]],
|
||||
ci_pipeline_artifacts: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
ci_sources_projects: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
ci_daily_build_group_report_results: [%w[partition_id last_pipeline_id]], # index on last_pipeline_id is sufficient
|
||||
ci_builds: [%w[partition_id stage_id], %w[partition_id execution_config_id], %w[auto_canceled_by_partition_id auto_canceled_by_id], %w[upstream_pipeline_partition_id upstream_pipeline_id], %w[partition_id commit_id]], # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142804#note_1745483081
|
||||
ci_pipeline_variables: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
p_ci_pipeline_variables: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
ci_pipelines: [%w[auto_canceled_by_partition_id auto_canceled_by_id]], # index on auto_canceled_by_id is sufficient
|
||||
ci_pipelines_config: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
ci_pipeline_metadata: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
ci_pipeline_messages: [%w[partition_id pipeline_id]], # index on pipeline_id is sufficient
|
||||
p_ci_builds: [%w[partition_id stage_id], %w[partition_id execution_config_id], %w[auto_canceled_by_partition_id auto_canceled_by_id], %w[upstream_pipeline_partition_id upstream_pipeline_id], %w[partition_id commit_id]], # https://gitlab.com/gitlab-org/gitlab/-/merge_requests/142804#note_1745483081
|
||||
ci_stages: [%w[partition_id pipeline_id]], # the index on pipeline_id is sufficient
|
||||
p_ci_stages: [%w[partition_id pipeline_id]], # the index on pipeline_id is sufficient
|
||||
ai_testing_terms_acceptances: %w[user_id], # testing terms only have 1 entry, and if the user is deleted the record should remain
|
||||
p_ci_builds_execution_configs: [%w[partition_id pipeline_id]], # the index on pipeline_id is enough
|
||||
ci_sources_pipelines: [%w[source_partition_id source_pipeline_id], %w[partition_id pipeline_id]],
|
||||
snippets: %w[organization_id] # this index is added in an async manner, hence it needs to be ignored in the first phase.
|
||||
snippets: %w[organization_id], # this index is added in an async manner, hence it needs to be ignored in the first phase.
|
||||
users: [%w[accepted_term_id]]
|
||||
}.with_indifferent_access.freeze
|
||||
|
||||
# If splitting FK and table removal into two MRs as suggested in the docs, use this constant in the initial FK removal MR.
|
||||
|
|
|
|||
|
|
@ -207,23 +207,6 @@ describe('noteable_discussion component', () => {
|
|||
expect(replyWrapper.exists()).toBe(true);
|
||||
expect(replyWrapper.classes('internal-note')).toBe(true);
|
||||
});
|
||||
|
||||
it('should add `public-note` class when the discussion is not internal', async () => {
|
||||
const softCopyInternalNotes = [...discussionMock.notes];
|
||||
const mockPublicNotes = softCopyInternalNotes.splice(0, 2);
|
||||
mockPublicNotes[0].internal = false;
|
||||
|
||||
const mockDiscussion = {
|
||||
...discussionMock,
|
||||
notes: [...mockPublicNotes],
|
||||
};
|
||||
wrapper.setProps({ discussion: mockDiscussion });
|
||||
await nextTick();
|
||||
|
||||
const replyWrapper = wrapper.find('[data-testid="reply-wrapper"]');
|
||||
expect(replyWrapper.exists()).toBe(true);
|
||||
expect(replyWrapper.classes('public-note')).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
describe('for resolved thread', () => {
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ import {
|
|||
formattedTimeFromDate,
|
||||
isTracingDateRangeOutOfBounds,
|
||||
validatedDateRangeQuery,
|
||||
urlWithStringifiedPayloadParam,
|
||||
} from '~/observability/utils';
|
||||
import {
|
||||
CUSTOM_DATE_RANGE_OPTION,
|
||||
|
|
@ -271,3 +272,15 @@ describe('validatedDateRangeQuery', () => {
|
|||
expect(result).toEqual({ value: '1h' });
|
||||
});
|
||||
});
|
||||
|
||||
describe('urlWithStringifiedPayloadParam', () => {
|
||||
it('returns the url with a stringified param', () => {
|
||||
expect(
|
||||
urlWithStringifiedPayloadParam(
|
||||
'http://gdk.test:3443/?foo=bar',
|
||||
{ a: 'b', c: 'd' },
|
||||
'my_param',
|
||||
),
|
||||
).toBe('http://gdk.test:3443/?foo=bar&my_param=%7B%22a%22%3A%22b%22%2C%22c%22%3A%22d%22%7D');
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -90,6 +90,19 @@ RSpec.describe ClickHouse::Models::BaseModel, feature_category: :database do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#group' do
|
||||
it 'returns a new instance with grouped results' do
|
||||
dummy_instance = dummy_class.new(query_builder)
|
||||
|
||||
expect(query_builder).to receive(:group).with(:id, :name).and_return(updated_query_builder)
|
||||
|
||||
new_instance = dummy_instance.group(:id, :name)
|
||||
|
||||
expect(new_instance).to be_a(dummy_class)
|
||||
expect(new_instance).not_to eq(dummy_instance)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#select' do
|
||||
it 'returns a new instance with selected fields' do
|
||||
dummy_instance = dummy_class.new(query_builder)
|
||||
|
|
|
|||
|
|
@ -0,0 +1,111 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe ClickHouse::Models::Ci::FinishedPipelinesHourly, feature_category: :fleet_visibility do
|
||||
let(:instance) { described_class.new }
|
||||
|
||||
let_it_be(:group) { create(:group, :nested) }
|
||||
let_it_be(:project) { create(:project, group: group) }
|
||||
let_it_be(:path) { project.reload.project_namespace.traversal_path }
|
||||
|
||||
specify { expect(path).to match(%r{\A(\d+/){3}\z}) }
|
||||
|
||||
describe '#for_project' do
|
||||
it 'builds the correct SQL' do
|
||||
expected_sql = <<~SQL.lines(chomp: true).join(' ')
|
||||
SELECT * FROM "ci_finished_pipelines_hourly"
|
||||
WHERE "ci_finished_pipelines_hourly"."path" = '#{path}'
|
||||
SQL
|
||||
|
||||
result_sql = instance.for_project(project).to_sql
|
||||
|
||||
expect(result_sql.strip).to eq(expected_sql.strip)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#by_status' do
|
||||
it 'builds the correct SQL' do
|
||||
expected_sql = <<~SQL.lines(chomp: true).join(' ')
|
||||
SELECT * FROM "ci_finished_pipelines_hourly"
|
||||
WHERE "ci_finished_pipelines_hourly"."status" IN ('failed', 'success')
|
||||
SQL
|
||||
|
||||
result_sql = instance.by_status(%i[failed success]).to_sql
|
||||
|
||||
expect(result_sql.strip).to eq(expected_sql.strip)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#group_by_status' do
|
||||
it 'builds the correct SQL' do
|
||||
expected_sql = <<~SQL.lines(chomp: true).join(' ')
|
||||
SELECT "ci_finished_pipelines_hourly"."status"
|
||||
FROM "ci_finished_pipelines_hourly"
|
||||
GROUP BY "ci_finished_pipelines_hourly"."status"
|
||||
SQL
|
||||
|
||||
result_sql = instance.select(:status).group_by_status.to_sql
|
||||
|
||||
expect(result_sql.strip).to eq(expected_sql.strip)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#count_pipelines_function' do
|
||||
it 'builds the correct SQL' do
|
||||
expected_sql = <<~SQL.lines(chomp: true).join(' ')
|
||||
SELECT "ci_finished_pipelines_hourly"."status", countMerge("ci_finished_pipelines_hourly"."count_pipelines")
|
||||
FROM "ci_finished_pipelines_hourly"
|
||||
SQL
|
||||
|
||||
result_sql = instance.select(:status, instance.count_pipelines_function).to_sql
|
||||
|
||||
expect(result_sql.strip).to eq(expected_sql.strip)
|
||||
end
|
||||
end
|
||||
|
||||
describe 'class methods' do
|
||||
before do
|
||||
allow(described_class).to receive(:new).and_return(instance)
|
||||
end
|
||||
|
||||
describe '.for_project' do
|
||||
it 'calls the corresponding instance method' do
|
||||
expect(instance).to receive(:for_project).with(project)
|
||||
|
||||
described_class.for_project(project)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.by_status' do
|
||||
it 'calls the corresponding instance method' do
|
||||
expect(instance).to receive(:by_status).with(:success)
|
||||
|
||||
described_class.by_status(:success)
|
||||
end
|
||||
end
|
||||
|
||||
describe '.group_by_status' do
|
||||
it 'calls the corresponding instance method' do
|
||||
expect(instance).to receive(:group_by_status)
|
||||
|
||||
described_class.group_by_status
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe 'method chaining' do
|
||||
it 'builds the correct SQL with chained methods' do
|
||||
expected_sql = <<~SQL.lines(chomp: true).join(' ')
|
||||
SELECT "ci_finished_pipelines_hourly"."status" FROM "ci_finished_pipelines_hourly"
|
||||
WHERE "ci_finished_pipelines_hourly"."path" = '#{path}'
|
||||
AND "ci_finished_pipelines_hourly"."status" IN ('failed', 'success')
|
||||
GROUP BY "ci_finished_pipelines_hourly"."status"
|
||||
SQL
|
||||
|
||||
result_sql = instance.for_project(project).select(:status).by_status(%i[failed success]).group_by_status.to_sql
|
||||
|
||||
expect(result_sql.strip).to eq(expected_sql.strip)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -278,6 +278,30 @@ RSpec.describe ClickHouse::QueryBuilder, feature_category: :database do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#group' do
|
||||
it 'builds correct group query' do
|
||||
expected_sql = <<~SQL.lines(chomp: true).join(' ')
|
||||
SELECT * FROM "test_table"
|
||||
GROUP BY column1
|
||||
SQL
|
||||
|
||||
sql = builder.group(:column1).to_sql
|
||||
|
||||
expect(sql).to eq(expected_sql)
|
||||
end
|
||||
|
||||
it 'chains multiple groups when called multiple times' do
|
||||
expected_sql = <<~SQL.lines(chomp: true).join(' ')
|
||||
SELECT * FROM "test_table"
|
||||
GROUP BY column1, column2
|
||||
SQL
|
||||
|
||||
sql = builder.group(:column1).group(:column2).to_sql
|
||||
|
||||
expect(sql).to eq(expected_sql)
|
||||
end
|
||||
end
|
||||
|
||||
describe '#to_sql' do
|
||||
it 'delegates to the Arel::SelectManager' do
|
||||
expect(builder.send(:manager)).to receive(:to_sql)
|
||||
|
|
|
|||
|
|
@ -46,7 +46,11 @@ RSpec.describe Gitlab::Database::PostgresPartition, type: :model, feature_catego
|
|||
end
|
||||
|
||||
describe '.with_list_constraint' do
|
||||
subject(:with_list_constraint) { described_class.with_list_constraint(partition_id) }
|
||||
subject(:with_list_constraint) do
|
||||
described_class
|
||||
.with_parent_tables(Ci::Partitionable.registered_models.map(&:table_name))
|
||||
.with_list_constraint(partition_id)
|
||||
end
|
||||
|
||||
context 'when condition matches' do
|
||||
let(:partition_id) { '102' }
|
||||
|
|
|
|||
|
|
@ -13,29 +13,32 @@ RSpec.describe VirtualRegistries::Packages::Policies::GroupPolicy, feature_categ
|
|||
|
||||
describe 'read_virtual_registry' do
|
||||
where(:group_visibility, :current_user, :allowed?) do
|
||||
'PUBLIC' | nil | false
|
||||
'PUBLIC' | ref(:non_group_member) | true
|
||||
'PUBLIC' | ref(:guest) | true
|
||||
'PUBLIC' | ref(:reporter) | true
|
||||
'PUBLIC' | ref(:developer) | true
|
||||
'PUBLIC' | ref(:maintainer) | true
|
||||
'PUBLIC' | ref(:owner) | true
|
||||
'PUBLIC' | nil | false
|
||||
'PUBLIC' | ref(:non_group_member) | false
|
||||
'PUBLIC' | ref(:guest) | true
|
||||
'PUBLIC' | ref(:reporter) | true
|
||||
'PUBLIC' | ref(:developer) | true
|
||||
'PUBLIC' | ref(:maintainer) | true
|
||||
'PUBLIC' | ref(:owner) | true
|
||||
'PUBLIC' | ref(:organization_owner) | true
|
||||
|
||||
'INTERNAL' | nil | false
|
||||
'INTERNAL' | ref(:non_group_member) | true
|
||||
'INTERNAL' | ref(:guest) | true
|
||||
'INTERNAL' | ref(:reporter) | true
|
||||
'INTERNAL' | ref(:developer) | true
|
||||
'INTERNAL' | ref(:maintainer) | true
|
||||
'INTERNAL' | ref(:owner) | true
|
||||
'INTERNAL' | nil | false
|
||||
'INTERNAL' | ref(:non_group_member) | false
|
||||
'INTERNAL' | ref(:guest) | true
|
||||
'INTERNAL' | ref(:reporter) | true
|
||||
'INTERNAL' | ref(:developer) | true
|
||||
'INTERNAL' | ref(:maintainer) | true
|
||||
'INTERNAL' | ref(:owner) | true
|
||||
'INTERNAL' | ref(:organization_owner) | true
|
||||
|
||||
'PRIVATE' | nil | false
|
||||
'PRIVATE' | ref(:non_group_member) | false
|
||||
'PRIVATE' | ref(:guest) | true
|
||||
'PRIVATE' | ref(:reporter) | true
|
||||
'PRIVATE' | ref(:developer) | true
|
||||
'PRIVATE' | ref(:maintainer) | true
|
||||
'PRIVATE' | ref(:owner) | true
|
||||
'PRIVATE' | nil | false
|
||||
'PRIVATE' | ref(:non_group_member) | false
|
||||
'PRIVATE' | ref(:guest) | true
|
||||
'PRIVATE' | ref(:reporter) | true
|
||||
'PRIVATE' | ref(:developer) | true
|
||||
'PRIVATE' | ref(:maintainer) | true
|
||||
'PRIVATE' | ref(:owner) | true
|
||||
'PRIVATE' | ref(:organization_owner) | true
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
@ -46,14 +49,42 @@ RSpec.describe VirtualRegistries::Packages::Policies::GroupPolicy, feature_categ
|
|||
it { is_expected.to public_send(allowed? ? :be_allowed : :be_disallowed, :read_virtual_registry) }
|
||||
end
|
||||
|
||||
context 'for deploy token' do
|
||||
let(:deploy_token) do
|
||||
create(:deploy_token, :group).tap do |token|
|
||||
create(:group_deploy_token, group: target, deploy_token: token)
|
||||
context 'with project membership' do
|
||||
let_it_be(:project) { create(:project, group: group) }
|
||||
let(:current_user) { non_group_member }
|
||||
|
||||
%i[
|
||||
guest
|
||||
reporter
|
||||
developer
|
||||
maintainer
|
||||
owner
|
||||
].each do |role|
|
||||
context "for #{role}" do
|
||||
before do
|
||||
project.send(:"add_#{role}", current_user)
|
||||
end
|
||||
|
||||
it { expect_allowed(:read_virtual_registry) }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
subject { described_class.new(deploy_token, policy_subject) }
|
||||
context 'for admin' do
|
||||
let(:current_user) { admin }
|
||||
|
||||
context 'when admin mode is enabled', :enable_admin_mode do
|
||||
it { expect_allowed(:read_virtual_registry) }
|
||||
end
|
||||
|
||||
context 'when admin mode is disabled' do
|
||||
it { expect_disallowed(:read_virtual_registry) }
|
||||
end
|
||||
end
|
||||
|
||||
context 'for deploy token' do
|
||||
let(:deploy_token) { create(:deploy_token, :group, groups: [target]) }
|
||||
let(:current_user) { deploy_token }
|
||||
|
||||
where(:target, :group_visibility, :read_virtual_registry, :allowed?) do
|
||||
ref(:group) | 'PUBLIC' | true | true
|
||||
|
|
@ -85,29 +116,32 @@ RSpec.describe VirtualRegistries::Packages::Policies::GroupPolicy, feature_categ
|
|||
%i[create update destroy].each do |action|
|
||||
describe "#{action}_virtual_registry" do
|
||||
where(:group_visibility, :current_user, :allowed?) do
|
||||
'PUBLIC' | nil | false
|
||||
'PUBLIC' | ref(:non_group_member) | false
|
||||
'PUBLIC' | ref(:guest) | false
|
||||
'PUBLIC' | ref(:reporter) | false
|
||||
'PUBLIC' | ref(:developer) | false
|
||||
'PUBLIC' | ref(:maintainer) | true
|
||||
'PUBLIC' | ref(:owner) | true
|
||||
'PUBLIC' | nil | false
|
||||
'PUBLIC' | ref(:non_group_member) | false
|
||||
'PUBLIC' | ref(:guest) | false
|
||||
'PUBLIC' | ref(:reporter) | false
|
||||
'PUBLIC' | ref(:developer) | false
|
||||
'PUBLIC' | ref(:maintainer) | true
|
||||
'PUBLIC' | ref(:owner) | true
|
||||
'PUBLIC' | ref(:organization_owner) | true
|
||||
|
||||
'INTERNAL' | nil | false
|
||||
'INTERNAL' | ref(:non_group_member) | false
|
||||
'INTERNAL' | ref(:guest) | false
|
||||
'INTERNAL' | ref(:reporter) | false
|
||||
'INTERNAL' | ref(:developer) | false
|
||||
'INTERNAL' | ref(:maintainer) | true
|
||||
'INTERNAL' | ref(:owner) | true
|
||||
'INTERNAL' | nil | false
|
||||
'INTERNAL' | ref(:non_group_member) | false
|
||||
'INTERNAL' | ref(:guest) | false
|
||||
'INTERNAL' | ref(:reporter) | false
|
||||
'INTERNAL' | ref(:developer) | false
|
||||
'INTERNAL' | ref(:maintainer) | true
|
||||
'INTERNAL' | ref(:owner) | true
|
||||
'INTERNAL' | ref(:organization_owner) | true
|
||||
|
||||
'PRIVATE' | nil | false
|
||||
'PRIVATE' | ref(:non_group_member) | false
|
||||
'PRIVATE' | ref(:guest) | false
|
||||
'PRIVATE' | ref(:reporter) | false
|
||||
'PRIVATE' | ref(:developer) | false
|
||||
'PRIVATE' | ref(:maintainer) | true
|
||||
'PRIVATE' | ref(:owner) | true
|
||||
'PRIVATE' | nil | false
|
||||
'PRIVATE' | ref(:non_group_member) | false
|
||||
'PRIVATE' | ref(:guest) | false
|
||||
'PRIVATE' | ref(:reporter) | false
|
||||
'PRIVATE' | ref(:developer) | false
|
||||
'PRIVATE' | ref(:maintainer) | true
|
||||
'PRIVATE' | ref(:owner) | true
|
||||
'PRIVATE' | ref(:organization_owner) | true
|
||||
end
|
||||
|
||||
with_them do
|
||||
|
|
@ -118,5 +152,17 @@ RSpec.describe VirtualRegistries::Packages::Policies::GroupPolicy, feature_categ
|
|||
it { is_expected.to public_send(allowed? ? :be_allowed : :be_disallowed, :"#{action}_virtual_registry") }
|
||||
end
|
||||
end
|
||||
|
||||
context 'for admin' do
|
||||
let(:current_user) { admin }
|
||||
|
||||
context 'when admin mode is enabled', :enable_admin_mode do
|
||||
it { expect_allowed(:"#{action}_virtual_registry") }
|
||||
end
|
||||
|
||||
context 'when admin mode is disabled' do
|
||||
it { expect_disallowed(:"#{action}_virtual_registry") }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,18 +7,18 @@ RSpec.describe API::VirtualRegistries::Packages::Maven, feature_category: :virtu
|
|||
include WorkhorseHelpers
|
||||
include HttpBasicAuthHelpers
|
||||
|
||||
let_it_be_with_reload(:registry) { create(:virtual_registries_packages_maven_registry) }
|
||||
let_it_be(:group) { create(:group) }
|
||||
let_it_be_with_reload(:registry) { create(:virtual_registries_packages_maven_registry, group: group) }
|
||||
let_it_be(:upstream) { create(:virtual_registries_packages_maven_upstream, registry: registry) }
|
||||
let_it_be(:group) { registry.group }
|
||||
let_it_be(:project) { create(:project, namespace: group) }
|
||||
let_it_be(:user) { project.creator }
|
||||
let_it_be(:personal_access_token) { create(:personal_access_token, user: user) }
|
||||
let_it_be(:user) { create(:user, owner_of: project) }
|
||||
let_it_be(:job) { create(:ci_build, :running, user: user, project: project) }
|
||||
let_it_be(:deploy_token) do
|
||||
create(:deploy_token, :group, groups: [group], read_virtual_registry: true)
|
||||
end
|
||||
|
||||
let_it_be(:headers) { user_basic_auth_header(user, personal_access_token) }
|
||||
let(:personal_access_token) { create(:personal_access_token, user: user) }
|
||||
let(:headers) { user_basic_auth_header(user, personal_access_token) }
|
||||
|
||||
shared_examples 'disabled feature flag' do
|
||||
before do
|
||||
|
|
@ -95,11 +95,11 @@ RSpec.describe API::VirtualRegistries::Packages::Maven, feature_category: :virtu
|
|||
end
|
||||
|
||||
context 'with a non member user' do
|
||||
let_it_be(:user) { build_stubbed(:user) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
where(:group_access_level, :status) do
|
||||
'PUBLIC' | :ok
|
||||
'INTERNAL' | :ok
|
||||
'PUBLIC' | :forbidden
|
||||
'INTERNAL' | :forbidden
|
||||
'PRIVATE' | :not_found
|
||||
end
|
||||
|
||||
|
|
@ -108,11 +108,7 @@ RSpec.describe API::VirtualRegistries::Packages::Maven, feature_category: :virtu
|
|||
group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_access_level, false))
|
||||
end
|
||||
|
||||
if params[:status] == :ok
|
||||
it_behaves_like 'successful response'
|
||||
else
|
||||
it_behaves_like 'returning response status', params[:status]
|
||||
end
|
||||
it_behaves_like 'returning response status', params[:status]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -323,11 +319,11 @@ RSpec.describe API::VirtualRegistries::Packages::Maven, feature_category: :virtu
|
|||
end
|
||||
|
||||
context 'with a non member user' do
|
||||
let_it_be(:user) { build_stubbed(:user) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
where(:group_access_level, :status) do
|
||||
'PUBLIC' | :ok
|
||||
'INTERNAL' | :ok
|
||||
'PUBLIC' | :forbidden
|
||||
'INTERNAL' | :forbidden
|
||||
'PRIVATE' | :forbidden
|
||||
end
|
||||
with_them do
|
||||
|
|
@ -335,11 +331,7 @@ RSpec.describe API::VirtualRegistries::Packages::Maven, feature_category: :virtu
|
|||
group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_access_level, false))
|
||||
end
|
||||
|
||||
if params[:status] == :ok
|
||||
it_behaves_like 'successful response'
|
||||
else
|
||||
it_behaves_like 'returning response status', params[:status]
|
||||
end
|
||||
it_behaves_like 'returning response status', params[:status]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -588,8 +580,8 @@ RSpec.describe API::VirtualRegistries::Packages::Maven, feature_category: :virtu
|
|||
let_it_be(:user) { create(:user) }
|
||||
|
||||
where(:group_access_level, :status) do
|
||||
'PUBLIC' | :ok
|
||||
'INTERNAL' | :ok
|
||||
'PUBLIC' | :forbidden
|
||||
'INTERNAL' | :forbidden
|
||||
'PRIVATE' | :forbidden
|
||||
end
|
||||
|
||||
|
|
@ -598,11 +590,7 @@ RSpec.describe API::VirtualRegistries::Packages::Maven, feature_category: :virtu
|
|||
group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_access_level, false))
|
||||
end
|
||||
|
||||
if params[:status] == :ok
|
||||
it_behaves_like 'successful response'
|
||||
else
|
||||
it_behaves_like 'returning response status', params[:status]
|
||||
end
|
||||
it_behaves_like 'returning response status', params[:status]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
@ -782,11 +770,11 @@ RSpec.describe API::VirtualRegistries::Packages::Maven, feature_category: :virtu
|
|||
end
|
||||
|
||||
context 'with a non member user' do
|
||||
let_it_be(:user) { build_stubbed(:user) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
|
||||
where(:group_access_level, :status) do
|
||||
'PUBLIC' | :ok
|
||||
'INTERNAL' | :ok
|
||||
'PUBLIC' | :forbidden
|
||||
'INTERNAL' | :forbidden
|
||||
'PRIVATE' | :forbidden
|
||||
end
|
||||
|
||||
|
|
@ -795,11 +783,7 @@ RSpec.describe API::VirtualRegistries::Packages::Maven, feature_category: :virtu
|
|||
group.update!(visibility_level: Gitlab::VisibilityLevel.const_get(group_access_level, false))
|
||||
end
|
||||
|
||||
if params[:status] == :ok
|
||||
it_behaves_like 'successful response'
|
||||
else
|
||||
it_behaves_like 'returning response status', params[:status]
|
||||
end
|
||||
it_behaves_like 'returning response status', params[:status]
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -8,16 +8,17 @@ require_relative '../../../scripts/pipeline/pre_merge_checks'
|
|||
RSpec.describe PreMergeChecks, time_travel_to: Time.parse('2024-05-29T10:00:00 UTC'), feature_category: :tooling do
|
||||
include StubENV
|
||||
|
||||
let(:instance) { described_class.new }
|
||||
let(:project_id) { '42' }
|
||||
let(:merge_request_iid) { '1' }
|
||||
let(:mr_pipelines_url) { "https://gitlab.test/api/v4/projects/#{project_id}/merge_requests/#{merge_request_iid}/pipelines" }
|
||||
let(:instance) { described_class.new }
|
||||
let(:project_id) { '42' }
|
||||
let(:merge_request_iid) { '1' }
|
||||
let(:target_branch) { 'master' }
|
||||
let(:mr_pipelines_url) { "https://gitlab.test/api/v4/projects/#{project_id}/merge_requests/#{merge_request_iid}/pipelines" }
|
||||
|
||||
let(:latest_mr_pipeline_ref) { "refs/merge-requests/1/merge" }
|
||||
let(:latest_mr_pipeline_status) { "success" }
|
||||
let(:latest_mr_pipeline_ref) { "refs/merge-requests/1/merge" }
|
||||
let(:latest_mr_pipeline_status) { "success" }
|
||||
let(:latest_mr_pipeline_created_at) { "2024-05-29T07:15:00 UTC" }
|
||||
let(:latest_mr_pipeline_web_url) { "https://gitlab.com/gitlab-org/gitlab/-/pipelines/1310472835" }
|
||||
let(:latest_mr_pipeline_name) { "Ruby 3.2 MR [tier:3, gdk]" }
|
||||
let(:latest_mr_pipeline_web_url) { "https://gitlab.com/gitlab-org/gitlab/-/pipelines/1310472835" }
|
||||
let(:latest_mr_pipeline_name) { "Ruby 3.2 MR [tier:3, gdk]" }
|
||||
let(:latest_mr_pipeline_short) do
|
||||
{
|
||||
id: 1309901620,
|
||||
|
|
@ -78,7 +79,8 @@ RSpec.describe PreMergeChecks, time_travel_to: Time.parse('2024-05-29T10:00:00 U
|
|||
stub_env(
|
||||
'CI_API_V4_URL' => 'https://gitlab.test/api/v4',
|
||||
'CI_PROJECT_ID' => project_id,
|
||||
'CI_MERGE_REQUEST_IID' => merge_request_iid
|
||||
'CI_MERGE_REQUEST_IID' => merge_request_iid,
|
||||
'CI_MERGE_REQUEST_TARGET_BRANCH_NAME' => target_branch
|
||||
)
|
||||
end
|
||||
|
||||
|
|
@ -102,6 +104,16 @@ RSpec.describe PreMergeChecks, time_travel_to: Time.parse('2024-05-29T10:00:00 U
|
|||
expect(instance.execute.message).to include("Missing merge_request_iid")
|
||||
end
|
||||
end
|
||||
|
||||
context 'when target_branch is missing' do
|
||||
let(:target_branch) { nil }
|
||||
|
||||
it 'returns a failed PreMergeChecksStatus' do
|
||||
expect(instance.execute).to be_a(described_class::PreMergeChecksStatus)
|
||||
expect(instance.execute).not_to be_success
|
||||
expect(instance.execute.message).to include("Missing target_branch")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#execute' do
|
||||
|
|
@ -138,6 +150,33 @@ RSpec.describe PreMergeChecks, time_travel_to: Time.parse('2024-05-29T10:00:00 U
|
|||
allow(api_client).to receive(:pipeline).with(project_id, mr_pipelines[2][:id]).and_return(latest_mr_pipeline)
|
||||
end
|
||||
|
||||
context 'and the target branch is a stable branch' do
|
||||
let(:target_branch) { 'a-stable-branch-stable-ee' }
|
||||
|
||||
context 'and the latest pipeline is not fresh enough' do
|
||||
let(:latest_mr_pipeline_created_at) { "2024-05-26T09:30:00 UTC" }
|
||||
|
||||
it 'returns a failed PreMergeChecksStatus' do
|
||||
expect(instance.execute).to be_a(described_class::PreMergeChecksStatus)
|
||||
expect(instance.execute).not_to be_success
|
||||
expect(instance.execute.message)
|
||||
.to include(
|
||||
"Expected latest pipeline (#{latest_mr_pipeline_web_url}) to be created within the last 72 hours " \
|
||||
"(it was created 72.5 hours ago)!"
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
context 'and the latest pipeline is fresh enough' do
|
||||
let(:latest_mr_pipeline_created_at) { "2024-05-26T10:30:00 UTC" }
|
||||
|
||||
it 'returns a successful PreMergeChecksStatus' do
|
||||
expect(instance.execute).to be_a(described_class::PreMergeChecksStatus)
|
||||
expect(instance.execute).to be_success
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context 'and it passes all the checks' do
|
||||
it 'returns a successful PreMergeChecksStatus' do
|
||||
expect(instance.execute).to be_a(described_class::PreMergeChecksStatus)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ require 'spec_helper'
|
|||
RSpec.describe VirtualRegistries::Packages::Maven::HandleFileRequestService, :aggregate_failures, feature_category: :virtual_registry do
|
||||
let_it_be(:registry) { create(:virtual_registries_packages_maven_registry, :with_upstream) }
|
||||
let_it_be(:project) { create(:project, namespace: registry.group) }
|
||||
let_it_be(:user) { create(:user, owner_of: project) }
|
||||
|
||||
let(:user) { project.creator }
|
||||
let(:upstream) { registry.upstream }
|
||||
let(:path) { 'com/test/package/1.2.3/package-1.2.3.pom' }
|
||||
let(:upstream_resource_url) { upstream.url_for(path) }
|
||||
|
|
|
|||
Loading…
Reference in New Issue