Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2024-03-21 18:14:12 +00:00
parent 91a8a89bd6
commit f2e8d3f288
133 changed files with 1779 additions and 293 deletions

View File

@ -181,7 +181,8 @@ rspec-all frontend_fixture as-if-foss:
- .frontend:rules:frontend_fixture-as-if-foss - .frontend:rules:frontend_fixture-as-if-foss
- .as-if-foss - .as-if-foss
variables: variables:
# We explicitely disable Crystalball here so as even in scheduled pipelines we don't need it since it's already enabled for `rspec-all frontend_fixture` there. # We explicitly disable Crystalball here so as even in scheduled pipelines we don't need it
# since it's already enabled for `rspec-all frontend_fixture` there.
CRYSTALBALL: "false" CRYSTALBALL: "false"
WEBPACK_VENDOR_DLL: "true" WEBPACK_VENDOR_DLL: "true"
KNAPSACK_GENERATE_REPORT: "" KNAPSACK_GENERATE_REPORT: ""

View File

@ -109,6 +109,7 @@ linters:
# haml-lint force enables these: https://github.com/sds/haml-lint/blob/v0.51.0/config/forced_rubocop_config.yml # haml-lint force enables these: https://github.com/sds/haml-lint/blob/v0.51.0/config/forced_rubocop_config.yml
- Layout/ArgumentAlignment - Layout/ArgumentAlignment
- Layout/ArrayAlignment - Layout/ArrayAlignment
- Layout/SpaceInsideParens # See https://gitlab.com/gitlab-org/gitlab/-/merge_requests/147088
- Layout/EndAlignment - Layout/EndAlignment
- Cop/LineBreakAfterGuardClauses - Cop/LineBreakAfterGuardClauses

View File

