Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
50d0abd57d
commit
cb7f283a39
|
|
@ -35,23 +35,6 @@ Layout/ArgumentAlignment:
|
|||
- 'app/graphql/mutations/work_items/delete.rb'
|
||||
- 'app/graphql/mutations/work_items/update.rb'
|
||||
- 'app/graphql/resolvers/admin/analytics/usage_trends/measurements_resolver.rb'
|
||||
- 'app/graphql/resolvers/ci/runner_projects_resolver.rb'
|
||||
- 'app/graphql/resolvers/ci/runner_resolver.rb'
|
||||
- 'app/graphql/resolvers/ci/runner_setup_resolver.rb'
|
||||
- 'app/graphql/resolvers/ci/runners_resolver.rb'
|
||||
- 'app/graphql/resolvers/ci/template_resolver.rb'
|
||||
- 'app/graphql/resolvers/ci/variables_resolver.rb'
|
||||
- 'app/graphql/resolvers/clusters/agent_tokens_resolver.rb'
|
||||
- 'app/graphql/resolvers/clusters/agents_resolver.rb'
|
||||
- 'app/graphql/resolvers/concerns/board_item_filterable.rb'
|
||||
- 'app/graphql/resolvers/concerns/group_issuable_resolver.rb'
|
||||
- 'app/graphql/resolvers/concerns/issues/sort_arguments.rb'
|
||||
- 'app/graphql/resolvers/concerns/project_search_arguments.rb'
|
||||
- 'app/graphql/resolvers/concerns/resolves_pipelines.rb'
|
||||
- 'app/graphql/resolvers/concerns/resolves_snippets.rb'
|
||||
- 'app/graphql/resolvers/concerns/search_arguments.rb'
|
||||
- 'app/graphql/resolvers/concerns/time_frame_arguments.rb'
|
||||
- 'app/graphql/resolvers/container_repositories_resolver.rb'
|
||||
- 'app/graphql/resolvers/work_items/types_resolver.rb'
|
||||
- 'app/graphql/resolvers/work_items_resolver.rb'
|
||||
- 'app/graphql/subscriptions/issuable_updated.rb'
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
4b1de41ff2b02d54bf57b0c965d9b265a175a3ec
|
||||
d3853184e7d735a89479582ceac1d525497e477b
|
||||
|
|
|
|||
|
|
@ -283,7 +283,7 @@ export default {
|
|||
>
|
||||
<span
|
||||
:id="`ci-variable-key-${item.id}`"
|
||||
class="gl-display-inline-block gl-max-w-full gl-word-break-word"
|
||||
class="gl-display-inline-block gl-max-w-full gl-break-anywhere"
|
||||
>{{ item.key }}</span
|
||||
>
|
||||
<gl-button
|
||||
|
|
@ -343,7 +343,7 @@ export default {
|
|||
>
|
||||
<span
|
||||
:id="`ci-variable-env-${item.id}`"
|
||||
class="gl-display-inline-block gl-max-w-full gl-word-break-word"
|
||||
class="gl-display-inline-block gl-max-w-full gl-break-anywhere"
|
||||
>{{ convertEnvironmentScopeValue(item.environmentScope) }}</span
|
||||
>
|
||||
<gl-button
|
||||
|
|
@ -365,7 +365,7 @@ export default {
|
|||
<gl-link
|
||||
:id="`ci-variable-group-${item.id}`"
|
||||
data-testid="ci-variable-table-row-cicd-path"
|
||||
class="gl-display-inline-block gl-max-w-full gl-word-break-word"
|
||||
class="gl-display-inline-block gl-max-w-full gl-break-anywhere"
|
||||
:href="item.groupCiCdSettingsPath"
|
||||
>
|
||||
{{ item.groupName }}
|
||||
|
|
|
|||
|
|
@ -90,7 +90,7 @@ export default {
|
|||
@close="closeDetailsDrawer"
|
||||
>
|
||||
<template #title>
|
||||
<h4 class="gl-font-weight-bold gl-font-size-h2 gl-m-0 gl-word-break-word">
|
||||
<h4 class="gl-font-weight-bold gl-font-size-h2 gl-m-0 gl-break-anywhere">
|
||||
{{ selectedItem.name }}
|
||||
</h4>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -160,7 +160,7 @@ export default {
|
|||
class="table-mobile-content gl-text-left gl-display-flex flex-column js-feature-flag-title gl-mr-5"
|
||||
>
|
||||
<div class="gl-display-flex gl-align-items-center">
|
||||
<div class="feature-flag-name text-monospace text-wrap gl-word-break-word">
|
||||
<div class="feature-flag-name text-monospace text-wrap gl-break-anywhere">
|
||||
{{ featureFlag.name }}
|
||||
</div>
|
||||
<div class="feature-flag-description">
|
||||
|
|
|
|||
|
|
@ -203,7 +203,7 @@ export default {
|
|||
data-testid="group-name"
|
||||
:href="group.relativePath"
|
||||
:title="group.fullName"
|
||||
class="no-expand gl-mr-3 gl-text-gray-900! gl-word-break-word"
|
||||
class="no-expand gl-mr-3 gl-text-gray-900! gl-break-anywhere"
|
||||
:itemprop="microdata.nameItemprop"
|
||||
>
|
||||
<!-- ending bracket must be by closing tag to prevent -->
|
||||
|
|
|
|||
|
|
@ -102,14 +102,14 @@ export default {
|
|||
<div v-for="(line, index) in allLines" :key="index">
|
||||
<span
|
||||
data-testid="highlights-text"
|
||||
class="gl-white-space-pre-wrap gl-word-break-word"
|
||||
class="gl-white-space-pre-wrap gl-break-anywhere"
|
||||
v-text="line.text"
|
||||
>
|
||||
</span
|
||||
><mark
|
||||
v-show="line.highlightedText"
|
||||
data-testid="highlights-mark"
|
||||
class="gl-px-1 gl-py-0 gl-bg-orange-100 gl-text-transparent gl-white-space-pre-wrap gl-word-break-word"
|
||||
class="gl-px-1 gl-py-0 gl-bg-orange-100 gl-text-transparent gl-white-space-pre-wrap gl-break-anywhere"
|
||||
v-text="line.highlightedText"
|
||||
>
|
||||
</mark>
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ export default {
|
|||
{
|
||||
key: 'source_title',
|
||||
label: __('Title'),
|
||||
tdClass: 'gl-md-w-30 gl-word-break-word',
|
||||
tdClass: 'gl-md-w-30 gl-break-anywhere',
|
||||
},
|
||||
{
|
||||
key: 'error',
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ export default {
|
|||
{
|
||||
key: 'title',
|
||||
label: __('Title'),
|
||||
tdClass: 'gl-md-w-30 gl-word-break-word',
|
||||
tdClass: 'gl-md-w-30 gl-break-anywhere',
|
||||
},
|
||||
{
|
||||
key: 'provider_url',
|
||||
|
|
|
|||
|
|
@ -70,7 +70,7 @@ export default {
|
|||
<template>
|
||||
<ul class="gl-list-none">
|
||||
<workload-details-item :label="$options.i18n.name">
|
||||
<span class="gl-word-break-word"> {{ item.name }}</span>
|
||||
<span class="gl-break-anywhere"> {{ item.name }}</span>
|
||||
</workload-details-item>
|
||||
<workload-details-item :label="$options.i18n.kind">
|
||||
{{ item.kind }}
|
||||
|
|
|
|||
|
|
@ -85,7 +85,7 @@ export default {
|
|||
@close="closeDetailsDrawer"
|
||||
>
|
||||
<template #title>
|
||||
<h4 class="gl-font-weight-bold gl-font-size-h2 gl-m-0 gl-word-break-word">
|
||||
<h4 class="gl-font-weight-bold gl-font-size-h2 gl-m-0 gl-break-anywhere">
|
||||
{{ selectedItem.name }}
|
||||
</h4>
|
||||
</template>
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ export const DEFAULT_WORKLOAD_TABLE_FIELDS = [
|
|||
{
|
||||
key: 'name',
|
||||
label: s__('KubernetesDashboard|Name'),
|
||||
tdClass: 'gl-md-w-half gl-lg-w-40p gl-word-break-word',
|
||||
tdClass: 'gl-md-w-half gl-lg-w-40p gl-break-anywhere',
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
|
|
@ -44,7 +44,7 @@ export const DEFAULT_WORKLOAD_TABLE_FIELDS = [
|
|||
{
|
||||
key: 'namespace',
|
||||
label: s__('KubernetesDashboard|Namespace'),
|
||||
tdClass: 'gl-md-w-30p gl-lg-w-40p gl-word-break-word',
|
||||
tdClass: 'gl-md-w-30p gl-lg-w-40p gl-break-anywhere',
|
||||
},
|
||||
{
|
||||
key: 'age',
|
||||
|
|
|
|||
|
|
@ -49,23 +49,6 @@ if (process.env.NODE_ENV !== 'production' && gon?.test_env) {
|
|||
import(/* webpackMode: "eager" */ './test_utils');
|
||||
}
|
||||
|
||||
if (gon?.user_color_mode === 'gl-system') {
|
||||
const root = document.documentElement;
|
||||
// eslint-disable-next-line @gitlab/require-i18n-strings
|
||||
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
root.classList.add('gl-dark');
|
||||
}
|
||||
|
||||
// eslint-disable-next-line @gitlab/require-i18n-strings
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
||||
if (e.matches) {
|
||||
root.classList.add('gl-dark');
|
||||
} else {
|
||||
root.classList.remove('gl-dark');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('beforeunload', () => {
|
||||
// Unbind scroll events
|
||||
// eslint-disable-next-line @gitlab/no-global-event-off
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ export default {
|
|||
<assignee-avatar-link
|
||||
:user="user"
|
||||
:issuable-type="issuableType"
|
||||
class="gl-word-break-word"
|
||||
class="gl-break-anywhere"
|
||||
data-css-area="user"
|
||||
>
|
||||
<div
|
||||
|
|
|
|||
|
|
@ -192,7 +192,7 @@ export default {
|
|||
class="labels-fetch-loading gl-align-items-center gl-w-full gl-h-full"
|
||||
size="lg"
|
||||
/>
|
||||
<ul v-else class="list-unstyled gl-mb-0 gl-word-break-word">
|
||||
<ul v-else class="list-unstyled gl-mb-0 gl-break-anywhere">
|
||||
<label-item
|
||||
v-for="(label, index) in visibleLabels"
|
||||
:key="label.id"
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ export default {
|
|||
</script>
|
||||
|
||||
<template>
|
||||
<div class="gl-display-flex gl-word-break-word">
|
||||
<div class="gl-display-flex gl-break-anywhere">
|
||||
<span
|
||||
class="dropdown-label-box gl-flex-shrink-0 gl-top-0 gl-mr-3"
|
||||
:style="{ 'background-color': label.color }"
|
||||
|
|
|
|||
|
|
@ -162,7 +162,7 @@ export default {
|
|||
:user="user"
|
||||
:root-path="rootPath"
|
||||
:issuable-type="issuableType"
|
||||
class="gl-word-break-word gl-mr-2"
|
||||
class="gl-break-anywhere gl-mr-2"
|
||||
data-css-area="user"
|
||||
>
|
||||
<div class="gl-ml-3 gl-line-height-normal gl-display-grid gl-align-items-center">
|
||||
|
|
|
|||
|
|
@ -144,7 +144,7 @@ export default {
|
|||
|
||||
<gl-link
|
||||
:href="getUsageQuotasUrl(project.webUrl)"
|
||||
class="gl-text-gray-900! js-project-link gl-word-break-word"
|
||||
class="gl-text-gray-900! js-project-link gl-break-anywhere"
|
||||
data-testid="project-link"
|
||||
>
|
||||
{{ getProjectRelativePath(project.nameWithNamespace) }}
|
||||
|
|
|
|||
|
|
@ -255,7 +255,7 @@ export default {
|
|||
</template>
|
||||
</gl-avatar-labeled>
|
||||
</div>
|
||||
<div class="gl-mt-2 gl-w-full gl-word-break-word">
|
||||
<div class="gl-mt-2 gl-w-full gl-break-anywhere">
|
||||
<template v-if="userIsLoading">
|
||||
<gl-skeleton-loader
|
||||
:lines="$options.maxSkeletonLines"
|
||||
|
|
|
|||
|
|
@ -132,7 +132,7 @@ export default {
|
|||
:note-id="noteId"
|
||||
:is-system-note="true"
|
||||
>
|
||||
<span ref="gfm-content" v-safe-html="actionTextHtml" class="gl-word-break-word"></span>
|
||||
<span ref="gfm-content" v-safe-html="actionTextHtml" class="gl-break-anywhere"></span>
|
||||
<template v-if="canSeeDescriptionVersion" #extra-controls>
|
||||
·
|
||||
<gl-button
|
||||
|
|
|
|||
|
|
@ -18,14 +18,13 @@ module WebHooks
|
|||
end
|
||||
|
||||
def create
|
||||
self.hook = relation.new(hook_params)
|
||||
hook.save
|
||||
result = WebHooks::CreateService.new(current_user).execute(hook_params, relation)
|
||||
|
||||
if hook.valid?
|
||||
if result.success?
|
||||
flash[:notice] = _('Webhook was created')
|
||||
else
|
||||
self.hooks = relation.select(&:persisted?)
|
||||
flash[:alert] = hook.errors.full_messages.to_sentence.html_safe
|
||||
flash[:alert] = result.message
|
||||
end
|
||||
|
||||
redirect_to action: :index
|
||||
|
|
|
|||
|
|
@ -26,8 +26,8 @@ module Resolvers
|
|||
unique_project_ids = plucked_runner_and_project_ids.collect { |_runner_id, project_id| project_id }.uniq
|
||||
projects = ProjectsFinder
|
||||
.new(current_user: current_user,
|
||||
params: project_finder_params(args),
|
||||
project_ids_relation: unique_project_ids)
|
||||
params: project_finder_params(args),
|
||||
project_ids_relation: unique_project_ids)
|
||||
.execute
|
||||
projects = apply_lookahead(projects)
|
||||
Preloaders::ProjectPolicyPreloader.new(projects, current_user).execute
|
||||
|
|
|
|||
|
|
@ -9,26 +9,26 @@ module Resolvers
|
|||
description 'Runner setup instructions.'
|
||||
|
||||
argument :platform,
|
||||
type: GraphQL::Types::String,
|
||||
required: true,
|
||||
description: 'Platform to generate the instructions for.'
|
||||
type: GraphQL::Types::String,
|
||||
required: true,
|
||||
description: 'Platform to generate the instructions for.'
|
||||
|
||||
argument :architecture,
|
||||
type: GraphQL::Types::String,
|
||||
required: true,
|
||||
description: 'Architecture to generate the instructions for.'
|
||||
type: GraphQL::Types::String,
|
||||
required: true,
|
||||
description: 'Architecture to generate the instructions for.'
|
||||
|
||||
argument :project_id,
|
||||
type: ::Types::GlobalIDType[::Project],
|
||||
required: false,
|
||||
deprecated: { reason: 'No longer used', milestone: '13.11' },
|
||||
description: 'Project to register the runner for.'
|
||||
type: ::Types::GlobalIDType[::Project],
|
||||
required: false,
|
||||
deprecated: { reason: 'No longer used', milestone: '13.11' },
|
||||
description: 'Project to register the runner for.'
|
||||
|
||||
argument :group_id,
|
||||
type: ::Types::GlobalIDType[::Group],
|
||||
required: false,
|
||||
deprecated: { reason: 'No longer used', milestone: '13.11' },
|
||||
description: 'Group to register the runner for.'
|
||||
type: ::Types::GlobalIDType[::Group],
|
||||
required: false,
|
||||
deprecated: { reason: 'No longer used', milestone: '13.11' },
|
||||
description: 'Group to register the runner for.'
|
||||
|
||||
def resolve(platform:, architecture:, **args)
|
||||
instructions = Gitlab::Ci::RunnerInstructions.new(
|
||||
|
|
|
|||
|
|
@ -9,53 +9,53 @@ module Resolvers
|
|||
type Types::Ci::RunnerType.connection_type, null: true
|
||||
|
||||
argument :active, ::GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
description: 'Filter runners by `active` (true) or `paused` (false) status.',
|
||||
deprecated: { reason: :renamed, replacement: 'paused', milestone: '14.8' }
|
||||
required: false,
|
||||
description: 'Filter runners by `active` (true) or `paused` (false) status.',
|
||||
deprecated: { reason: :renamed, replacement: 'paused', milestone: '14.8' }
|
||||
|
||||
argument :paused, ::GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
description: 'Filter runners by `paused` (true) or `active` (false) status.'
|
||||
required: false,
|
||||
description: 'Filter runners by `paused` (true) or `active` (false) status.'
|
||||
|
||||
argument :status, ::Types::Ci::RunnerStatusEnum,
|
||||
required: false,
|
||||
description: 'Filter runners by status.'
|
||||
required: false,
|
||||
description: 'Filter runners by status.'
|
||||
|
||||
argument :type, ::Types::Ci::RunnerTypeEnum,
|
||||
required: false,
|
||||
description: 'Filter runners by type.'
|
||||
required: false,
|
||||
description: 'Filter runners by type.'
|
||||
|
||||
argument :tag_list, [GraphQL::Types::String],
|
||||
required: false,
|
||||
description: 'Filter by tags associated with the runner (comma-separated or array).'
|
||||
required: false,
|
||||
description: 'Filter by tags associated with the runner (comma-separated or array).'
|
||||
|
||||
argument :search, GraphQL::Types::String,
|
||||
required: false,
|
||||
description: 'Filter by full token or partial text in description field.'
|
||||
required: false,
|
||||
description: 'Filter by full token or partial text in description field.'
|
||||
|
||||
argument :sort, ::Types::Ci::RunnerSortEnum,
|
||||
required: false,
|
||||
description: 'Sort order of results.'
|
||||
required: false,
|
||||
description: 'Sort order of results.'
|
||||
|
||||
argument :upgrade_status, ::Types::Ci::RunnerUpgradeStatusEnum,
|
||||
required: false,
|
||||
description: 'Filter by upgrade status.'
|
||||
required: false,
|
||||
description: 'Filter by upgrade status.'
|
||||
|
||||
argument :creator_id, ::Types::GlobalIDType[::User].as('UserID'),
|
||||
required: false,
|
||||
description: 'Filter runners by creator ID.'
|
||||
required: false,
|
||||
description: 'Filter runners by creator ID.'
|
||||
|
||||
argument :creator_username, GraphQL::Types::String,
|
||||
required: false,
|
||||
description: 'Filter runners by creator username.',
|
||||
alpha: { milestone: '16.7' }
|
||||
required: false,
|
||||
description: 'Filter runners by creator username.',
|
||||
alpha: { milestone: '16.7' }
|
||||
|
||||
argument :version_prefix, GraphQL::Types::String,
|
||||
required: false,
|
||||
description: "Filter runners by version. Runners that contain runner managers with the version at " \
|
||||
"the start of the search term are returned. For example, the search term '14.' returns " \
|
||||
"runner managers with versions '14.11.1' and '14.2.3'.",
|
||||
alpha: { milestone: '16.6' }
|
||||
required: false,
|
||||
description: "Filter runners by version. Runners that contain runner managers with the version at " \
|
||||
"the start of the search term are returned. For example, the search term '14.' returns " \
|
||||
"runner managers with versions '14.11.1' and '14.2.3'.",
|
||||
alpha: { milestone: '16.6' }
|
||||
|
||||
def resolve_with_lookahead(**args)
|
||||
apply_lookahead(
|
||||
|
|
|
|||
|
|
@ -6,10 +6,10 @@ module Resolvers
|
|||
type Types::Ci::TemplateType, null: true
|
||||
|
||||
argument :name,
|
||||
GraphQL::Types::String,
|
||||
required: true,
|
||||
description: 'Name of the CI/CD template to search for. ' \
|
||||
'Template must be formatted as `Name.gitlab-ci.yml`.'
|
||||
GraphQL::Types::String,
|
||||
required: true,
|
||||
description: 'Name of the CI/CD template to search for. ' \
|
||||
'Template must be formatted as `Name.gitlab-ci.yml`.'
|
||||
|
||||
alias_method :project, :object
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,8 @@ module Resolvers
|
|||
type Types::Ci::InstanceVariableType.connection_type, null: true
|
||||
|
||||
argument :sort, ::Types::Ci::VariableSortEnum,
|
||||
required: false,
|
||||
description: 'Sort order of results.'
|
||||
required: false,
|
||||
description: 'Sort order of results.'
|
||||
|
||||
def resolve(**args)
|
||||
if parent.is_a?(Group) || parent.is_a?(Project)
|
||||
|
|
|
|||
|
|
@ -11,8 +11,8 @@ module Resolvers
|
|||
|
||||
when_single do
|
||||
argument :name, GraphQL::Types::String,
|
||||
required: true,
|
||||
description: 'Name of the cluster agent.'
|
||||
required: true,
|
||||
description: 'Name of the cluster agent.'
|
||||
end
|
||||
|
||||
def resolve_with_lookahead(**args)
|
||||
|
|
|
|||
|
|
@ -15,7 +15,7 @@ module BoardItemFilterable
|
|||
if filters[:or]
|
||||
if ::Feature.disabled?(:or_issuable_queries, resource_parent)
|
||||
raise ::Gitlab::Graphql::Errors::ArgumentError,
|
||||
"'or' arguments are only allowed when the `or_issuable_queries` feature flag is enabled."
|
||||
"'or' arguments are only allowed when the `or_issuable_queries` feature flag is enabled."
|
||||
end
|
||||
|
||||
rewrite_param_name(filters[:or], :author_usernames, :author_username)
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@ module GroupIssuableResolver
|
|||
|
||||
included do
|
||||
argument :include_subgroups, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
default_value: false,
|
||||
description: "Include #{issuable_collection_name} belonging to subgroups"
|
||||
required: false,
|
||||
default_value: false,
|
||||
description: "Include #{issuable_collection_name} belonging to subgroups"
|
||||
|
||||
argument :include_archived, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
default_value: false,
|
||||
description: "Return #{issuable_collection_name} from archived projects"
|
||||
required: false,
|
||||
default_value: false,
|
||||
description: "Return #{issuable_collection_name} from archived projects"
|
||||
end
|
||||
|
||||
def resolve(**args)
|
||||
|
|
|
|||
|
|
@ -12,9 +12,9 @@ module Issues
|
|||
|
||||
included do
|
||||
argument :sort, Types::IssueSortEnum,
|
||||
description: 'Sort issues by this criteria.',
|
||||
required: false,
|
||||
default_value: :created_desc
|
||||
description: 'Sort issues by this criteria.',
|
||||
required: false,
|
||||
default_value: :created_desc
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -5,30 +5,30 @@ module ProjectSearchArguments
|
|||
|
||||
included do
|
||||
argument :membership, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
description: 'Return only projects that the current user is a member of.'
|
||||
required: false,
|
||||
description: 'Return only projects that the current user is a member of.'
|
||||
|
||||
argument :search, GraphQL::Types::String,
|
||||
required: false,
|
||||
description: 'Search query, which can be for the project name, a path, or a description.'
|
||||
required: false,
|
||||
description: 'Search query, which can be for the project name, a path, or a description.'
|
||||
|
||||
argument :search_namespaces, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
description: 'Include namespace in project search.'
|
||||
required: false,
|
||||
description: 'Include namespace in project search.'
|
||||
|
||||
argument :topics, type: [GraphQL::Types::String],
|
||||
required: false,
|
||||
description: 'Filter projects by topics.'
|
||||
required: false,
|
||||
description: 'Filter projects by topics.'
|
||||
|
||||
argument :personal, GraphQL::Types::Boolean,
|
||||
required: false,
|
||||
description: 'Return only personal projects.'
|
||||
required: false,
|
||||
description: 'Return only personal projects.'
|
||||
|
||||
argument :sort, GraphQL::Types::String,
|
||||
required: false,
|
||||
default_value: 'id_desc',
|
||||
description: "Sort order of results. Format: `<field_name>_<sort_direction>`, " \
|
||||
"for example: `id_desc` or `name_asc`"
|
||||
required: false,
|
||||
default_value: 'id_desc',
|
||||
description: "Sort order of results. Format: `<field_name>_<sort_direction>`, " \
|
||||
"for example: `id_desc` or `name_asc`"
|
||||
end
|
||||
|
||||
private
|
||||
|
|
|
|||
|
|
@ -6,36 +6,36 @@ module ResolvesPipelines
|
|||
included do
|
||||
type Types::Ci::PipelineType.connection_type, null: false
|
||||
argument :status,
|
||||
Types::Ci::PipelineStatusEnum,
|
||||
required: false,
|
||||
description: "Filter pipelines by their status."
|
||||
Types::Ci::PipelineStatusEnum,
|
||||
required: false,
|
||||
description: "Filter pipelines by their status."
|
||||
argument :scope, ::Types::Ci::PipelineScopeEnum,
|
||||
required: false,
|
||||
description: 'Filter pipelines by scope.'
|
||||
required: false,
|
||||
description: 'Filter pipelines by scope.'
|
||||
argument :ref,
|
||||
GraphQL::Types::String,
|
||||
required: false,
|
||||
description: "Filter pipelines by the ref they are run for."
|
||||
GraphQL::Types::String,
|
||||
required: false,
|
||||
description: "Filter pipelines by the ref they are run for."
|
||||
argument :sha,
|
||||
GraphQL::Types::String,
|
||||
required: false,
|
||||
description: "Filter pipelines by the sha of the commit they are run for."
|
||||
GraphQL::Types::String,
|
||||
required: false,
|
||||
description: "Filter pipelines by the sha of the commit they are run for."
|
||||
argument :source,
|
||||
GraphQL::Types::String,
|
||||
required: false,
|
||||
description: "Filter pipelines by their source."
|
||||
GraphQL::Types::String,
|
||||
required: false,
|
||||
description: "Filter pipelines by their source."
|
||||
|
||||
argument :updated_after, Types::TimeType,
|
||||
required: false,
|
||||
description: 'Pipelines updated after this date.'
|
||||
required: false,
|
||||
description: 'Pipelines updated after this date.'
|
||||
argument :updated_before, Types::TimeType,
|
||||
required: false,
|
||||
description: 'Pipelines updated before this date.'
|
||||
required: false,
|
||||
description: 'Pipelines updated before this date.'
|
||||
|
||||
argument :username,
|
||||
GraphQL::Types::String,
|
||||
required: false,
|
||||
description: "Filter pipelines by the user that triggered the pipeline."
|
||||
GraphQL::Types::String,
|
||||
required: false,
|
||||
description: "Filter pipelines by the user that triggered the pipeline."
|
||||
end
|
||||
|
||||
class_methods do
|
||||
|
|
|
|||
|
|
@ -8,12 +8,12 @@ module ResolvesSnippets
|
|||
type Types::SnippetType.connection_type, null: true
|
||||
|
||||
argument :ids, [::Types::GlobalIDType[::Snippet]],
|
||||
required: false,
|
||||
description: 'Array of global snippet IDs. For example, `gid://gitlab/ProjectSnippet/1`.'
|
||||
required: false,
|
||||
description: 'Array of global snippet IDs. For example, `gid://gitlab/ProjectSnippet/1`.'
|
||||
|
||||
argument :visibility, Types::Snippets::VisibilityScopesEnum,
|
||||
required: false,
|
||||
description: 'Visibility of the snippet.'
|
||||
required: false,
|
||||
description: 'Visibility of the snippet.'
|
||||
end
|
||||
|
||||
def resolve(**args)
|
||||
|
|
|
|||
|
|
@ -5,14 +5,14 @@ module SearchArguments
|
|||
|
||||
included do
|
||||
argument :search, GraphQL::Types::String,
|
||||
required: false,
|
||||
description: 'Search query for title or description.'
|
||||
required: false,
|
||||
description: 'Search query for title or description.'
|
||||
argument :in, [Types::IssuableSearchableFieldEnum],
|
||||
required: false,
|
||||
description: <<~DESC
|
||||
required: false,
|
||||
description: <<~DESC
|
||||
Specify the fields to perform the search in.
|
||||
Defaults to `[TITLE, DESCRIPTION]`. Requires the `search` argument.'
|
||||
DESC
|
||||
DESC
|
||||
end
|
||||
|
||||
def ready?(**args)
|
||||
|
|
@ -28,7 +28,7 @@ module SearchArguments
|
|||
return unless args[:in].present? && args[:search].blank?
|
||||
|
||||
raise Gitlab::Graphql::Errors::ArgumentError,
|
||||
'`search` should be present when including the `in` argument'
|
||||
'`search` should be present when including the `in` argument'
|
||||
end
|
||||
|
||||
def validate_search_rate_limit!(args)
|
||||
|
|
|
|||
|
|
@ -5,8 +5,8 @@ module TimeFrameArguments
|
|||
|
||||
included do
|
||||
argument :timeframe, Types::TimeframeInputType,
|
||||
required: false,
|
||||
description: 'List items overlapping the given timeframe.'
|
||||
required: false,
|
||||
description: 'List items overlapping the given timeframe.'
|
||||
end
|
||||
|
||||
def transform_timeframe_parameters(args)
|
||||
|
|
|
|||
|
|
@ -7,13 +7,13 @@ module Resolvers
|
|||
type Types::ContainerRepositoryType, null: true
|
||||
|
||||
argument :name, GraphQL::Types::String,
|
||||
required: false,
|
||||
description: 'Filter the container repositories by their name.'
|
||||
required: false,
|
||||
description: 'Filter the container repositories by their name.'
|
||||
|
||||
argument :sort, Types::ContainerRepositorySortEnum,
|
||||
description: 'Sort container repositories by this criteria.',
|
||||
required: false,
|
||||
default_value: :created_desc
|
||||
description: 'Sort container repositories by this criteria.',
|
||||
required: false,
|
||||
default_value: :created_desc
|
||||
|
||||
def resolve(name: nil, sort: nil)
|
||||
ContainerRepositoriesFinder.new(user: current_user, subject: object, params: { name: name, sort: sort })
|
||||
|
|
|
|||
|
|
@ -26,7 +26,7 @@ module WebHooks
|
|||
end
|
||||
|
||||
def can_access_web_hooks?(object)
|
||||
Ability.allowed?(current_user, :admin_project, object)
|
||||
Ability.allowed?(current_user, :admin_web_hook, object)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,28 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module WebHooks
|
||||
class CreateService
|
||||
include Services::ReturnServiceResponses
|
||||
|
||||
def initialize(current_user)
|
||||
@current_user = current_user
|
||||
end
|
||||
|
||||
def execute(hook_params, relation)
|
||||
hook = relation.new(hook_params)
|
||||
|
||||
if hook.save
|
||||
success({ hook: hook, async: false })
|
||||
else
|
||||
return error("Invalid url given", 422) if hook.errors[:url].present?
|
||||
return error("Invalid branch filter given", 422) if hook.errors[:push_events_branch_filter].present?
|
||||
|
||||
error(hook.errors.full_messages.to_sentence, 422)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :current_user
|
||||
end
|
||||
end
|
||||
|
|
@ -6,7 +6,7 @@
|
|||
.gl-display-flex.gl-justify-content-space-between.gl-flex-wrap.gl-flex-direction-column.gl-sm-flex-direction-row.gl-gap-3.gl-my-5
|
||||
.home-panel-title-row.gl-display-flex
|
||||
= render Pajamas::AvatarComponent.new(@group, alt: @group.name, size: 48, class: 'float-none gl-align-self-start gl-flex-shrink-0 gl-mr-3', avatar_options: { itemprop: 'logo' })
|
||||
%h1.home-panel-title.gl-heading-1.gl-mt-3.gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-gap-3.gl-word-break-word{ class: 'gl-mb-0!', itemprop: 'name' }
|
||||
%h1.home-panel-title.gl-heading-1.gl-mt-3.gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-gap-3.gl-break-anywhere{ class: 'gl-mb-0!', itemprop: 'name' }
|
||||
= @group.name
|
||||
%span.visibility-icon.gl-text-secondary.has-tooltip{ data: { container: 'body' }, title: visibility_icon_description(@group) }
|
||||
= visibility_level_icon(@group.visibility_level, options: { class: 'icon' })
|
||||
|
|
|
|||
|
|
@ -0,0 +1,17 @@
|
|||
- return unless user_application_system_mode?
|
||||
|
||||
= javascript_tag do
|
||||
:plain
|
||||
const root = document.documentElement;
|
||||
if (window.matchMedia('(prefers-color-scheme: dark)').matches) {
|
||||
root.classList.add('gl-dark');
|
||||
}
|
||||
|
||||
window.matchMedia('(prefers-color-scheme: dark)').addEventListener('change', (e) => {
|
||||
if (e.matches) {
|
||||
root.classList.add('gl-dark');
|
||||
} else {
|
||||
root.classList.remove('gl-dark');
|
||||
}
|
||||
});
|
||||
|
||||
|
|
@ -14,6 +14,8 @@
|
|||
= Gon::Base.render_data(nonce: content_security_policy_nonce)
|
||||
= yield :project_javascripts
|
||||
|
||||
= render 'layouts/application_color_mode_js'
|
||||
|
||||
= render 'layouts/startup_js'
|
||||
= yield :startup_js
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,7 @@
|
|||
.gl-display-flex.gl-justify-content-space-between.gl-flex-wrap.gl-flex-direction-column.gl-md-flex-direction-row.gl-gap-5
|
||||
.home-panel-title-row.gl-display-flex.gl-align-items-center
|
||||
= render Pajamas::AvatarComponent.new(@project, alt: @project.name, class: 'gl-align-self-start gl-flex-shrink-0 gl-mr-3', size: 48, avatar_options: { itemprop: 'image' })
|
||||
%h1.home-panel-title.gl-heading-1.gl-mt-3.gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-gap-3.gl-word-break-word{ class: 'gl-mb-0!', data: { testid: 'project-name-content' }, itemprop: 'name' }
|
||||
%h1.home-panel-title.gl-heading-1.gl-mt-3.gl-display-flex.gl-align-items-center.gl-flex-wrap.gl-gap-3.gl-break-anywhere{ class: 'gl-mb-0!', data: { testid: 'project-name-content' }, itemprop: 'name' }
|
||||
= @project.name
|
||||
= visibility_level_content(@project, css_class: 'visibility-icon gl-display-inline-flex gl-text-secondary', icon_css_class: 'icon')
|
||||
= render_if_exists 'compliance_management/compliance_framework/compliance_framework_badge', project: @project, additional_classes: 'gl-align-self-center'
|
||||
|
|
|
|||
|
|
@ -14,7 +14,7 @@
|
|||
|
||||
.detail-page-header.border-bottom-0.gl-display-block.gl-pt-5{ class: "gl-sm-display-flex! #{'is-merge-request' if !fluid_layout}" }
|
||||
.detail-page-header-body
|
||||
%h1.title.page-title.gl-font-size-h-display.gl-my-0.gl-display-inline-block.gl-flex-grow-1.gl-word-break-word{ data: { testid: 'title-content' } }
|
||||
%h1.title.page-title.gl-font-size-h-display.gl-my-0.gl-display-inline-block.gl-flex-grow-1.gl-break-anywhere{ data: { testid: 'title-content' } }
|
||||
= markdown_field(@merge_request, :title)
|
||||
|
||||
- unless hide_gutter_toggle
|
||||
|
|
|
|||
|
|
@ -24,7 +24,7 @@
|
|||
- else
|
||||
= render Pajamas::AvatarComponent.new(project, size: 48, alt: '')
|
||||
|
||||
.gl-w-full.gl-pt-2.gl-word-break-word
|
||||
.gl-w-full.gl-pt-2.gl-break-anywhere
|
||||
.gl-display-flex.gl-align-items-center.gl-flex-wrap
|
||||
%h2.gl-font-base.gl-line-height-20.gl-my-0
|
||||
= link_to project_path(project), class: 'text-plain gl-mr-3 js-prefetch-document', title: project.name do
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@
|
|||
= render 'devise/shared/tab_single', tab_title: _('Authorize identity provider link')
|
||||
%h4.gl-mt-0= safe_format(s_('Allow %{strongOpen}%{provider}%{strongClose} to sign you in?'), tag_pair(tag.strong, :strongOpen, :strongClose), provider: provider)
|
||||
%p= safe_format(s_('Authorizing allows you to sign in with %{strongOpen}%{provider}%{strongClose}.'), tag_pair(tag.strong, :strongOpen, :strongClose), provider: provider)
|
||||
= render Pajamas::AlertComponent.new(variant: :warning, dismissible: false, alert_options: { class: 'gl-mb-5 gl-word-break-word' }) do |c|
|
||||
= render Pajamas::AlertComponent.new(variant: :warning, dismissible: false, alert_options: { class: 'gl-mb-5 gl-break-anywhere' }) do |c|
|
||||
- c.with_body do
|
||||
= safe_format(_('To allow %{strongOpen}%{provider}%{strongClose} to manage your GitLab account %{strongOpen}%{username}%{strongClose} (%{email}) after you sign in successfully using single sign-on, select %{strongOpen}Authorize%{strongClose}.'), tag_pair(tag.strong, :strongOpen, :strongClose), provider: provider, username: current_user.username, email: current_user.email)
|
||||
|
||||
|
|
|
|||
|
|
@ -31,6 +31,10 @@ function gitLabUIUtilities({ addUtilities }) {
|
|||
'var(--default-mono-font, "GitLab Mono"), "JetBrains Mono", "Menlo", "DejaVu Sans Mono", "Liberation Mono", "Consolas", "Ubuntu Mono", "Courier New", "andale mono", "lucida console", monospace',
|
||||
'font-variant-ligatures': 'none',
|
||||
},
|
||||
'.break-anywhere': {
|
||||
'overflow-wrap': 'anywhere',
|
||||
'word-break': 'normal',
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -23,3 +23,4 @@ desired_sharding_key:
|
|||
table: merge_requests
|
||||
sharding_key: target_project_id
|
||||
belongs_to: merge_request
|
||||
desired_sharding_key_migration_job_name: BackfillApprovalMergeRequestRulesProjectId
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
---
|
||||
migration_job_name: BackfillApprovalMergeRequestRulesProjectId
|
||||
description: Backfills sharding key `approval_merge_request_rules.project_id` from `merge_requests`.
|
||||
feature_category: code_review_workflow
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/151630
|
||||
milestone: '17.0'
|
||||
queued_migration_version: 20240501044351
|
||||
finalize_after: '2024-06-22'
|
||||
finalized_by: # version of the migration that finalized this BBM
|
||||
|
|
@ -1,9 +1,11 @@
|
|||
---
|
||||
migration_job_name: BackfillArchivedAndTraversalIdsToVulnerabilityReads
|
||||
description: Backfill project.archived and project.namespace.traversal_ids values to the denormalized columns of the same name on vulnerability_reads. No-oped and requeued in job RequeueBackfillArchivedAndTraversalIdsToVulnerabilityReads.
|
||||
description: Backfill project.archived and project.namespace.traversal_ids values
|
||||
to the denormalized columns of the same name on vulnerability_reads. No-oped and
|
||||
requeued in job RequeueBackfillArchivedAndTraversalIdsToVulnerabilityReads.
|
||||
feature_category: vulnerability_management
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/144765
|
||||
milestone: '16.10'
|
||||
queued_migration_version: 20240214163238
|
||||
finalize_after: '2024-03-15'
|
||||
finalized_by:
|
||||
finalized_by: '20240513231841'
|
||||
|
|
|
|||
|
|
@ -8,3 +8,4 @@ description: TODO
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56344
|
||||
milestone: '13.11'
|
||||
gitlab_schema: gitlab_main
|
||||
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442659
|
||||
|
|
|
|||
|
|
@ -8,3 +8,4 @@ description: TODO
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/55681
|
||||
milestone: '13.12'
|
||||
gitlab_schema: gitlab_main
|
||||
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442660
|
||||
|
|
|
|||
|
|
@ -8,3 +8,4 @@ description: TODO
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/48334
|
||||
milestone: '13.8'
|
||||
gitlab_schema: gitlab_main
|
||||
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442661
|
||||
|
|
|
|||
|
|
@ -8,3 +8,4 @@ description: TODO
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/34069
|
||||
milestone: '13.2'
|
||||
gitlab_schema: gitlab_main
|
||||
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442662
|
||||
|
|
|
|||
|
|
@ -9,3 +9,4 @@ description: Represents an Advanced Search index
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/113612/
|
||||
milestone: '15.11'
|
||||
gitlab_schema: gitlab_main
|
||||
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442663
|
||||
|
|
|
|||
|
|
@ -9,3 +9,4 @@ description: Describes a Zoekt server that will be used for indexing and search
|
|||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/105049
|
||||
milestone: '15.9'
|
||||
gitlab_schema: gitlab_main
|
||||
sharding_key_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/442657
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddProjectIdToApprovalMergeRequestRules < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.0'
|
||||
|
||||
def change
|
||||
add_column :approval_merge_request_rules, :project_id, :bigint
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class IndexApprovalMergeRequestRulesOnProjectId < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.0'
|
||||
disable_ddl_transaction!
|
||||
|
||||
INDEX_NAME = 'index_approval_merge_request_rules_on_project_id'
|
||||
|
||||
def up
|
||||
add_concurrent_index :approval_merge_request_rules, :project_id, name: INDEX_NAME
|
||||
end
|
||||
|
||||
def down
|
||||
remove_concurrent_index_by_name :approval_merge_request_rules, INDEX_NAME
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,16 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddApprovalMergeRequestRulesProjectIdFk < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.0'
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_concurrent_foreign_key :approval_merge_request_rules, :projects, column: :project_id, on_delete: :cascade
|
||||
end
|
||||
|
||||
def down
|
||||
with_lock_retries do
|
||||
remove_foreign_key :approval_merge_request_rules, column: :project_id
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddApprovalMergeRequestRulesProjectIdTrigger < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.0'
|
||||
|
||||
def up
|
||||
install_sharding_key_assignment_trigger(
|
||||
table: :approval_merge_request_rules,
|
||||
sharding_key: :project_id,
|
||||
parent_table: :merge_requests,
|
||||
parent_sharding_key: :target_project_id,
|
||||
foreign_key: :merge_request_id
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
remove_sharding_key_assignment_trigger(
|
||||
table: :approval_merge_request_rules,
|
||||
sharding_key: :project_id,
|
||||
parent_table: :merge_requests,
|
||||
parent_sharding_key: :target_project_id,
|
||||
foreign_key: :merge_request_id
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class QueueBackfillApprovalMergeRequestRulesProjectId < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.0'
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main_cell
|
||||
|
||||
MIGRATION = "BackfillApprovalMergeRequestRulesProjectId"
|
||||
DELAY_INTERVAL = 2.minutes
|
||||
BATCH_SIZE = 1000
|
||||
SUB_BATCH_SIZE = 100
|
||||
|
||||
def up
|
||||
queue_batched_background_migration(
|
||||
MIGRATION,
|
||||
:approval_merge_request_rules,
|
||||
:id,
|
||||
:project_id,
|
||||
:merge_requests,
|
||||
:target_project_id,
|
||||
:merge_request_id,
|
||||
job_interval: DELAY_INTERVAL,
|
||||
batch_size: BATCH_SIZE,
|
||||
sub_batch_size: SUB_BATCH_SIZE
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
delete_batched_background_migration(
|
||||
MIGRATION,
|
||||
:approval_merge_request_rules,
|
||||
:id,
|
||||
[
|
||||
:project_id,
|
||||
:merge_requests,
|
||||
:target_project_id,
|
||||
:merge_request_id
|
||||
]
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class FinalizeBackfillArchivedAndTraversalIdsToVulnerabilityReads < Gitlab::Database::Migration[2.2]
|
||||
milestone '17.0'
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
def up
|
||||
ensure_batched_background_migration_is_finished(
|
||||
job_class_name: 'BackfillArchivedAndTraversalIdsToVulnerabilityReads',
|
||||
table_name: :vulnerability_reads,
|
||||
column_name: :id,
|
||||
job_arguments: [],
|
||||
finalize: true
|
||||
)
|
||||
end
|
||||
|
||||
def down; end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
dfce55f9bc75cc5c2781a4facac3638979345cdf79132b7789fe812bbd75c2ab
|
||||
|
|
@ -0,0 +1 @@
|
|||
d59f45b47fad1f968c4406afcf5a411339509ebb3c824c3d494e95d2b9f0ed28
|
||||
|
|
@ -0,0 +1 @@
|
|||
a8ab824118902e1d4cfbd02c551ad67d541126d89c28cb6b06728483d4e9851a
|
||||
|
|
@ -0,0 +1 @@
|
|||
a4f37df2585fb1234dbeb478bb2c59478b5c7b13749f84826d262f806f47c0db
|
||||
|
|
@ -0,0 +1 @@
|
|||
baa0cadb88abee532373ca3800d135645bf2e8a42558f9f7ddb17a79024eab60
|
||||
|
|
@ -0,0 +1 @@
|
|||
7ff0d546bcdd55adad6153210404eeb6e4d4db644b146570efc820344ae13883
|
||||
|
|
@ -704,6 +704,22 @@ $$;
|
|||
|
||||
COMMENT ON FUNCTION table_sync_function_3f39f64fc3() IS 'Partitioning migration: table sync for merge_request_diff_files table';
|
||||
|
||||
CREATE FUNCTION trigger_01b3fc052119() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
BEGIN
|
||||
IF NEW."project_id" IS NULL THEN
|
||||
SELECT "target_project_id"
|
||||
INTO NEW."project_id"
|
||||
FROM "merge_requests"
|
||||
WHERE "merge_requests"."id" = NEW."merge_request_id";
|
||||
END IF;
|
||||
|
||||
RETURN NEW;
|
||||
|
||||
END
|
||||
$$;
|
||||
|
||||
CREATE FUNCTION trigger_10ee1357e825() RETURNS trigger
|
||||
LANGUAGE plpgsql
|
||||
AS $$
|
||||
|
|
@ -4753,6 +4769,7 @@ CREATE TABLE approval_merge_request_rules (
|
|||
security_orchestration_policy_configuration_id bigint,
|
||||
scan_result_policy_id bigint,
|
||||
applicable_post_merge boolean,
|
||||
project_id bigint,
|
||||
CONSTRAINT check_6fca5928b2 CHECK ((char_length(section) <= 255))
|
||||
);
|
||||
|
||||
|
|
@ -24497,6 +24514,8 @@ CREATE UNIQUE INDEX index_approval_merge_request_rules_groups_1 ON approval_merg
|
|||
|
||||
CREATE INDEX index_approval_merge_request_rules_groups_2 ON approval_merge_request_rules_groups USING btree (group_id);
|
||||
|
||||
CREATE INDEX index_approval_merge_request_rules_on_project_id ON approval_merge_request_rules USING btree (project_id);
|
||||
|
||||
CREATE UNIQUE INDEX index_approval_merge_request_rules_users_1 ON approval_merge_request_rules_users USING btree (approval_merge_request_rule_id, user_id);
|
||||
|
||||
CREATE INDEX index_approval_merge_request_rules_users_2 ON approval_merge_request_rules_users USING btree (user_id);
|
||||
|
|
@ -29855,6 +29874,8 @@ CREATE TRIGGER table_sync_trigger_cd362c20e2 AFTER INSERT OR DELETE OR UPDATE ON
|
|||
|
||||
CREATE TRIGGER tags_loose_fk_trigger AFTER DELETE ON tags REFERENCING OLD TABLE AS old_table FOR EACH STATEMENT EXECUTE FUNCTION insert_into_loose_foreign_keys_deleted_records();
|
||||
|
||||
CREATE TRIGGER trigger_01b3fc052119 BEFORE INSERT OR UPDATE ON approval_merge_request_rules FOR EACH ROW EXECUTE FUNCTION trigger_01b3fc052119();
|
||||
|
||||
CREATE TRIGGER trigger_10ee1357e825 BEFORE INSERT OR UPDATE ON p_ci_builds FOR EACH ROW EXECUTE FUNCTION trigger_10ee1357e825();
|
||||
|
||||
CREATE TRIGGER trigger_174b23fa3dfb BEFORE INSERT OR UPDATE ON approval_project_rules_users FOR EACH ROW EXECUTE FUNCTION trigger_174b23fa3dfb();
|
||||
|
|
@ -30985,6 +31006,9 @@ ALTER TABLE p_ci_builds_metadata
|
|||
ALTER TABLE ONLY gitlab_subscriptions
|
||||
ADD CONSTRAINT fk_e2595d00a1 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY approval_merge_request_rules
|
||||
ADD CONSTRAINT fk_e33a9aaf67 FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE;
|
||||
|
||||
ALTER TABLE ONLY abuse_events
|
||||
ADD CONSTRAINT fk_e5ce49c215 FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE SET NULL;
|
||||
|
||||
|
|
|
|||
|
|
@ -265,8 +265,9 @@ The default expiration and the expiration on GitLab.com is 15 minutes.
|
|||
|
||||
```ruby
|
||||
gitlab_workhorse['env'] = {
|
||||
"http_proxy" => "http://USERNAME:PASSWORD@example.com:8080",
|
||||
"https_proxy" => "http://USERNAME:PASSWORD@example.com:8080"
|
||||
"http_proxy" => "http://USERNAME:PASSWORD@example.com:8080",
|
||||
"https_proxy" => "http://USERNAME:PASSWORD@example.com:8080"
|
||||
}
|
||||
```
|
||||
|
||||
1. Save the file and [reconfigure GitLab](../restart_gitlab.md#reconfigure-a-linux-package-installation) for the changes to take effect.
|
||||
|
|
|
|||
|
|
@ -9,9 +9,9 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
DETAILS:
|
||||
**Tier:** Free, Premium, Ultimate
|
||||
**Offering:** GitLab.com, Self-managed, GitLab Dedicated
|
||||
**Status:** Beta
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/391331) in GitLab 15.11 as a Beta feature.
|
||||
> - [Made Generally Available](https://gitlab.com/gitlab-com/www-gitlab-com/-/merge_requests/134062) in GitLab 17.0.
|
||||
|
||||
Use inputs to increase the flexibility of CI/CD configuration files that are designed
|
||||
to be reused.
|
||||
|
|
|
|||
|
|
@ -37,13 +37,6 @@ You can create, edit, or delete a compliance framework from a compliance project
|
|||
- [Edit a compliance framework](../../user/compliance/compliance_center/compliance_projects_report.md#edit-a-compliance-framework).
|
||||
- [Delete a compliance framework](../../user/compliance/compliance_center/compliance_projects_report.md#delete-a-compliance-framework).
|
||||
|
||||
### From group settings
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your group.
|
||||
1. Select **Settings** > **General**.
|
||||
1. Expand the **Compliance frameworks** section.
|
||||
1. Create, edit, or delete compliance frameworks.
|
||||
|
||||
Subgroups and projects have access to all compliance frameworks created on their top-level group. However, compliance frameworks cannot be created, edited,
|
||||
or deleted at the subgroup or project level. Project owners can choose a framework to apply to their projects.
|
||||
|
||||
|
|
@ -61,16 +54,6 @@ Frameworks cannot be added to projects in personal namespaces.
|
|||
To assign a compliance framework to a project, apply the compliance framework through the
|
||||
[Compliance projects report](../../user/compliance/compliance_center/compliance_projects_report.md#apply-a-compliance-framework-to-projects-in-a-group).
|
||||
|
||||
### From group settings
|
||||
|
||||
To assign a compliance framework to a project:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project.
|
||||
1. Select **Settings** > **General**.
|
||||
1. Expand **Compliance frameworks**.
|
||||
1. Select a compliance framework.
|
||||
1. Select **Save changes**.
|
||||
|
||||
### GraphQL API
|
||||
|
||||
You can use the [GraphQL API](../../api/graphql/reference/index.md#mutationprojectsetcomplianceframework) to add a
|
||||
|
|
@ -115,18 +98,6 @@ To set as default (or remove the default) from [compliance framework report](../
|
|||
1. Select **Set as default**.
|
||||
1. Select **Save changes**.
|
||||
|
||||
#### From group settings
|
||||
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/375038) in GitLab 15.7.
|
||||
|
||||
To set as default (or remove the default) by using group settings:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your group.
|
||||
1. Select **Settings > General**.
|
||||
1. Expand the **Compliance frameworks** section and locate the compliance framework to set (or remove) as default.
|
||||
1. Select the vertical ellipsis (**{ellipsis_v}**) for the compliance frame and then select **Set default** (or
|
||||
**Remove default**).
|
||||
|
||||
#### Example GraphQL mutations for setting a default compliance framework
|
||||
|
||||
Creating a new compliance framework and setting it as the default framework for the group.
|
||||
|
|
@ -178,13 +149,3 @@ Prerequisites:
|
|||
|
||||
To remove a compliance framework from one or multiple project in a group, remove the compliance framework through the
|
||||
[Compliance projects report](../../user/compliance/compliance_center/compliance_projects_report.md#remove-a-compliance-framework-from-projects-in-a-group).
|
||||
|
||||
### From group settings
|
||||
|
||||
To remove a compliance framework from one project in a group:
|
||||
|
||||
1. On the left sidebar, select **Search or go to** and find your project.
|
||||
1. Select **Settings** > **General**.
|
||||
1. Expand **Compliance frameworks**.
|
||||
1. Select **None**.
|
||||
1. Select **Save changes**.
|
||||
|
|
|
|||
|
|
@ -21,6 +21,10 @@ You can migrate GitLab groups:
|
|||
- From one self-managed GitLab instance to another.
|
||||
- Between groups in the same GitLab instance.
|
||||
|
||||
Migration by direct transfer creates a new copy of the group. If you want to move groups instead of copying groups, you
|
||||
can [transfer groups](../manage.md#transfer-a-group) if the groups are in the same GitLab instance. Transferring groups
|
||||
instead of migrating them is a faster and more complete option.
|
||||
|
||||
You can migrate groups in two ways:
|
||||
|
||||
- By direct transfer (recommended).
|
||||
|
|
@ -55,9 +59,6 @@ ready for production use.
|
|||
We invite you to leave your feedback about migrating by direct transfer in
|
||||
[the feedback issue](https://gitlab.com/gitlab-org/gitlab/-/issues/284495).
|
||||
|
||||
If you want to move groups instead of copying groups, you can [transfer groups](../manage.md#transfer-a-group) if the
|
||||
groups are in the same GitLab instance. Transferring groups is a faster and more complete option.
|
||||
|
||||
## Known issues
|
||||
|
||||
- Because of [issue 406685](https://gitlab.com/gitlab-org/gitlab/-/issues/406685), files with a filename longer than 255 characters are not migrated.
|
||||
|
|
|
|||
|
|
@ -99,9 +99,14 @@ module API
|
|||
end
|
||||
post ":id/hooks" do
|
||||
hook_params = create_hook_params
|
||||
hook = user_project.hooks.new(hook_params)
|
||||
|
||||
save_hook(hook, Entities::ProjectHook)
|
||||
result = WebHooks::CreateService.new(current_user).execute(hook_params, hook_scope)
|
||||
|
||||
if result[:status] == :success
|
||||
present result[:hook], with: Entities::ProjectHook
|
||||
else
|
||||
error!(result.message, result.http_status || 422)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Edit project hook' do
|
||||
|
|
|
|||
|
|
@ -82,9 +82,14 @@ module API
|
|||
end
|
||||
post do
|
||||
hook_params = create_hook_params
|
||||
hook = SystemHook.new(hook_params)
|
||||
|
||||
save_hook(hook, Entities::Hook)
|
||||
result = WebHooks::CreateService.new(current_user).execute(hook_params, hook_scope)
|
||||
|
||||
if result[:status] == :success
|
||||
present result[:hook], with: Entities::Hook
|
||||
else
|
||||
error!(result.message, result.http_status || 422)
|
||||
end
|
||||
end
|
||||
|
||||
desc 'Edit system hook' do
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Gitlab
|
||||
module BackgroundMigration
|
||||
# rubocop: disable Migration/BackgroundMigrationBaseClass -- BackfillDesiredShardingKeyJob inherits from BatchedMigrationJob.
|
||||
class BackfillApprovalMergeRequestRulesProjectId < BackfillDesiredShardingKeyJob
|
||||
operation_name :backfill_approval_merge_request_rules_project_id
|
||||
feature_category :code_review_workflow
|
||||
end
|
||||
# rubocop: enable Migration/BackgroundMigrationBaseClass
|
||||
end
|
||||
end
|
||||
|
|
@ -69,6 +69,7 @@ module Gitlab
|
|||
GEO_NODES_LOAD = 'SELECT 1 AS one FROM "geo_nodes" LIMIT 1'
|
||||
LICENSES_LOAD = 'SELECT "licenses".* FROM "licenses" ORDER BY "licenses"."id"'
|
||||
SCHEMA_INTROSPECTION = %r{SELECT.*(FROM|JOIN) (pg_attribute|pg_class)}m
|
||||
SAVEPOINT = %r{(RELEASE )?SAVEPOINT}m
|
||||
|
||||
# queries can be safely ignored if they are amoritized in regular usage
|
||||
# (i.e. only requested occasionally and otherwise cached).
|
||||
|
|
@ -76,6 +77,7 @@ module Gitlab
|
|||
return true if sql&.include?(GEO_NODES_LOAD)
|
||||
return true if sql&.include?(LICENSES_LOAD)
|
||||
return true if SCHEMA_INTROSPECTION.match?(sql)
|
||||
return true if SAVEPOINT.match?(sql)
|
||||
|
||||
false
|
||||
end
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ describe('Workload table component', () => {
|
|||
key: 'name',
|
||||
label: 'Name',
|
||||
sortable: true,
|
||||
tdClass: 'gl-md-w-half gl-lg-w-40p gl-word-break-word',
|
||||
tdClass: 'gl-md-w-half gl-lg-w-40p gl-break-anywhere',
|
||||
},
|
||||
{
|
||||
key: 'status',
|
||||
|
|
@ -49,7 +49,7 @@ describe('Workload table component', () => {
|
|||
key: 'namespace',
|
||||
label: 'Namespace',
|
||||
sortable: true,
|
||||
tdClass: 'gl-md-w-30p gl-lg-w-40p gl-word-break-word',
|
||||
tdClass: 'gl-md-w-30p gl-lg-w-40p gl-break-anywhere',
|
||||
},
|
||||
{
|
||||
key: 'age',
|
||||
|
|
|
|||
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::BackgroundMigration::BackfillApprovalMergeRequestRulesProjectId,
|
||||
feature_category: :code_review_workflow,
|
||||
schema: 20240501044347 do
|
||||
include_examples 'desired sharding key backfill job' do
|
||||
let(:batch_table) { :approval_merge_request_rules }
|
||||
let(:backfill_column) { :project_id }
|
||||
let(:backfill_via_table) { :merge_requests }
|
||||
let(:backfill_via_column) { :target_project_id }
|
||||
let(:backfill_via_foreign_key) { :merge_request_id }
|
||||
end
|
||||
end
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe Gitlab::QueryLimiting::Transaction do
|
||||
RSpec.describe Gitlab::QueryLimiting::Transaction, feature_category: :database do
|
||||
after do
|
||||
Thread.current[described_class::THREAD_KEY] = nil
|
||||
end
|
||||
|
|
@ -87,6 +87,8 @@ RSpec.describe Gitlab::QueryLimiting::Transaction do
|
|||
transaction.increment(described_class::LICENSES_LOAD)
|
||||
transaction.increment('SELECT a.attname, a.other_column FROM pg_attribute a')
|
||||
transaction.increment('SELECT x.foo, a.attname FROM some_table x JOIN pg_attribute a')
|
||||
transaction.increment('SAVEPOINT active_record_2')
|
||||
transaction.increment('RELEASE SAVEPOINT active_record_2')
|
||||
transaction.increment(<<-SQL)
|
||||
SELECT a.attname, a.other_column
|
||||
FROM pg_attribute a
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
require_migration!
|
||||
|
||||
RSpec.describe QueueBackfillApprovalMergeRequestRulesProjectId, feature_category: :code_review_workflow do
|
||||
let!(:batched_migration) { described_class::MIGRATION }
|
||||
|
||||
it 'schedules a new batched migration' do
|
||||
reversible_migration do |migration|
|
||||
migration.before -> {
|
||||
expect(batched_migration).not_to have_scheduled_batched_migration
|
||||
}
|
||||
|
||||
migration.after -> {
|
||||
expect(batched_migration).to have_scheduled_batched_migration(
|
||||
table_name: :approval_merge_request_rules,
|
||||
column_name: :id,
|
||||
interval: described_class::DELAY_INTERVAL,
|
||||
batch_size: described_class::BATCH_SIZE,
|
||||
sub_batch_size: described_class::SUB_BATCH_SIZE,
|
||||
gitlab_schema: :gitlab_main_cell,
|
||||
job_arguments: [
|
||||
:project_id,
|
||||
:merge_requests,
|
||||
:target_project_id,
|
||||
:merge_request_id
|
||||
]
|
||||
)
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe WebHooks::CreateService, feature_category: :webhooks do
|
||||
let_it_be(:current_user) { create(:user) }
|
||||
|
||||
describe '#execute' do
|
||||
let_it_be(:project) { create(:project) }
|
||||
let_it_be(:relation) { ProjectHook.none }
|
||||
let(:hook_params) { { url: 'https://example.com/hook', project_id: project.id } }
|
||||
|
||||
subject(:webhook_created) { described_class.new(current_user) }
|
||||
|
||||
context 'when creating a new hook' do
|
||||
it 'creates a new hook' do
|
||||
expect do
|
||||
response = webhook_created.execute(hook_params, relation)
|
||||
|
||||
expect(response).to be_success
|
||||
expect(response[:async]).to eq(false)
|
||||
end.to change { ProjectHook.count }.by(1)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the URL is invalid' do
|
||||
it 'returns an error response' do
|
||||
hook_params[:url] = 'invalid_url'
|
||||
|
||||
response = webhook_created.execute(hook_params, relation)
|
||||
|
||||
expect(response).not_to be_success
|
||||
expect(response[:message]).to eq("Invalid url given")
|
||||
expect(response[:http_status]).to eq(422)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the branch filter is invalid' do
|
||||
let(:invalid_params) { hook_params.merge(push_events_branch_filter: 'bad branch name') }
|
||||
|
||||
it 'returns an error response' do
|
||||
response = webhook_created.execute(invalid_params, relation)
|
||||
|
||||
expect(response).not_to be_success
|
||||
expect(response[:message]).to eq("Invalid branch filter given")
|
||||
expect(response[:http_status]).to eq(422)
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the project is not provided' do
|
||||
let(:invalid_params) { hook_params.merge(project_id: nil) }
|
||||
|
||||
it 'returns an error response for missing project' do
|
||||
response = webhook_created.execute(invalid_params, relation)
|
||||
|
||||
expect(response).not_to be_success
|
||||
expect(response[:message]).to eq("Project can't be blank")
|
||||
expect(response[:http_status]).to eq(422)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
Loading…
Reference in New Issue