Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
91a8a89bd6
commit
f2e8d3f288
|
|
@ -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: ""
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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')
|
||||||
|
|
|
||||||
|
|
@ -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" />
|
||||||
|
|
|
||||||
|
|
@ -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,
|
||||||
|
|
|
||||||
|
|
@ -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).",
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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>
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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 }}
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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!
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
|
|
||||||
|
|
@ -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)
|
||||||
|
|
||||||
[
|
[
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
4745de5adaef6c0ea8c669317111b1568b8abf1f6c4a565db464f6bb8b59e70a
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
0287ede4aceee941c41c3b8f1e6a22bdbdd793b4b53206f44c9e56f44f22b97f
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
839b964e455dbd577ab389accb922922b99148a847d01d9164d832f68b0e5547
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
93148a82bf2a7021b282420ee13dab381fb05dc878902bc2a1e1e98ff81dda0a
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
c676560059b9cf10b47a4ca7a8b92149d92bb261bde3cfee1043ab7318801aff
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
f1f8f01acb0b0d70de398dd48bea37f60e5d0da2799ff31f5b3915e566b280f3
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
13de6dff291398df87dc95a81e8d4f7f8ce7a3f22fcb3df39006e0b386d369cf
|
||||||
|
|
@ -0,0 +1 @@
|
||||||
|
45f5f3988b6fac58c19dc5bbe74eedfa1d697746c83493f478600749c25abc46
|
||||||
|
|
@ -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);
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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.
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
@ -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:)
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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 don’t have access to Productivity Analytics in this group"
|
msgid "You don’t have access to Productivity Analytics in this group"
|
||||||
msgstr ""
|
msgstr ""
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 "$@"
|
||||||
|
|
|
||||||
|
|
@ -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'
|
||||||
|
|
|
||||||
|
|
@ -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
|
||||||
|
|
|
||||||
|
|
@ -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' }
|
||||||
|
|
|
||||||
|
|
@ -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 }
|
||||||
|
|
|
||||||
|
|
@ -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
Loading…
Reference in New Issue