@ -22,13 +22,12 @@ export default {
}, },
computed: { computed: {
...mapGetters('diffs', ['isInlineView', 'isParallelView']), ...mapGetters('diffs', ['isInlineView', 'isParallelView']),
...mapState('diffs', ['renderTreeList', 'showWhitespace', 'viewDiffsFileByFile']), ...mapState('diffs', ['showWhitespace', 'viewDiffsFileByFile']),
}, },
methods: { methods: {
...mapActions('diffs', [ ...mapActions('diffs', [
'setInlineDiffViewType', 'setInlineDiffViewType',
'setParallelDiffViewType', 'setParallelDiffViewType',
'setRenderTreeList',
'setShowWhitespace', 'setShowWhitespace',
'setFileByFile', 'setFileByFile',
]), ]),
@ -60,25 +59,6 @@ export default {
>{{ $options.i18n.preferences }}</span >{{ $options.i18n.preferences }}</span
> >
</slot> </slot>
<div class="gl-px-3">
<span class="gl-font-weight-bold gl-display-block gl-mb-2">{{ __('File browser') }}</span>
<gl-button-group class="gl-display-flex">
<gl-button
:class="{ selected: !renderTreeList }"
class="gl-w-half js-list-view"
@click="setRenderTreeList({ renderTreeList: false })"
>
{{ __('List view') }}
</gl-button>
<gl-button
:class="{ selected: renderTreeList }"
class="gl-w-half js-tree-view"
@click="setRenderTreeList({ renderTreeList: true })"
>
{{ __('Tree view') }}
</gl-button>
</gl-button-group>
</div>
<div class="gl-mt-3 gl-px-3"> <div class="gl-mt-3 gl-px-3">
<span class="gl-font-weight-bold gl-display-block gl-mb-2">{{ <span class="gl-font-weight-bold gl-display-block gl-mb-2">{{
__('Compare changes') __('Compare changes')

View File

@ -1,5 +1,5 @@
<script> <script>
import { GlTooltipDirective, GlIcon } from '@gitlab/ui'; import { GlTooltipDirective, GlIcon, GlBadge, GlButtonGroup, GlButton } from '@gitlab/ui';
// eslint-disable-next-line no-restricted-imports // eslint-disable-next-line no-restricted-imports
import { mapActions, mapGetters, mapState } from 'vuex'; import { mapActions, mapGetters, mapState } from 'vuex';
import micromatch from 'micromatch'; import micromatch from 'micromatch';
@ -16,6 +16,9 @@ export default {
GlTooltip: GlTooltipDirective, GlTooltip: GlTooltipDirective,
}, },
components: { components: {
GlBadge,
GlButtonGroup,
GlButton,
TreeListHeight, TreeListHeight,
GlIcon, GlIcon,
DiffFileRow, DiffFileRow,
@ -126,7 +129,7 @@ export default {
}, },
}, },
methods: { methods: {
...mapActions('diffs', ['toggleTreeOpen', 'goToFile']), ...mapActions('diffs', ['toggleTreeOpen', 'goToFile', 'setRenderTreeList']),
clearSearch() { clearSearch() {
this.search = ''; this.search = '';
}, },
@ -139,6 +142,30 @@ export default {
<template> <template>
<div class="tree-list-holder d-flex flex-column" data-testid="file-tree-container"> <div class="tree-list-holder d-flex flex-column" data-testid="file-tree-container">
<div class="gl-display-flex gl-align-items-center gl-mb-3">
<h5 class="gl-display-inline-block gl-my-0">{{ __('Files') }}</h5>
<gl-badge size="sm" class="gl-ml-2">{{ allBlobs.length }}</gl-badge>
<gl-button-group class="gl-ml-auto">
<gl-button
v-gl-tooltip.hover
icon="list-bulleted"
:selected="!renderTreeList"
:title="__('List view')"
:aria-label="__('List view')"
data-testid="list-view-toggle"
@click="setRenderTreeList({ renderTreeList: false })"
/>
<gl-button
v-gl-tooltip.hover
icon="file-tree"
:selected="renderTreeList"
:title="__('Tree view')"
:aria-label="__('Tree view')"
data-testid="tree-view-toggle"
@click="setRenderTreeList({ renderTreeList: true })"
/>
</gl-button-group>
</div>
<div class="gl-pb-3 position-relative tree-list-search d-flex"> <div class="gl-pb-3 position-relative tree-list-search d-flex">
<div class="flex-fill d-flex"> <div class="flex-fill d-flex">
<gl-icon name="search" class="gl-absolute gl-top-3 gl-left-3 tree-list-icon" /> <gl-icon name="search" class="gl-absolute gl-top-3 gl-left-3 tree-list-icon" />

View File

@ -437,6 +437,8 @@ export const assignDiscussionsToDiff = (
}; };
export const removeDiscussionsFromDiff = ({ commit }, removeDiscussion) => { export const removeDiscussionsFromDiff = ({ commit }, removeDiscussion) => {
if (!removeDiscussion.diff_file) return;
const { const {
diff_file: { file_hash: fileHash }, diff_file: { file_hash: fileHash },
line_code: lineCode, line_code: lineCode,

View File

@ -239,6 +239,16 @@
"always" "always"
] ]
}, },
"access": {
"markdownDescription": "Configure who can access the artifacts. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifactsaccess).",
"default": "all",
"type": "string",
"enum": [
"none",
"developer",
"all"
]
},
"expire_in": { "expire_in": {
"type": "string", "type": "string",
"markdownDescription": "How long artifacts should be kept. They are saved 30 days by default. Artifacts that have expired are removed periodically via cron job. Supports a wide variety of formats, e.g. '1 week', '3 mins 4 sec', '2 hrs 20 min', '2h20min', '6 mos 1 day', '47 yrs 6 mos and 4d', '3 weeks and 2 days'. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifactsexpire_in).", "markdownDescription": "How long artifacts should be kept. They are saved 30 days by default. Artifacts that have expired are removed periodically via cron job. Supports a wide variety of formats, e.g. '1 week', '3 mins 4 sec', '2 hrs 20 min', '2h20min', '6 mos 1 day', '47 yrs 6 mos and 4d', '3 weeks and 2 days'. [Learn More](https://docs.gitlab.com/ee/ci/yaml/#artifactsexpire_in).",

View File

@ -21,6 +21,7 @@ import ConfirmRollbackModal from './confirm_rollback_modal.vue';
import DeleteEnvironmentModal from './delete_environment_modal.vue'; import DeleteEnvironmentModal from './delete_environment_modal.vue';
import CanaryUpdateModal from './canary_update_modal.vue'; import CanaryUpdateModal from './canary_update_modal.vue';
import EmptyState from './empty_state.vue'; import EmptyState from './empty_state.vue';
import EnviromentsAppSkeletonLoader from './environments_app_skeleton_loader.vue';
export default { export default {
components: { components: {
@ -28,6 +29,7 @@ export default {
CanaryUpdateModal, CanaryUpdateModal,
ConfirmRollbackModal, ConfirmRollbackModal,
EmptyState, EmptyState,
EnviromentsAppSkeletonLoader,
EnvironmentFolder, EnvironmentFolder,
EnableReviewAppModal, EnableReviewAppModal,
EnvironmentItem, EnvironmentItem,
@ -128,6 +130,9 @@ export default {
hasEnvironments() { hasEnvironments() {
return this.environments.length > 0 || this.folders.length > 0; return this.environments.length > 0 || this.folders.length > 0;
}, },
loading() {
return this.$apollo.queries.environmentApp.loading;
},
showEmptyState() { showEmptyState() {
return !this.$apollo.queries.environmentApp.loading && !this.hasEnvironments; return !this.$apollo.queries.environmentApp.loading && !this.hasEnvironments;
}, },
@ -144,7 +149,7 @@ export default {
return this.activeCount > 0 || this.stoppedCount > 0; return this.activeCount > 0 || this.stoppedCount > 0;
}, },
showContent() { showContent() {
return this.hasAnyEnvironment || this.hasSearch; return !this.loading && (this.hasAnyEnvironment || this.hasSearch);
}, },
addEnvironment() { addEnvironment() {
if (!this.canCreateEnvironment) { if (!this.canCreateEnvironment) {
@ -268,6 +273,7 @@ export default {
<stop-environment-modal :environment="environmentToStop" graphql /> <stop-environment-modal :environment="environmentToStop" graphql />
<confirm-rollback-modal :environment="environmentToRollback" graphql /> <confirm-rollback-modal :environment="environmentToRollback" graphql />
<canary-update-modal :environment="environmentToChangeCanary" :weight="weight" /> <canary-update-modal :environment="environmentToChangeCanary" :weight="weight" />
<enviroments-app-skeleton-loader v-if="loading" :i18n="$options.i18n" :search-value="search" />
<template v-if="showContent"> <template v-if="showContent">
<gl-tabs <gl-tabs
:action-secondary="openReviewAppModal" :action-secondary="openReviewAppModal"

View File

@ -0,0 +1,77 @@
<script>
import {
GlLoadingIcon,
GlSkeletonLoader,
GlBadge,
GlSearchBoxByType,
GlTab,
GlTabs,
} from '@gitlab/ui';
export default {
components: {
GlLoadingIcon,
GlSkeletonLoader,
GlBadge,
GlSearchBoxByType,
GlTab,
GlTabs,
},
props: {
i18n: {
type: Object,
required: true,
},
searchValue: {
type: String,
required: true,
},
},
};
</script>
<template>
<div>
<gl-tabs>
<gl-tab :disabled="true">
<template #title>
<span>{{ $props.i18n.active }}</span>
<gl-badge size="sm" class="gl-tab-counter-badge">
<gl-loading-icon label="" size="sm" color="dark" variant="dots" :inline="true" />
</gl-badge>
</template>
</gl-tab>
<gl-tab :disabled="true">
<template #title>
<span>{{ $props.i18n.stopped }}</span>
<gl-badge size="sm" class="gl-tab-counter-badge">
<gl-loading-icon label="" size="sm" color="dark" variant="dots" :inline="true" />
</gl-badge>
</template>
</gl-tab>
</gl-tabs>
<gl-search-box-by-type
class="gl-mb-4"
:disabled="true"
:value="$props.searchValue"
:placeholder="$props.i18n.searchPlaceholder"
/>
<div class="gl-pt-6">
<gl-skeleton-loader :width="1248" :height="200">
<rect x="8" y="0" width="24" height="24" />
<rect x="46" y="5" width="247" height="15" />
<rect x="0" y="49" width="1248" height="1" />
<rect x="8" y="64" width="24" height="24" />
<rect x="46" y="69" width="247" height="15" />
<rect x="0" y="113" width="1248" height="1" />
<rect x="1168" y="64" width="80" height="32" />
<rect x="8" y="128" width="24" height="24" />
<rect x="46" y="133" width="247" height="15" />
<rect x="0" y="177" width="1248" height="1" />
<rect x="1168" y="128" width="80" height="32" />
</gl-skeleton-loader>
</div>
</div>
</template>

View File

@ -44,9 +44,6 @@ export default {
copyProjectId() { copyProjectId() {
return sprintf(s__('ProjectPage|Project ID: %{id}'), { id: this.projectId }); return sprintf(s__('ProjectPage|Project ID: %{id}'), { id: this.projectId });
}, },
isUserAdmin() {
return this.adminPath !== null && this.adminPath !== '';
},
}, },
i18n: { i18n: {
adminButtonTooltip: __('View project in admin area'), adminButtonTooltip: __('View project in admin area'),
@ -59,7 +56,7 @@ export default {
class="gl-align-items-center gl-display-flex gl-flex-wrap gl-gap-3 gl-justify-content-md-end project-repo-buttons" class="gl-align-items-center gl-display-flex gl-flex-wrap gl-gap-3 gl-justify-content-md-end project-repo-buttons"
> >
<gl-button <gl-button
v-if="isUserAdmin" v-if="adminPath"
v-gl-tooltip v-gl-tooltip
:aria-label="$options.i18n.adminButtonTooltip" :aria-label="$options.i18n.adminButtonTooltip"
:href="adminPath" :href="adminPath"

View File

@ -106,7 +106,9 @@ export default {
<span> {{ contactCount }} </span> <span> {{ contactCount }} </span>
</div> </div>
<div class="hide-collapsed help-button gl-float-right"> <div class="hide-collapsed help-button gl-float-right">
<gl-link :href="$options.crmDocsLink" target="_blank"><gl-icon name="question-o" /></gl-link> <gl-link :href="$options.crmDocsLink" target="_blank"
><gl-icon name="question-o" class="gl-text-blue-600"
/></gl-link>
</div> </div>
<div class="title hide-collapsed gl-mb-2 gl-line-height-20 gl-font-weight-bold"> <div class="title hide-collapsed gl-mb-2 gl-line-height-20 gl-font-weight-bold">
{{ contactsLabel }} {{ contactsLabel }}

View File

@ -8,6 +8,7 @@ class ApplicationRecord < ActiveRecord::Base
include CrossDatabaseModification include CrossDatabaseModification
include SensitiveSerializableHash include SensitiveSerializableHash
include ResetOnColumnErrors include ResetOnColumnErrors
include HasCheckConstraints
self.abstract_class = true self.abstract_class = true
@ -130,6 +131,11 @@ class ApplicationRecord < ActiveRecord::Base
object.is_a?(self) object.is_a?(self)
end end
def self.nullable_column?(column_name)
columns.find { |column| column.name == column_name }.null &&
!not_null_check?(column_name)
end
def readable_by?(user) def readable_by?(user)
Ability.allowed?(user, "read_#{to_ability_name}".to_sym, self) Ability.allowed?(user, "read_#{to_ability_name}".to_sym, self)
end end

View File

@ -726,12 +726,24 @@ module Ci
job_artifacts_archive.public_access? job_artifacts_archive.public_access?
end end
def artifact_is_public_in_config? def artifacts_no_access?
return false if job_artifacts_archive.nil? # To backward compatibility return false if no artifacts found
job_artifacts_archive.none_access?
end
def artifact_access_setting_in_config
artifacts_public = options.dig(:artifacts, :public) artifacts_public = options.dig(:artifacts, :public)
artifacts_access = options.dig(:artifacts, :access)
return true if artifacts_public.nil? # Default artifacts:public to true raise ArgumentError, 'artifacts:public and artifacts:access are mutually exclusive' if !artifacts_public.nil? && !artifacts_access.nil?
artifacts_public return :public if artifacts_public == true || artifacts_access == 'all'
return :private if artifacts_public == false || artifacts_access == 'developer'
return :none if artifacts_access == 'none'
# default behaviour
:public
end end
def artifacts_metadata_entry(path, **options) def artifacts_metadata_entry(path, **options)

View File

@ -19,7 +19,7 @@ module Ci
self.primary_key = :id self.primary_key = :id
self.sequence_name = :ci_job_artifacts_id_seq self.sequence_name = :ci_job_artifacts_id_seq
enum accessibility: { public: 0, private: 1 }, _suffix: true enum accessibility: { public: 0, private: 1, none: 2 }, _suffix: true
PLAN_LIMIT_PREFIX = 'ci_max_artifact_size_' PLAN_LIMIT_PREFIX = 'ci_max_artifact_size_'
@ -227,6 +227,10 @@ module Ci
public_accessibility? public_accessibility?
end end
def none_access?
none_accessibility?
end
private private
def store_file_in_transaction! def store_file_in_transaction!

View File

@ -121,5 +121,25 @@ module Enums
def self.package_manager_from_trivy_pkg_type(pkg_type) def self.package_manager_from_trivy_pkg_type(pkg_type)
PACKAGE_MANAGERS_FROM_TRIVY_PKG_TYPE[pkg_type] PACKAGE_MANAGERS_FROM_TRIVY_PKG_TYPE[pkg_type]
end end
# We do not use the namespaced names for OS component types even
# if the PURL specification declares otherwise, since this will
# preserve the name format established by the container-scanning
# analyzers. For example, a namespaced name for an Alpine cURL component
# might look like `apk/curl` when found by an SBOM generator. If found
# by a container-scanning analyzer, this same component would be reported
# as `curl`. The differences in naming would impact dependency and
# vulnerability deduplication, and if left as is would create dependency
# lists and vulnerability reports that are inaccurate.
#
# For full details, see https://gitlab.com/gitlab-org/gitlab/-/issues/442847
def self.use_namespaced_name?(purl_type)
case purl_type
when 'apk', 'deb', 'rpm'
false
else
true
end
end
end end
end end

View File

@ -0,0 +1,32 @@
# frozen_string_literal: true
module HasCheckConstraints
extend ActiveSupport::Concern
NOT_NULL_CHECK_PATTERN = /IS NOT NULL/i
class_methods do
def not_null_check?(column_name)
constraints.any? do |constraint|
constraint.constraint_valid &&
constraint.column_names.include?(column_name) &&
NOT_NULL_CHECK_PATTERN.match(constraint.definition)
end
end
def clear_constraints_cache!
@constraints = nil
end
private
def constraints
@constraints ||= Gitlab::Database::PostgresConstraint.check_constraints
.by_table_identifier(fully_qualified_table_name)
end
def fully_qualified_table_name
"#{connection.current_schema}.#{table_name}"
end
end
end

View File

@ -679,6 +679,18 @@ class Integration < ApplicationRecord
category == :ci category == :ci
end end
def deactivate!
update(active: false)
end
def activate!
update(active: true)
end
def toggle!
active? ? deactivate! : activate!
end
private private
# Ancestors sorted by hierarchy depth in bottom-top order. # Ancestors sorted by hierarchy depth in bottom-top order.

View File

@ -2460,8 +2460,7 @@ class Project < ApplicationRecord
Gitlab::Ci::Variables::Collection.new Gitlab::Ci::Variables::Collection.new
.append(key: 'CI', value: 'true') .append(key: 'CI', value: 'true')
.append(key: 'GITLAB_CI', value: 'true') .append(key: 'GITLAB_CI', value: 'true')
.append(key: 'CI_COMPONENT_FQDN', value: Gitlab.config.gitlab_ci.component_fqdn) .append(key: 'CI_SERVER_FQDN', value: Gitlab.config.gitlab_ci.server_fqdn)
.append(key: 'CI_SERVER_FQDN', value: Gitlab.config.gitlab_ci.component_fqdn)
.append(key: 'CI_SERVER_URL', value: Gitlab.config.gitlab.url) .append(key: 'CI_SERVER_URL', value: Gitlab.config.gitlab.url)
.append(key: 'CI_SERVER_HOST', value: Gitlab.config.gitlab.host) .append(key: 'CI_SERVER_HOST', value: Gitlab.config.gitlab.host)
.append(key: 'CI_SERVER_PORT', value: Gitlab.config.gitlab.port.to_s) .append(key: 'CI_SERVER_PORT', value: Gitlab.config.gitlab.port.to_s)

View File

@ -40,6 +40,10 @@ module Ci
@subject.artifacts_public? @subject.artifacts_public?
end end
condition(:artifacts_none, scope: :subject) do
@subject.artifacts_no_access?
end
condition(:terminal, scope: :subject) do condition(:terminal, scope: :subject) do
@subject.has_terminal? @subject.has_terminal?
end end
@ -116,7 +120,7 @@ module Ci
prevent :create_build_service_proxy prevent :create_build_service_proxy
end end
rule { can_read_project_build }.enable :read_job_artifacts rule { can_read_project_build & ~artifacts_none }.enable :read_job_artifacts
rule { ~artifacts_public & ~project_developer }.prevent :read_job_artifacts rule { ~artifacts_public & ~project_developer }.prevent :read_job_artifacts
end end
end end

View File

@ -8,6 +8,10 @@ module Ci
@subject.public_access? @subject.public_access?
end end
condition(:none_access, scope: :subject) do
@subject.none_access?
end
condition(:can_read_project_build, scope: :subject) do condition(:can_read_project_build, scope: :subject) do
can?(:read_build, @subject.job.project) can?(:read_build, @subject.job.project)
end end
@ -16,7 +20,7 @@ module Ci
can?(:developer_access, @subject.job.project) can?(:developer_access, @subject.job.project)
end end
rule { can_read_project_build }.enable :read_job_artifacts rule { can_read_project_build & ~none_access }.enable :read_job_artifacts
rule { ~public_access & ~has_access_to_project }.prevent :read_job_artifacts rule { ~public_access & ~has_access_to_project }.prevent :read_job_artifacts
end end
end end

View File

@ -130,7 +130,7 @@ module Ci
return accessibility if accessibility.present? return accessibility if accessibility.present?
job.artifact_is_public_in_config? ? :public : :private job.artifact_access_setting_in_config
end end
def parse_artifact(artifact) def parse_artifact(artifact)

View File

@ -2550,6 +2550,15 @@
:weight: 1 :weight: 1
:idempotent: false :idempotent: false
:tags: [] :tags: []
- :name: bitbucket_import_stage_import_users
:worker_name: Gitlab::BitbucketImport::Stage::ImportUsersWorker
:feature_category: :importers
:has_external_dependencies: true
:urgency: :low
:resource_boundary: :unknown
:weight: 1
:idempotent: true
:tags: []
- :name: bitbucket_server_import_advance_stage - :name: bitbucket_server_import_advance_stage
:worker_name: Gitlab::BitbucketServerImport::AdvanceStageWorker :worker_name: Gitlab::BitbucketServerImport::AdvanceStageWorker
:feature_category: :importers :feature_category: :importers

View File

@ -13,6 +13,10 @@ module Gitlab
importer.execute importer.execute
if Feature.enabled?(:bitbucket_cloud_convert_mentions_to_users, project.creator)
return ImportUsersWorker.perform_async(project.id)
end
ImportPullRequestsWorker.perform_async(project.id) ImportPullRequestsWorker.perform_async(project.id)
end end

View File

@ -0,0 +1,27 @@
# frozen_string_literal: true
module Gitlab
module BitbucketImport
module Stage
class ImportUsersWorker
include StageMethods
idempotent!
private
def import(project)
importer = importer_class.new(project)
importer.execute
ImportPullRequestsWorker.perform_async(project.id)
end
def importer_class
Importers::UsersImporter
end
end
end
end
end

View File

@ -0,0 +1,9 @@
---
name: bitbucket_cloud_convert_mentions_to_users
feature_issue_url:
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144923
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442484
milestone: '16.10'
group: group::import and integrate
type: gitlab_com_derisk
default_enabled: false

View File

@ -266,7 +266,7 @@ Settings['gitlab_ci'] ||= {}
Settings.gitlab_ci['shared_runners_enabled'] = true if Settings.gitlab_ci['shared_runners_enabled'].nil? Settings.gitlab_ci['shared_runners_enabled'] = true if Settings.gitlab_ci['shared_runners_enabled'].nil?
Settings.gitlab_ci['builds_path'] = Settings.absolute(Settings.gitlab_ci['builds_path'] || "builds/") Settings.gitlab_ci['builds_path'] = Settings.absolute(Settings.gitlab_ci['builds_path'] || "builds/")
Settings.gitlab_ci['url'] ||= Settings.__send__(:build_gitlab_ci_url) Settings.gitlab_ci['url'] ||= Settings.__send__(:build_gitlab_ci_url)
Settings.gitlab_ci['component_fqdn'] ||= Settings.__send__(:build_ci_component_fqdn) Settings.gitlab_ci['server_fqdn'] ||= Settings.__send__(:build_ci_server_fqdn)
# #
# CI Secure Files # CI Secure Files

View File

@ -5,8 +5,7 @@ require 'gitlab-http'
Gitlab::HTTP_V2.configure do |config| Gitlab::HTTP_V2.configure do |config|
config.allowed_internal_uris = [ config.allowed_internal_uris = [
URI::HTTP.build( (Gitlab.config.gitlab.protocol == 'https' ? URI::HTTPS : URI::HTTP).build(
scheme: Gitlab.config.gitlab.protocol,
host: Gitlab.config.gitlab.host, host: Gitlab.config.gitlab.host,
port: Gitlab.config.gitlab.port port: Gitlab.config.gitlab.port
), ),

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_workflows_branch_pipeli
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_workflows_mergerequest_
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_helm_2to3_monthly
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_deploy_ecs_monthly
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_deploy_ec2_monthly
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_deploy_monthly
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_build_monthly
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_test_monthly
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_deploy_latest_mont
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_cf_provision_month
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_build_latest_month
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_helm_2to3
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_test_mont
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_cf_provis
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: removed status: removed
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_build_lat
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: removed status: removed
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_build_mon
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: "14.4" milestone: "14.4"

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_workflows_branch_pipeli
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_workflows_mergerequest_
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_helm_2to3_weekly
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_deploy_ecs_weekly
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_deploy_ec2_weekly
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_deploy_weekly
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_build_weekly
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_test_weekly
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_deploy_latest_week
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_cf_provision_weekl
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_jobs_build_latest_weekl
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_helm_2to3
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_test_week
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_cf_provis
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: removed status: removed
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_build_lat
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: removed status: removed
milestone: '14.3' milestone: '14.3'

View File

@ -3,7 +3,7 @@ key_path: redis_hll_counters.ci_templates.p_ci_templates_implicit_jobs_build_wee
description: '' description: ''
product_section: '' product_section: ''
product_stage: '' product_stage: ''
product_group: '' product_group: pipeline_authoring
value_type: number value_type: number
status: active status: active
milestone: "14.4" milestone: "14.4"

View File

@ -11,7 +11,7 @@ Settings = GitlabSettings.load(file, Rails.env) do
on_standard_port?(gitlab) on_standard_port?(gitlab)
end end
def build_ci_component_fqdn def build_ci_server_fqdn
custom_port = ":#{gitlab.port}" unless on_standard_port?(gitlab) custom_port = ":#{gitlab.port}" unless on_standard_port?(gitlab)
[ [

View File

@ -111,6 +111,8 @@
- 1 - 1
- - bitbucket_import_stage_import_repository - - bitbucket_import_stage_import_repository
- 1 - 1
- - bitbucket_import_stage_import_users
- 1
- - bitbucket_server_import_advance_stage - - bitbucket_server_import_advance_stage
- 1 - 1
- - bitbucket_server_import_import_lfs_object - - bitbucket_server_import_import_lfs_object
@ -685,6 +687,8 @@
- 1 - 1
- - search_zoekt_project_transfer - - search_zoekt_project_transfer
- 1 - 1
- - security_delete_orchestration_configuration
- 1
- - security_generate_policy_violation_comment - - security_generate_policy_violation_comment
- 1 - 1
- - security_orchestration_configuration_create_bot - - security_orchestration_configuration_create_bot
@ -717,6 +721,8 @@
- 1 - 1
- - security_sync_scan_policies - - security_sync_scan_policies
- 1 - 1
- - security_unassign_redundant_policy_configurations
- 1
- - security_unenforceable_policy_rules_notification - - security_unenforceable_policy_rules_notification
- 1 - 1
- - security_unenforceable_policy_rules_pipeline_notification - - security_unenforceable_policy_rules_pipeline_notification

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class AddIndexScanResultPoliciesOnConfigurationIdAndIdAndUpdatedAt < Gitlab::Database::Migration[2.2]
milestone '16.10'
disable_ddl_transaction!
INDEX_NAME = :idx_scan_result_policies_on_configuration_id_id_updated_at
TABLE_NAME = :scan_result_policies
def up
add_concurrent_index(TABLE_NAME, %i[security_orchestration_policy_configuration_id id updated_at], name: INDEX_NAME)
end
def down
remove_concurrent_index_by_name(TABLE_NAME, INDEX_NAME)
end
end

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class AddIndexApprovalProjectRulesOnConfigurationIdAndId < Gitlab::Database::Migration[2.2]
milestone '16.10'
disable_ddl_transaction!
INDEX_NAME = :idx_approval_project_rules_on_configuration_id_and_id
TABLE_NAME = :approval_project_rules
def up
add_concurrent_index(TABLE_NAME, %i[security_orchestration_policy_configuration_id id], name: INDEX_NAME)
end
def down
remove_concurrent_index_by_name(TABLE_NAME, INDEX_NAME)
end
end

View File

@ -0,0 +1,17 @@
# frozen_string_literal: true
class ScheduleIndexApprovalMergeRequestRulesOnConfigIdAndIdAndUpdatedAt < Gitlab::Database::Migration[2.2]
milestone '16.10'
INDEX_NAME = :idx_approval_mr_rules_on_config_id_and_id_and_updated_at
TABLE_NAME = :approval_merge_request_rules
COLUMNS = %i[security_orchestration_policy_configuration_id id updated_at]
def up
prepare_async_index(TABLE_NAME, COLUMNS, name: INDEX_NAME)
end
def down
unprepare_async_index(TABLE_NAME, COLUMNS, name: INDEX_NAME)
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class ScheduleIndexMergeRequestsOnUnmergedStateId < Gitlab::Database::Migration[2.2]
milestone '16.10'
INDEX_NAME = :idx_merge_requests_on_unmerged_state_id
TABLE_NAME = :merge_requests
def up
prepare_async_index(TABLE_NAME, :id, name: INDEX_NAME, where: "state_id <> 3")
end
def down
unprepare_async_index(TABLE_NAME, :id, name: INDEX_NAME)
end
end

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class AddIndexScanResultPolicyViolationsOnScanResultPolicyIdAndId < Gitlab::Database::Migration[2.2]
milestone '16.10'
disable_ddl_transaction!
INDEX_NAME = :idx_scan_result_policy_violations_on_policy_id_and_id
TABLE_NAME = :scan_result_policy_violations
def up
add_concurrent_index(TABLE_NAME, %i[scan_result_policy_id id], name: INDEX_NAME)
end
def down
remove_concurrent_index_by_name(TABLE_NAME, INDEX_NAME)
end
end

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class RemoveIndexApprovalProjectRulesOnSecOrchestrationConfigId < Gitlab::Database::Migration[2.2]
milestone '16.10'
disable_ddl_transaction!
TABLE_NAME = :approval_project_rules
INDEX_NAME = :idx_approval_project_rules_on_sec_orchestration_config_id
def up
remove_concurrent_index_by_name(TABLE_NAME, INDEX_NAME)
end
def down
add_concurrent_index(TABLE_NAME, :security_orchestration_policy_configuration_id, name: INDEX_NAME)
end
end

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
class AddNullCheckConstraintForVulnerabilityReadsTraversalIds < Gitlab::Database::Migration[2.2]
disable_ddl_transaction!
milestone '16.11'
def up
add_not_null_constraint :vulnerability_reads, :traversal_ids, validate: false
end
def down
remove_not_null_constraint :vulnerability_reads, :traversal_ids
end
end

View File

@ -0,0 +1,15 @@
# frozen_string_literal: true
class PrepareAsyncTraversalIdsCheckConstraintValidation < Gitlab::Database::Migration[2.2]
milestone '16.11'
CONSTRAINT_NAME = 'check_f5ba7c2496'
def up
prepare_async_check_constraint_validation :vulnerability_reads, name: CONSTRAINT_NAME
end
def down
unprepare_async_check_constraint_validation :vulnerability_reads, name: CONSTRAINT_NAME
end
end

View File

@ -0,0 +1 @@
4745de5adaef6c0ea8c669317111b1568b8abf1f6c4a565db464f6bb8b59e70a

View File

@ -0,0 +1 @@
0287ede4aceee941c41c3b8f1e6a22bdbdd793b4b53206f44c9e56f44f22b97f

View File

@ -0,0 +1 @@
839b964e455dbd577ab389accb922922b99148a847d01d9164d832f68b0e5547

View File

@ -0,0 +1 @@
93148a82bf2a7021b282420ee13dab381fb05dc878902bc2a1e1e98ff81dda0a

View File

@ -0,0 +1 @@
c676560059b9cf10b47a4ca7a8b92149d92bb261bde3cfee1043ab7318801aff

View File

@ -0,0 +1 @@
f1f8f01acb0b0d70de398dd48bea37f60e5d0da2799ff31f5b3915e566b280f3

View File

@ -0,0 +1 @@
13de6dff291398df87dc95a81e8d4f7f8ce7a3f22fcb3df39006e0b386d369cf

View File

@ -0,0 +1 @@
45f5f3988b6fac58c19dc5bbe74eedfa1d697746c83493f478600749c25abc46

View File

@ -20579,6 +20579,9 @@ ALTER TABLE sprints
ALTER TABLE web_hook_logs ALTER TABLE web_hook_logs
ADD CONSTRAINT check_df72cb58f5 CHECK ((char_length(url_hash) <= 44)) NOT VALID; ADD CONSTRAINT check_df72cb58f5 CHECK ((char_length(url_hash) <= 44)) NOT VALID;
ALTER TABLE vulnerability_reads
ADD CONSTRAINT check_f5ba7c2496 CHECK ((traversal_ids IS NOT NULL)) NOT VALID;
ALTER TABLE projects ALTER TABLE projects
ADD CONSTRAINT check_fa75869cb1 CHECK ((project_namespace_id IS NOT NULL)) NOT VALID; ADD CONSTRAINT check_fa75869cb1 CHECK ((project_namespace_id IS NOT NULL)) NOT VALID;
@ -23668,9 +23671,9 @@ CREATE INDEX idx_approval_merge_request_rules_on_scan_result_policy_id ON approv
CREATE INDEX idx_approval_merge_request_rules_on_sec_orchestration_config_id ON approval_merge_request_rules USING btree (security_orchestration_policy_configuration_id); CREATE INDEX idx_approval_merge_request_rules_on_sec_orchestration_config_id ON approval_merge_request_rules USING btree (security_orchestration_policy_configuration_id);
CREATE INDEX idx_approval_project_rules_on_scan_result_policy_id ON approval_project_rules USING btree (scan_result_policy_id); CREATE INDEX idx_approval_project_rules_on_configuration_id_and_id ON approval_project_rules USING btree (security_orchestration_policy_configuration_id, id);
CREATE INDEX idx_approval_project_rules_on_sec_orchestration_config_id ON approval_project_rules USING btree (security_orchestration_policy_configuration_id); CREATE INDEX idx_approval_project_rules_on_scan_result_policy_id ON approval_project_rules USING btree (scan_result_policy_id);
CREATE INDEX idx_audit_events_group_external_destinations_on_group_id ON audit_events_group_external_streaming_destinations USING btree (group_id); CREATE INDEX idx_audit_events_group_external_destinations_on_group_id ON audit_events_group_external_streaming_destinations USING btree (group_id);
@ -23868,6 +23871,10 @@ CREATE INDEX idx_sbom_occurrences_on_project_id_and_source_id ON sbom_occurrence
CREATE UNIQUE INDEX idx_sbom_source_packages_on_name_and_purl_type ON sbom_source_packages USING btree (name, purl_type); CREATE UNIQUE INDEX idx_sbom_source_packages_on_name_and_purl_type ON sbom_source_packages USING btree (name, purl_type);
CREATE INDEX idx_scan_result_policies_on_configuration_id_id_updated_at ON scan_result_policies USING btree (security_orchestration_policy_configuration_id, id, updated_at);
CREATE INDEX idx_scan_result_policy_violations_on_policy_id_and_id ON scan_result_policy_violations USING btree (scan_result_policy_id, id);
CREATE UNIQUE INDEX idx_security_scans_on_build_and_scan_type ON security_scans USING btree (build_id, scan_type); CREATE UNIQUE INDEX idx_security_scans_on_build_and_scan_type ON security_scans USING btree (build_id, scan_type);
CREATE INDEX idx_security_scans_on_scan_type ON security_scans USING btree (scan_type); CREATE INDEX idx_security_scans_on_scan_type ON security_scans USING btree (scan_type);

View File

@ -101,7 +101,8 @@ To enable merge trains:
1. On the left sidebar, select **Search or go to** and find your project. 1. On the left sidebar, select **Search or go to** and find your project.
1. Select **Settings > Merge requests**. 1. Select **Settings > Merge requests**.
1. In the **Merge method** section, verify that **Merge commit** is selected. 1. In GitLab 16.4 and earlier, in the **Merge method** section, verify that **Merge commit** is selected.
In GitLab 16.5 and later, you can use any merge method.
1. In the **Merge options** section, ensure **Enable merged results pipelines** is enabled 1. In the **Merge options** section, ensure **Enable merged results pipelines** is enabled
and select **Enable merge trains**. and select **Enable merge trains**.
1. Select **Save changes**. 1. Select **Save changes**.
@ -173,7 +174,7 @@ Merging immediately can use a lot of CI/CD resources. Use this option
only in critical situations. only in critical situations.
NOTE: NOTE:
The **merge immediately** option may not be available if your project utilizes the [fast-forward](../../user/project/merge_requests/methods/index.md#fast-forward-merge) The **merge immediately** option may not be available if your project uses the [fast-forward](../../user/project/merge_requests/methods/index.md#fast-forward-merge)
merge method and the source branch is behind the target branch. See [issue 434070](https://gitlab.com/gitlab-org/gitlab/-/issues/434070) for more details. merge method and the source branch is behind the target branch. See [issue 434070](https://gitlab.com/gitlab-org/gitlab/-/issues/434070) for more details.
### Allow merge trains to be skipped to merge immediately without restarting merge train pipelines ### Allow merge trains to be skipped to merge immediately without restarting merge train pipelines

View File

@ -1424,6 +1424,10 @@ job:
> - [Updated](https://gitlab.com/gitlab-org/gitlab/-/issues/322454) in GitLab 15.10. Artifacts created with `artifacts:public` before 15.10 are not guaranteed to remain private after this update. > - [Updated](https://gitlab.com/gitlab-org/gitlab/-/issues/322454) in GitLab 15.10. Artifacts created with `artifacts:public` before 15.10 are not guaranteed to remain private after this update.
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/294503) in GitLab 16.7. Feature flag `non_public_artifacts` removed. > - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/issues/294503) in GitLab 16.7. Feature flag `non_public_artifacts` removed.
NOTE:
`artifacts:public` is now superceded by [`artifacts:access`](#artifactsaccess) which
has more options.
Use `artifacts:public` to determine whether the job artifacts should be Use `artifacts:public` to determine whether the job artifacts should be
publicly available. publicly available.
@ -1448,6 +1452,31 @@ job:
public: false public: false
``` ```
### `artifacts:access`
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/145206) in GitLab 16.10.
Use `artifacts:access` to determine who can access the job artifacts.
You cannot use [`artifacts:public`](#artifactspublic) and `artifacts:access` in the same job.
**Keyword type**: Job keyword. You can use it only as part of a job.
**Possible inputs**:
- `all` (default): Artifacts in public pipelines are available for download by anyone, including anonymous,
guest, and reporter users.
- `developer`: Artifacts are only available for download by users with the Developer role or higher.
- `none`: Artifacts are not available for download by anyone.
**Example of `artifacts:access`**:
```yaml
job:
artifacts:
access: 'developer'
```
#### `artifacts:reports` #### `artifacts:reports`
Use [`artifacts:reports`](artifacts_reports.md) to collect artifacts generated by Use [`artifacts:reports`](artifacts_reports.md) to collect artifacts generated by

View File

@ -11,6 +11,7 @@ DETAILS:
**Offering:** GitLab.com, Self-managed, GitLab Dedicated **Offering:** GitLab.com, Self-managed, GitLab Dedicated
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/381902) in GitLab 15.8, GitLab no longer automatically creates namespaces or groups that don't exist. GitLab also no longer falls back to using the user's personal namespace if the namespace or group name is taken. > - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/381902) in GitLab 15.8, GitLab no longer automatically creates namespaces or groups that don't exist. GitLab also no longer falls back to using the user's personal namespace if the namespace or group name is taken.
> - Ability to import projects with a `.` in their path [added](https://gitlab.com/gitlab-org/gitlab/-/issues/434175) in GitLab 16.11.
Import your projects from Gitea to GitLab. Import your projects from Gitea to GitLab.
@ -28,8 +29,6 @@ created as private in GitLab as well.
## Known issues ## Known issues
- You must rename projects with a `.` in their path for all items to be imported correctly.
For more information, see [issue 434175](https://gitlab.com/gitlab-org/gitlab/-/issues/434175).
- Because Gitea is not an OAuth provider, the author or assignee cannot be mapped to users on - Because Gitea is not an OAuth provider, the author or assignee cannot be mapped to users on
your GitLab instance. The project creator (usually the user who started the import process) your GitLab instance. The project creator (usually the user who started the import process)
is then set as the author. For issues, you can still see the original Gitea author. is then set as the author. For issues, you can still see the original Gitea author.

View File

@ -14,22 +14,22 @@ module Bitbucket
end end
def issues(repo) def issues(repo)
path = "/repositories/#{repo}/issues" path = "/repositories/#{repo}/issues?sort=created_on"
get_collection(path, :issue) get_collection(path, :issue)
end end
def issue_comments(repo, issue_id) def issue_comments(repo, issue_id)
path = "/repositories/#{repo}/issues/#{issue_id}/comments" path = "/repositories/#{repo}/issues/#{issue_id}/comments?sort=created_on"
get_collection(path, :comment) get_collection(path, :comment)
end end
def pull_requests(repo) def pull_requests(repo)
path = "/repositories/#{repo}/pullrequests?state=ALL" path = "/repositories/#{repo}/pullrequests?state=ALL&sort=created_on"
get_collection(path, :pull_request) get_collection(path, :pull_request)
end end
def pull_request_comments(repo, pull_request) def pull_request_comments(repo, pull_request)
path = "/repositories/#{repo}/pullrequests/#{pull_request}/comments" path = "/repositories/#{repo}/pullrequests/#{pull_request}/comments?sort=created_on"
get_collection(path, :pull_request_comment) get_collection(path, :pull_request_comment)
end end
@ -44,7 +44,7 @@ module Bitbucket
end end
def repos(filter: nil) def repos(filter: nil)
path = "/repositories?role=member" path = "/repositories?role=member&sort=created_on"
path += "&q=name~\"#{filter}\"" if filter path += "&q=name~\"#{filter}\"" if filter
get_collection(path, :repo) get_collection(path, :repo)
@ -57,10 +57,15 @@ module Bitbucket
end end
end end
def users(workspace_key, page_number: nil, limit: nil)
path = "/workspaces/#{workspace_key}/members"
get_collection(path, :user, page_number: page_number, limit: limit)
end
private private
def get_collection(path, type) def get_collection(path, type, page_number: nil, limit: nil)
paginator = Paginator.new(connection, path, type) paginator = Paginator.new(connection, path, type, page_number: page_number, limit: limit)
Collection.new(paginator) Collection.new(paginator)
end end
end end

View File

@ -4,23 +4,27 @@ module Bitbucket
class Paginator class Paginator
PAGE_LENGTH = 50 # The minimum length is 10 and the maximum is 100. PAGE_LENGTH = 50 # The minimum length is 10 and the maximum is 100.
def initialize(connection, url, type) def initialize(connection, url, type, page_number: nil, limit: nil)
@connection = connection @connection = connection
@type = type @type = type
@url = url @url = url
@page = nil @page_number = page_number
@limit = limit
@total = 0
end end
def items def items
raise StopIteration if over_limit?
raise StopIteration unless has_next_page? raise StopIteration unless has_next_page?
@page = fetch_next_page @page = fetch_next_page
@total += @page.items.count
@page.items @page.items
end end
private private
attr_reader :connection, :page, :url, :type attr_reader :connection, :page, :url, :type, :page_number, :limit
def has_next_page? def has_next_page?
page.nil? || page.next? page.nil? || page.next?
@ -30,8 +34,25 @@ module Bitbucket
page.nil? ? url : page.next page.nil? ? url : page.next
end end
def max_per_page
limit || PAGE_LENGTH
end
def over_limit?
return false unless limit
limit > 0 && @total >= limit
end
# Note to self for specs:
# - Allowed pagelen to be set by limit instead of just using PAGE_LENGTH
# - Allow specifying a starting page to grab one page at a time, so PageCounter can be used for logging
# - Added over_limit? to make sure only one page is called.
def fetch_next_page def fetch_next_page
parsed_response = connection.get(next_url, pagelen: PAGE_LENGTH, sort: :created_on) extra_query = { pagelen: max_per_page }
extra_query[:page] = page_number if page_number && limit
parsed_response = connection.get(next_url, extra_query)
Page.new(parsed_response, type) Page.new(parsed_response, type)
end end
end end

View File

@ -6,6 +6,24 @@ module Bitbucket
def username def username
raw['username'] raw['username']
end end
def account_id
user['account_id']
end
def name
user['display_name']
end
def nickname
user['nickname']
end
private
def user
raw['user']
end
end end
end end
end end

View File

@ -47,12 +47,16 @@ module ExtractsRef
strong_memoize_attr :commit strong_memoize_attr :commit
def tag def tag
return unless repository.tag_exists?(ref)
raw_commit = repository.find_tag(ref)&.dereferenced_target raw_commit = repository.find_tag(ref)&.dereferenced_target
::Commit.new(raw_commit, repository.container) if raw_commit ::Commit.new(raw_commit, repository.container) if raw_commit
end end
strong_memoize_attr :tag strong_memoize_attr :tag
def branch def branch
return unless repository.branch_exists?(ref)
raw_commit = repository.find_branch(ref)&.dereferenced_target raw_commit = repository.find_branch(ref)&.dereferenced_target
::Commit.new(raw_commit, repository.container) if raw_commit ::Commit.new(raw_commit, repository.container) if raw_commit
end end

View File

@ -0,0 +1,65 @@
# frozen_string_literal: true
module Gitlab
module BitbucketImport
module Importers
class UsersImporter
include Loggable
include Gitlab::Import::UserFromMention
BATCH_SIZE = 100
def initialize(project)
@project = project
@project_id = project.id
end
attr_reader :project, :project_id
def execute
log_info(import_stage: 'import_users', message: 'starting')
current = page_counter.current
loop do
log_info(
import_stage: 'import_users',
message: "importing page #{current} using batch size #{BATCH_SIZE}"
)
users = client.users(workspace_key, page_number: current, limit: BATCH_SIZE).to_a
break if users.empty?
cache_users(users)
current += 1
page_counter.set(current)
end
page_counter.expire!
log_info(import_stage: 'import_users', message: 'finished')
end
private
def cache_users(users)
# No-op for now
end
def client
@client ||= Bitbucket::Client.new(project.import_data.credentials)
end
def workspace_key
project.import_source.split('/').first
end
def page_counter
@page_counter ||= Gitlab::Import::PageCounter.new(project, :users, 'bitbucket-importer')
end
end
end
end
end

View File

@ -14,7 +14,7 @@ module Gitlab
end end
def self.fqdn_prefix def self.fqdn_prefix
"#{Settings.gitlab_ci['component_fqdn']}/" "#{Settings.gitlab_ci['server_fqdn']}/"
end end
def initialize(address:) def initialize(address:)

View File

@ -13,7 +13,8 @@ module Gitlab
include ::Gitlab::Config::Entry::Attributable include ::Gitlab::Config::Entry::Attributable
ALLOWED_WHEN = %w[on_success on_failure always].freeze ALLOWED_WHEN = %w[on_success on_failure always].freeze
ALLOWED_KEYS = %i[name untracked paths reports when expire_in expose_as exclude public].freeze ALLOWED_ACCESS = %w[none developer all].freeze
ALLOWED_KEYS = %i[name untracked paths reports when expire_in expose_as exclude public access].freeze
EXPOSE_AS_REGEX = /\A\w[-\w ]*\z/ EXPOSE_AS_REGEX = /\A\w[-\w ]*\z/
EXPOSE_AS_ERROR_MESSAGE = "can contain only letters, digits, '-', '_' and spaces" EXPOSE_AS_ERROR_MESSAGE = "can contain only letters, digits, '-', '_' and spaces"
@ -26,6 +27,8 @@ module Gitlab
validates :config, allowed_keys: ALLOWED_KEYS validates :config, allowed_keys: ALLOWED_KEYS
validates :paths, presence: true, if: :expose_as_present? validates :paths, presence: true, if: :expose_as_present?
validates :config, mutually_exclusive_keys: %i[access public]
with_options allow_nil: true do with_options allow_nil: true do
validates :name, type: String validates :name, type: String
validates :public, boolean: true validates :public, boolean: true
@ -44,6 +47,10 @@ module Gitlab
message: "should be one of: #{ALLOWED_WHEN.join(', ')}" message: "should be one of: #{ALLOWED_WHEN.join(', ')}"
} }
validates :expire_in, duration: { parser: ::Gitlab::Ci::Build::DurationParser } validates :expire_in, duration: { parser: ::Gitlab::Ci::Build::DurationParser }
validates :access, type: String, inclusion: {
in: ALLOWED_ACCESS,
message: "should be one of: #{ALLOWED_ACCESS.join(', ')}"
}
end end
end end

View File

@ -24,7 +24,7 @@ module Gitlab
override :url override :url
def url def url
File.join(Settings.build_ci_component_fqdn, project.full_path, '//', ci_config_path) File.join(Settings.build_ci_server_fqdn, project.full_path, '//', ci_config_path)
end end
private private

View File

@ -30,7 +30,7 @@ module Gitlab
end end
def purl_type def purl_type
purl.type purl&.type
end end
def type def type
@ -38,13 +38,7 @@ module Gitlab
end end
def name def name
return @name unless purl use_namespaced_name? ? [purl.namespace, purl.name].compact.join('/') : @name
[purl.namespace, purl.name].compact.join('/')
end
def name_without_namespace
@name
end end
def key def key
@ -81,6 +75,10 @@ module Gitlab
def purl_type_int(component) def purl_type_int(component)
::Enums::Sbom::PURL_TYPES.fetch(component.purl&.type&.to_sym, 0) ::Enums::Sbom::PURL_TYPES.fetch(component.purl&.type&.to_sym, 0)
end end
def use_namespaced_name?
purl.present? && Enums::Sbom.use_namespaced_name?(purl_type)
end
end end
end end
end end

View File

@ -29,7 +29,7 @@ module Gitlab
# Gitea plan to be GitHub compliant # Gitea plan to be GitHub compliant
if project.gitea_import? if project.gitea_import?
uri = URI.parse(project.import_url) uri = URI.parse(project.import_url)
host = "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}".sub(%r{/?[\w-]+/[\w-]+\.git\z}, '') host = "#{uri.scheme}://#{uri.host}:#{uri.port}#{uri.path}".sub(%r{/?[\w.-]+/[\w.-]+\.git\z}, '')
opts = { opts = {
host: host, host: host,
api_version: 'v1' api_version: 'v1'

View File

@ -89,7 +89,7 @@ module Gitlab
end end
def nullability(order_value, attribute_name) def nullability(order_value, attribute_name)
nullable = model_class.columns.find { |column| column.name == attribute_name }.null nullable = model_class.nullable_column?(attribute_name)
if nullable && order_value.is_a?(Arel::Nodes::Ascending) if nullable && order_value.is_a?(Arel::Nodes::Ascending)
:nulls_last :nulls_last

View File

@ -33,6 +33,11 @@ module Gitlab
def self.verified?(env) def self.verified?(env)
minimal_env = env.slice('REQUEST_METHOD', 'rack.session', 'HTTP_X_CSRF_TOKEN') minimal_env = env.slice('REQUEST_METHOD', 'rack.session', 'HTTP_X_CSRF_TOKEN')
.merge('rack.input' => '') .merge('rack.input' => '')
# The CSRF token for some requests is in the form instead of headers.
# This line of code is used to accommodate this situation. See: https://gitlab.com/gitlab-org/gitlab/-/issues/443398
minimal_env['HTTP_X_CSRF_TOKEN'] ||= Rack::Request.new(env.dup).params['authenticity_token']
call(minimal_env) call(minimal_env)
true true

View File

@ -246,7 +246,13 @@ module Gitlab
end end
def idempotency_string def idempotency_string
"#{worker_class_name}:#{Sidekiq.dump_json(arguments)}" "#{worker_class_name}:#{idempotency_arguments}"
end
def idempotency_arguments
args = worker_klass.try(:idempotency_arguments, arguments) || arguments
Sidekiq.dump_json(args)
end end
def existing_wal_locations def existing_wal_locations

View File

@ -13058,6 +13058,9 @@ msgstr ""
msgid "ComplianceReport|Compliance framework" msgid "ComplianceReport|Compliance framework"
msgstr "" msgstr ""
msgid "ComplianceReport|Compliance pipelines are now in maintenance mode"
msgstr ""
msgid "ComplianceReport|Create a new framework" msgid "ComplianceReport|Create a new framework"
msgstr "" msgstr ""
@ -13067,6 +13070,9 @@ msgstr ""
msgid "ComplianceReport|Edit the framework" msgid "ComplianceReport|Edit the framework"
msgstr "" msgstr ""
msgid "ComplianceReport|For more information, see %{linkStart}how to migrate from compliance pipelines to pipeline execution policy actions%{linkEnd}."
msgstr ""
msgid "ComplianceReport|Framework successfully applied" msgid "ComplianceReport|Framework successfully applied"
msgstr "" msgstr ""
@ -13118,6 +13124,9 @@ msgstr ""
msgid "ComplianceReport|Update result" msgid "ComplianceReport|Update result"
msgstr "" msgstr ""
msgid "ComplianceReport|You can still edit existing compliance pipelines, but cannot create new compliance pipelines. %{linkStart}Pipeline execution policy%{linkEnd} actions provide the ability to enforce CI/CD jobs, execute security scans, and better manage compliance. You should migrate as soon as possible."
msgstr ""
msgid "ComplianceStandardsAdherence| Standards adherence export" msgid "ComplianceStandardsAdherence| Standards adherence export"
msgstr "" msgstr ""
@ -21452,9 +21461,6 @@ msgstr ""
msgid "File added" msgid "File added"
msgstr "" msgstr ""
msgid "File browser"
msgstr ""
msgid "File deleted" msgid "File deleted"
msgstr "" msgstr ""
@ -45698,7 +45704,7 @@ msgstr ""
msgid "SecurityOrchestration|Security policy project was linked successfully" msgid "SecurityOrchestration|Security policy project was linked successfully"
msgstr "" msgstr ""
msgid "SecurityOrchestration|Security policy project was unlinked successfully" msgid "SecurityOrchestration|Security policy project will be unlinked soon"
msgstr "" msgstr ""
msgid "SecurityOrchestration|Security policy projects store your organization's security policies. They are identified when policies are created, or when a project is linked as a security policy project. %{linkStart}Learn more%{linkEnd}." msgid "SecurityOrchestration|Security policy projects store your organization's security policies. They are identified when policies are created, or when a project is linked as a security policy project. %{linkStart}Learn more%{linkEnd}."
@ -58262,6 +58268,9 @@ msgstr ""
msgid "You don't have write access to the source branch." msgid "You don't have write access to the source branch."
msgstr "" msgstr ""
msgid "You don't need to link the security policy projects from the group. All policies in the security policy projects are inherited already."
msgstr ""
msgid "You dont have access to Productivity Analytics in this group" msgid "You dont have access to Productivity Analytics in this group"
msgstr "" msgstr ""

View File

@ -1,102 +1,106 @@
#!/usr/bin/env bash #!/usr/bin/env bash
# This script runs a suite of non-E2E specs related to the Remote Development category, as
# a pre-commit/pre-push "Smoke Test" to catch any broken tests without having to wait
# on CI to catch them. Note that there are some shared/common specs related to
# Remote Development which are not included in this suite.
# https://en.wikipedia.org/wiki/Smoke_testing_(software)
# shellcheck disable=SC2059 # shellcheck disable=SC2059
set -o errexit # AKA -e - exit immediately on errors (http://mywiki.wooledge.org/BashFAQ/105) BCyan='\033[1;36m'
BRed='\033[1;31m'
########### BGreen='\033[1;32m'
## Setup ## BBlue='\033[1;34m'
########### Color_Off='\033[0m'
# https://stackoverflow.com/a/28938235
BCyan='\033[1;36m' # Bold Cyan
BRed='\033[1;31m' # Bold Red
BGreen='\033[1;32m' # Bold Green
BBlue='\033[1;34m' # Bold Blue
Color_Off='\033[0m' # Text Reset
# Exit handling
function onexit_err() { function onexit_err() {
local exit_status=${1:-$?} local exit_status=${1:-$?}
printf "\n❌❌❌ ${BRed}Remote Development smoke test failed!${Color_Off} ❌❌❌\n" printf "\n❌❌❌ ${BRed}Remote Development smoke test failed!${Color_Off} ❌❌❌\n"
if [ "${REVEAL_RUBOCOP_TODO}" -ne 0 ]; then
if [ ${REVEAL_RUBOCOP_TODO} -ne 0 ]; then
printf "\n(If the failure was due to rubocop, set REVEAL_RUBOCOP_TODO=0 to ignore TODOs)\n" printf "\n(If the failure was due to rubocop, set REVEAL_RUBOCOP_TODO=0 to ignore TODOs)\n"
fi fi
exit "${exit_status}" exit "${exit_status}"
} }
trap onexit_err ERR trap onexit_err ERR
set -o errexit set -o errexit
##################### function print_start_message {
## Invoke commands ## printf "${BCyan}\nStarting Remote Development smoke test...${Color_Off}\n\n"
##################### }
printf "${BCyan}\nStarting Remote Development smoke test...\n\n${Color_Off}" function run_rubocop {
printf "${BBlue}Running RuboCop${Color_Off}\n\n"
files_for_rubocop=()
while IFS= read -r -d '' file; do
files_for_rubocop+=("$file")
done < <(find . -path './**/remote_development/*.rb' -print0)
REVEAL_RUBOCOP_TODO=${REVEAL_RUBOCOP_TODO:-1} bundle exec rubocop --parallel --force-exclusion --no-server "${files_for_rubocop[@]}"
}
############# function run_rspec_fast {
## RUBOCOP ## printf "\n\n${BBlue}Running backend RSpec fast specs${Color_Off}\n\n"
#############
printf "${BBlue}Running RuboCop for Remote Development and related files${Color_Off}\n\n" # NOTE: We do not use `--tag rd_fast` here, because `rd_fast_spec_helper` has a check to ensure that all the
# files which require it are tagged with `rd_fast`.
# TODO: Also run rubocop for the other non-remote-development files once they are passing rubocop files_for_fast=()
# with REVEAL_RUBOCOP_TODO=1 while IFS= read -r file; do
while IFS= read -r -d '' file; do files_for_fast+=("$file")
files_for_rubocop+=("$file") done < <(find ee/spec -path '**/remote_development/*_spec.rb' -exec grep -lE 'require_relative.*rd_fast_spec_helper' {} +)
done < <(find . -path './**/remote_development/*.rb' -print0)
REVEAL_RUBOCOP_TODO=${REVEAL_RUBOCOP_TODO:-1} bundle exec rubocop --parallel --force-exclusion --no-server "${files_for_rubocop[@]}" bin/rspec "${files_for_fast[@]}"
}
########## function run_jest {
## JEST ## printf "\n\n${BBlue}Running Remote Development frontend Jest specs${Color_Off}\n\n"
########## yarn jest ee/spec/frontend/remote_development
}
printf "\n\n${BBlue}Running Remote Development frontend Jest specs${Color_Off}\n\n" function run_rspec_rails {
printf "\n\n${BBlue}Running backend RSpec non-fast specs${Color_Off}\n\n"
files_for_rails=()
while IFS= read -r file; do
files_for_rails+=("$file")
done < <(find ee/spec -path '**/remote_development/*_spec.rb' | grep -v 'qa/qa' | grep -v '/features/')
yarn jest ee/spec/frontend/remote_development files_for_rails+=(
"ee/spec/graphql/types/query_type_spec.rb"
"ee/spec/graphql/types/subscription_type_spec.rb"
"ee/spec/requests/api/internal/kubernetes_spec.rb"
"spec/graphql/types/subscription_type_spec.rb"
"spec/lib/result_spec.rb"
"spec/support_specs/matchers/result_matchers_spec.rb"
)
####################### bin/rspec -r spec_helper --tag ~rd_fast "${files_for_rails[@]}"
## RSPEC NON-FEATURE ## }
#######################
printf "\n\n${BBlue}Running Remote Development and related backend RSpec non-selenium specs${Color_Off}\n\n" function run_rspec_feature {
printf "\n\n${BBlue}Running backend RSpec feature specs${Color_Off}\n\n"
files_for_feature=()
while IFS= read -r file; do
files_for_feature+=("$file")
done < <(find ee/spec -path '**/remote_development/*_spec.rb' | grep -v 'qa/qa' | grep '/features/')
while IFS= read -r file; do bin/rspec -r spec_helper "${files_for_feature[@]}"
files_for_rspec+=("$file") }
done < <(find . -path './**/remote_development/*_spec.rb' | grep -v 'qa/qa' | grep -v '/features/')
files_for_rspec+=( function print_success_message {
"ee/spec/graphql/types/query_type_spec.rb" printf "\n✅✅✅ ${BGreen}All executed linters/specs passed successfully!${Color_Off} ✅✅✅\n"
"ee/spec/graphql/types/subscription_type_spec.rb" }
"ee/spec/requests/api/internal/kubernetes_spec.rb"
"spec/graphql/types/subscription_type_spec.rb"
"spec/lib/result_spec.rb"
"spec/support_specs/matchers/result_matchers_spec.rb"
)
bin/rspec -r spec_helper "${files_for_rspec[@]}"
################### function main {
## RSPEC FEATURE ## # cd to gitlab root directory
################### cd "$(dirname "${BASH_SOURCE[0]}")"/../..
printf "\n\n${BBlue}Running Remote Development and related backend RSpec feature specs${Color_Off}\n\n" print_start_message
while IFS= read -r file; do # Run linting before tests
files_for_rspec_selenium+=("$file") [ -z "${SKIP_RUBOCOP}" ] && run_rubocop
done < <(find . -path './**/remote_development/*_spec.rb' | grep -v 'qa/qa' | grep '/features/')
printf "\n${BRed}SKIPPING FEATURE SPECS, THEY ARE CURRENTLY BROKEN. SEE https://gitlab.slack.com/archives/C3JJET4Q6/p1702638503864429 and https://gitlab.com/gitlab-org/gitlab/-/merge_requests/140015${Color_Off} ❌❌❌\n" # Test sections are sorted roughly in increasing order of execution time.
# bin/rspec -r spec_helper "${files_for_rspec_selenium[@]}" [ -z "${SKIP_FAST}" ] && run_rspec_fast
[ -z "${SKIP_JEST}" ] && run_jest
[ -z "${SKIP_RAILS}" ] && run_rspec_rails
[ -z "${SKIP_FEATURE}" ] && run_rspec_feature
########################### print_success_message
## Print success message ## }
###########################
printf "\n✅✅✅ ${BGreen}All Remote Development specs passed successfully!${Color_Off} ✅✅✅\n" main "$@"

View File

@ -46,8 +46,8 @@ RSpec.describe Settings, feature_category: :system_access do
end end
end end
describe '.build_ci_component_fqdn' do describe '.build_ci_server_fqdn' do
subject(:fqdn) { described_class.build_ci_component_fqdn } subject(:fqdn) { described_class.build_ci_server_fqdn }
where(:host, :port, :relative_url, :result) do where(:host, :port, :relative_url, :result) do
'acme.com' | 9090 | '/gitlab' | 'acme.com:9090/gitlab' 'acme.com' | 9090 | '/gitlab' | 'acme.com:9090/gitlab'

View File

@ -9,17 +9,34 @@ module CrystalballEnv
return unless ENV['CRYSTALBALL'] == 'true' return unless ENV['CRYSTALBALL'] == 'true'
require 'crystalball' require 'crystalball'
require_relative '../tooling/lib/tooling/crystalball/coverage_lines_execution_detector' require_relative '../tooling/lib/tooling/crystalball/described_class_execution_detector'
require_relative '../tooling/lib/tooling/crystalball/coverage_lines_strategy'
map_storage_path_base = ENV['CI_JOB_NAME'] || 'crystalball_data' map_storage_path_base = ENV['CI_JOB_NAME'] || 'crystalball_data'
map_storage_path = "crystalball/#{map_storage_path_base.gsub(%r{[/ ]}, '_')}.yml" map_storage_path = "crystalball/#{map_storage_path_base.gsub(%r{[/ ]}, '_')}.yml"
execution_detector = Tooling::Crystalball::CoverageLinesExecutionDetector.new(exclude_prefixes: EXCLUDED_PREFIXES)
Crystalball::MapGenerator.start! do |config| Crystalball::MapGenerator.start! do |config|
config.map_storage_path = map_storage_path config.map_storage_path = map_storage_path
config.register Tooling::Crystalball::CoverageLinesStrategy.new(execution_detector)
# https://toptal.github.io/crystalball/map_generators/#describedclassstrategy
described_class_execution_detector = Tooling::Crystalball::DescribedClassExecutionDetector.new(
root_path: File.expand_path('../', __dir__),
exclude_prefixes: EXCLUDED_PREFIXES
)
config.register Crystalball::MapGenerator::DescribedClassStrategy.new(
execution_detector: described_class_execution_detector
)
# Modified version of https://toptal.github.io/crystalball/map_generators/#coveragestrategy
#
# require_relative '../tooling/lib/tooling/crystalball/coverage_lines_execution_detector'
# require_relative '../tooling/lib/tooling/crystalball/coverage_lines_strategy'
# execution_detector = Tooling::Crystalball::CoverageLinesExecutionDetector.new(
# exclude_prefixes: EXCLUDED_PREFIXES
# )
# config.register Tooling::Crystalball::CoverageLinesStrategy.new(execution_detector)
# https://toptal.github.io/crystalball/map_generators/#actionviewstrategy
# config.register Crystalball::Rails::MapGenerator::ActionViewStrategy.new
end end
end end
end end

View File

@ -330,6 +330,14 @@ FactoryBot.define do
end end
end end
trait :no_access_artifacts do
after(:create) do |build, evaluator|
create(:ci_job_artifact, :archive, :none, job: build, expire_at: build.artifacts_expire_at)
create(:ci_job_artifact, :metadata, :none, job: build, expire_at: build.artifacts_expire_at)
build.reload
end
end
trait :report_results do trait :report_results do
after(:build) do |build| after(:build) do |build|
build.report_results << build(:ci_build_report_result) build.report_results << build(:ci_build_report_result)
@ -597,6 +605,34 @@ FactoryBot.define do
end end
end end
trait :with_developer_access_artifacts do
options do
{
artifacts: { access: 'developer' }
}
end
end
# invalid case for access setting
trait :with_access_and_public_setting do
options do
{
artifacts: {
public: true,
access: 'all'
}
}
end
end
trait :with_none_access_artifacts do
options do
{
artifacts: { access: 'none' }
}
end
end
trait :with_public_artifacts_config do trait :with_public_artifacts_config do
options do options do
{ {
@ -605,6 +641,14 @@ FactoryBot.define do
end end
end end
trait :with_all_access_artifacts do
options do
{
artifacts: { access: 'all' }
}
end
end
trait :non_playable do trait :non_playable do
status { 'created' } status { 'created' }
self.when { 'manual' } self.when { 'manual' }

View File

@ -182,6 +182,10 @@ FactoryBot.define do
accessibility { 'public' } accessibility { 'public' }
end end
trait :none do
accessibility { 'none' }
end
trait :accessibility do trait :accessibility do
file_type { :accessibility } file_type { :accessibility }
file_format { :raw } file_format { :raw }

View File

@ -30,44 +30,6 @@ describe('Diff settings dropdown component', () => {
store.getters['diffs/isParallelView'] = false; store.getters['diffs/isParallelView'] = false;
}); });
describe('tree view buttons', () => {
it('list view button dispatches setRenderTreeList with false', () => {
const wrapper = createComponent();
wrapper.find('.js-list-view').trigger('click');
expect(store.dispatch).toHaveBeenCalledWith('diffs/setRenderTreeList', {
renderTreeList: false,
});
});
it('tree view button dispatches setRenderTreeList with true', () => {
const wrapper = createComponent();
wrapper.find('.js-tree-view').trigger('click');
expect(store.dispatch).toHaveBeenCalledWith('diffs/setRenderTreeList', {
renderTreeList: true,
});
});
it('sets list button as selected when renderTreeList is false', () => {
store.state.diffs = { renderTreeList: false };
const wrapper = createComponent();
expect(wrapper.find('.js-list-view').classes('selected')).toBe(true);
expect(wrapper.find('.js-tree-view').classes('selected')).toBe(false);
});
it('sets tree button as selected when renderTreeList is true', () => {
store.state.diffs = { renderTreeList: true };
const wrapper = createComponent();
expect(wrapper.find('.js-list-view').classes('selected')).toBe(false);
expect(wrapper.find('.js-tree-view').classes('selected')).toBe(true);
});
});
describe('compare changes', () => { describe('compare changes', () => {
it('sets inline button as selected', () => { it('sets inline button as selected', () => {
store.state.diffs = { diffViewType: INLINE_DIFF_VIEW_TYPE }; store.state.diffs = { diffViewType: INLINE_DIFF_VIEW_TYPE };

Some files were not shown because too many files have changed in this diff Show More