Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
8c9cb9bb57
commit
7d8cc770b1
|
|
@ -123,6 +123,7 @@ detect-tests:
|
|||
tooling/bin/partial_to_views_mappings ${RSPEC_CHANGED_FILES_PATH} ${RSPEC_VIEWS_INCLUDING_PARTIALS_PATH};
|
||||
tooling/bin/find_tests ${RSPEC_VIEWS_INCLUDING_PARTIALS_PATH} ${RSPEC_MATCHING_TESTS_PATH};
|
||||
tooling/bin/js_to_system_specs_mappings ${RSPEC_CHANGED_FILES_PATH} ${RSPEC_MATCHING_TESTS_PATH};
|
||||
tooling/bin/graphql_base_type_mappings ${RSPEC_CHANGED_FILES_PATH} ${RSPEC_MATCHING_TESTS_PATH};
|
||||
tooling/bin/find_changes ${RSPEC_CHANGED_FILES_PATH} ${RSPEC_MATCHING_TESTS_PATH} ${FRONTEND_FIXTURES_MAPPING_PATH};
|
||||
filter_rspec_matched_foss_tests ${RSPEC_MATCHING_TESTS_PATH} ${RSPEC_MATCHING_TESTS_FOSS_PATH};
|
||||
filter_rspec_matched_ee_tests ${RSPEC_MATCHING_TESTS_PATH} ${RSPEC_MATCHING_TESTS_EE_PATH};
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
28a95b4b97a1f2b2187cccfa05feebf073d0696b
|
||||
0c5b7fc851773654a7e2dedf195eb55409967284
|
||||
|
|
|
|||
|
|
@ -1 +1 @@
|
|||
v15.10.0
|
||||
v15.11.0-rc1
|
||||
|
|
|
|||
|
|
@ -1,16 +1,18 @@
|
|||
<script>
|
||||
import { debounce, uniq } from 'lodash';
|
||||
import { GlDropdownDivider, GlDropdownItem, GlCollapsibleListbox } from '@gitlab/ui';
|
||||
import { GlDropdownDivider, GlDropdownItem, GlCollapsibleListbox, GlSprintf } from '@gitlab/ui';
|
||||
import glFeatureFlagsMixin from '~/vue_shared/mixins/gl_feature_flags_mixin';
|
||||
import { __, s__, sprintf } from '~/locale';
|
||||
import { convertEnvironmentScope } from '../utils';
|
||||
import { ENVIRONMENT_QUERY_LIMIT } from '../constants';
|
||||
|
||||
export default {
|
||||
name: 'CiEnvironmentsDropdown',
|
||||
components: {
|
||||
GlCollapsibleListbox,
|
||||
GlDropdownDivider,
|
||||
GlDropdownItem,
|
||||
GlCollapsibleListbox,
|
||||
GlSprintf,
|
||||
},
|
||||
mixins: [glFeatureFlagsMixin()],
|
||||
props: {
|
||||
|
|
@ -95,9 +97,10 @@ export default {
|
|||
this.selectEnvironment(this.searchTerm);
|
||||
},
|
||||
},
|
||||
ENVIRONMENT_QUERY_LIMIT,
|
||||
i18n: {
|
||||
maxEnvsNote: s__(
|
||||
'CiVariable|Maximum of 20 environments listed. For more environments, enter a search query.',
|
||||
'CiVariable|Maximum of %{limit} environments listed. For more environments, enter a search query.',
|
||||
),
|
||||
},
|
||||
};
|
||||
|
|
@ -117,9 +120,11 @@ export default {
|
|||
<gl-dropdown-divider v-if="shouldRenderDivider" />
|
||||
<div v-if="isEnvScopeLimited" data-testid="max-envs-notice">
|
||||
<gl-dropdown-item class="gl-list-style-none" disabled>
|
||||
<span class="gl-font-sm">
|
||||
{{ $options.i18n.maxEnvsNote }}
|
||||
</span>
|
||||
<gl-sprintf :message="$options.i18n.maxEnvsNote" class="gl-font-sm">
|
||||
<template #limit>
|
||||
{{ $options.ENVIRONMENT_QUERY_LIMIT }}
|
||||
</template>
|
||||
</gl-sprintf>
|
||||
</gl-dropdown-item>
|
||||
</div>
|
||||
<div v-if="shouldRenderCreateButton">
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
import { __, s__ } from '~/locale';
|
||||
|
||||
export const ADD_CI_VARIABLE_MODAL_ID = 'add-ci-variable';
|
||||
export const ENVIRONMENT_QUERY_LIMIT = 20;
|
||||
export const ENVIRONMENT_QUERY_LIMIT = 30;
|
||||
|
||||
export const SORT_DIRECTIONS = {
|
||||
ASC: 'KEY_ASC',
|
||||
|
|
|
|||
|
|
@ -21,7 +21,7 @@ export default {
|
|||
editCommentLabel: __('Edit comment'),
|
||||
deleteCommentLabel: __('Delete comment'),
|
||||
moreActionsLabel: __('More actions'),
|
||||
reportAbuse: __('Report abuse to administrator'),
|
||||
reportAbuse: __('Report abuse'),
|
||||
},
|
||||
name: 'NoteActions',
|
||||
components: {
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ export default {
|
|||
|
||||
<template>
|
||||
<div
|
||||
class="gl-display-flex gl-sm-align-items-center gl-flex-direction-column gl-sm-flex-direction-row gl-justify-content-space-between gl-pt-5"
|
||||
class="gl-display-flex gl-sm-align-items-center gl-flex-direction-column gl-sm-flex-direction-row gl-justify-content-space-between gl-pt-5 gl-pb-3"
|
||||
>
|
||||
<h2 class="gl-font-size-h1 gl-m-0">{{ __('Activity') }}</h2>
|
||||
<div class="gl-display-flex gl-gap-3 gl-w-full gl-sm-w-auto gl-mt-3 gl-sm-mt-0">
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
import { initLinkToSpam } from '~/abuse_reports';
|
||||
import initFilePickers from '~/file_pickers';
|
||||
|
||||
initLinkToSpam();
|
||||
initFilePickers();
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ export default {
|
|||
v-if="userPermissions.canMerge"
|
||||
size="small"
|
||||
variant="confirm"
|
||||
category="secondary"
|
||||
category="tertiary"
|
||||
data-testid="merge-locally-button"
|
||||
class="js-check-out-modal-trigger gl-align-self-start"
|
||||
>
|
||||
|
|
|
|||
|
|
@ -983,8 +983,8 @@ $tabs-holder-z-index: 250;
|
|||
.merge-request-overview {
|
||||
@include media-breakpoint-up(lg) {
|
||||
display: grid;
|
||||
grid-template-columns: calc(95% - 285px) auto;
|
||||
grid-gap: 5%;
|
||||
grid-template-columns: calc(97% - 285px) auto;
|
||||
grid-gap: 3%;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ class AbuseReportsController < ApplicationController
|
|||
private
|
||||
|
||||
def report_params
|
||||
params.require(:abuse_report).permit(:message, :user_id, :category, :reported_from_url, links_to_spam: [])
|
||||
params.require(:abuse_report).permit(:message, :user_id, :category, :reported_from_url, :screenshot, links_to_spam: [])
|
||||
end
|
||||
|
||||
# rubocop: disable CodeReuse/ActiveRecord
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ module Admin
|
|||
def index
|
||||
@relations_by_tab = {
|
||||
'queued' => batched_migration_class.queued.queue_order,
|
||||
'finalizing' => batched_migration_class.finalizing.queue_order,
|
||||
'failed' => batched_migration_class.with_status(:failed).queue_order,
|
||||
'finished' => batched_migration_class.with_status(:finished).queue_order.reverse_order
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ module UploadsActions
|
|||
include Gitlab::Utils::StrongMemoize
|
||||
include SendFileUpload
|
||||
|
||||
UPLOAD_MOUNTS = %w[avatar attachment file logo pwa_icon header_logo favicon].freeze
|
||||
UPLOAD_MOUNTS = %w[avatar attachment file logo pwa_icon header_logo favicon screenshot].freeze
|
||||
|
||||
included do
|
||||
prepend_before_action :set_request_format_from_path_extension
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@ class UploadsController < ApplicationController
|
|||
"projects/topic" => Projects::Topic,
|
||||
'alert_management_metric_image' => ::AlertManagement::MetricImage,
|
||||
"achievements/achievement" => Achievements::Achievement,
|
||||
"abuse_report" => AbuseReport,
|
||||
nil => PersonalSnippet
|
||||
}.freeze
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,34 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module DataTransfer
|
||||
class GroupDataTransferFinder
|
||||
def initialize(group:, from:, to:, user:)
|
||||
@group = group
|
||||
@from = from
|
||||
@to = to
|
||||
@user = user
|
||||
end
|
||||
|
||||
def execute
|
||||
return ::Projects::DataTransfer.none unless Ability.allowed?(user, :read_usage_quotas, group)
|
||||
|
||||
::Projects::DataTransfer
|
||||
.with_namespace_between_dates(group, from, to)
|
||||
.select('SUM(repository_egress
|
||||
+ artifacts_egress
|
||||
+ packages_egress
|
||||
+ registry_egress
|
||||
) as total_egress,
|
||||
SUM(repository_egress) as repository_egress,
|
||||
SUM(artifacts_egress) as artifacts_egress,
|
||||
SUM(packages_egress) as packages_egress,
|
||||
SUM(registry_egress) as registry_egress,
|
||||
date,
|
||||
namespace_id')
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :group, :from, :to, :user
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Mocked data for data transfer
|
||||
# Follow this epic for recent progress: https://gitlab.com/groups/gitlab-org/-/epics/9330
|
||||
module DataTransfer
|
||||
class MockedTransferFinder
|
||||
def execute
|
||||
start_date = Date.new(2023, 0o1, 0o1)
|
||||
date_for_index = ->(i) { (start_date + i.months).strftime('%Y-%m-%d') }
|
||||
|
||||
0.upto(11).map do |i|
|
||||
{
|
||||
date: date_for_index.call(i),
|
||||
repository_egress: rand(70000..550000),
|
||||
artifacts_egress: rand(70000..550000),
|
||||
packages_egress: rand(70000..550000),
|
||||
registry_egress: rand(70000..550000)
|
||||
}.tap do |hash|
|
||||
hash[:total_egress] = hash
|
||||
.slice(:repository_egress, :artifacts_egress, :packages_egress, :registry_egress)
|
||||
.values
|
||||
.sum
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module DataTransfer
|
||||
class ProjectDataTransferFinder
|
||||
def initialize(project:, from:, to:, user:)
|
||||
@project = project
|
||||
@from = from
|
||||
@to = to
|
||||
@user = user
|
||||
end
|
||||
|
||||
def execute
|
||||
return ::Projects::DataTransfer.none unless Ability.allowed?(user, :read_usage_quotas, project)
|
||||
|
||||
::Projects::DataTransfer
|
||||
.with_project_between_dates(project, from, to)
|
||||
.select(:project_id, :date, :repository_egress, :artifacts_egress, :packages_egress, :registry_egress,
|
||||
"repository_egress + artifacts_egress + packages_egress + registry_egress as total_egress")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
attr_reader :project, :from, :to, :user
|
||||
end
|
||||
end
|
||||
|
|
@ -3,8 +3,6 @@
|
|||
module Mutations
|
||||
module AwardEmojis
|
||||
class Base < BaseMutation
|
||||
include ::Mutations::FindsByGid
|
||||
|
||||
NOT_EMOJI_AWARDABLE = 'You cannot award emoji to this resource.'
|
||||
|
||||
authorize :award_emoji
|
||||
|
|
|
|||
|
|
@ -29,12 +29,6 @@ module Mutations
|
|||
errors: errors_on_object(board)
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -15,16 +15,12 @@ module Mutations
|
|||
description: 'ID of the runner to delete.'
|
||||
|
||||
def resolve(id:, **runner_attrs)
|
||||
runner = authorized_find!(id)
|
||||
runner = authorized_find!(id: id)
|
||||
|
||||
::Ci::Runners::UnregisterRunnerService.new(runner, current_user).execute
|
||||
|
||||
{ errors: runner.errors.full_messages }
|
||||
end
|
||||
|
||||
def find_object(id)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@ module Mutations
|
|||
description: 'Runner after mutation.'
|
||||
|
||||
def resolve(id:, **runner_attrs)
|
||||
runner = authorized_find!(id)
|
||||
runner = authorized_find!(id: id)
|
||||
|
||||
associated_projects_ids = runner_attrs.delete(:associated_projects)
|
||||
|
||||
|
|
@ -40,10 +40,6 @@ module Mutations
|
|||
response
|
||||
end
|
||||
|
||||
def find_object(id)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def associate_runner_projects(response, runner, associated_project_ids)
|
||||
|
|
|
|||
|
|
@ -54,12 +54,6 @@ module Mutations
|
|||
errors: Array.wrap(result.message)
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -21,12 +21,6 @@ module Mutations
|
|||
|
||||
{ errors: errors_on_object(token) }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -24,12 +24,6 @@ module Mutations
|
|||
errors: Array.wrap(result.message)
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,9 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mutations
|
||||
module FindsByGid
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -4,12 +4,6 @@ module Mutations
|
|||
module ContainerRepositories
|
||||
class DestroyBase < Mutations::BaseMutation
|
||||
include ::Mutations::PackageEventable
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -28,12 +28,6 @@ module Mutations
|
|||
errors: errors_on_object(design)
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -53,10 +53,6 @@ module Mutations
|
|||
end
|
||||
end
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
|
||||
def resolve!(discussion)
|
||||
::Discussions::ResolveService.new(
|
||||
discussion.project,
|
||||
|
|
|
|||
|
|
@ -35,10 +35,6 @@ module Mutations
|
|||
{ errors: Array.wrap(result[:message]) }
|
||||
end
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def certificate_based_clusters_enabled?
|
||||
|
|
|
|||
|
|
@ -83,10 +83,6 @@ module Mutations
|
|||
super(**args)
|
||||
end
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
|
||||
def annotation_create_params(args)
|
||||
annotation_source = AnnotationSource.new(object: annotation_source(args))
|
||||
|
||||
|
|
|
|||
|
|
@ -13,12 +13,6 @@ module Mutations
|
|||
Types::Notes::NoteType,
|
||||
null: true,
|
||||
description: 'Note after mutation.'
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -47,10 +47,6 @@ module Mutations
|
|||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
|
||||
def create_note_params(noteable, args)
|
||||
{
|
||||
noteable: noteable,
|
||||
|
|
|
|||
|
|
@ -23,12 +23,6 @@ module Mutations
|
|||
errors: errors
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -21,12 +21,6 @@ module Mutations
|
|||
|
||||
{ errors: package_file.errors.full_messages }
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ module Mutations
|
|||
description: 'Deleted release asset link.'
|
||||
|
||||
def resolve(id:)
|
||||
link = authorized_find!(id)
|
||||
link = authorized_find!(id: id)
|
||||
|
||||
result = ::Releases::Links::DestroyService
|
||||
.new(link.release, current_user)
|
||||
|
|
@ -31,10 +31,6 @@ module Mutations
|
|||
{ link: nil, errors: result.message }
|
||||
end
|
||||
end
|
||||
|
||||
def find_object(id)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -44,7 +44,7 @@ module Mutations
|
|||
end
|
||||
|
||||
def resolve(id:, **link_attrs)
|
||||
link = authorized_find!(id)
|
||||
link = authorized_find!(id: id)
|
||||
|
||||
result = ::Releases::Links::UpdateService
|
||||
.new(link.release, current_user, link_attrs)
|
||||
|
|
@ -56,10 +56,6 @@ module Mutations
|
|||
{ link: nil, errors: result.message }
|
||||
end
|
||||
end
|
||||
|
||||
def find_object(id)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -10,12 +10,6 @@ module Mutations
|
|||
Types::GlobalIDType[::Terraform::State],
|
||||
required: true,
|
||||
description: 'Global ID of the Terraform state.'
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -1,13 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Mutations
|
||||
module Todos
|
||||
class Base < ::Mutations::BaseMutation
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module Mutations
|
||||
module Todos
|
||||
class Create < ::Mutations::Todos::Base
|
||||
class Create < ::Mutations::BaseMutation
|
||||
graphql_name 'TodoCreate'
|
||||
|
||||
authorize :create_todo
|
||||
|
|
@ -17,7 +17,7 @@ module Mutations
|
|||
description: 'To-do item created.'
|
||||
|
||||
def resolve(target_id:)
|
||||
target = authorized_find!(target_id)
|
||||
target = authorized_find!(id: target_id)
|
||||
|
||||
todo = TodoService.new.mark_todo(target, current_user)&.first
|
||||
errors = errors_on_object(todo) if todo
|
||||
|
|
@ -27,12 +27,6 @@ module Mutations
|
|||
errors: errors
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module Mutations
|
||||
module Todos
|
||||
class MarkAllDone < ::Mutations::Todos::Base
|
||||
class MarkAllDone < ::Mutations::BaseMutation
|
||||
graphql_name 'TodosMarkAllDone'
|
||||
|
||||
authorize :update_user
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module Mutations
|
||||
module Todos
|
||||
class MarkDone < ::Mutations::Todos::Base
|
||||
class MarkDone < ::Mutations::BaseMutation
|
||||
graphql_name 'TodoMarkDone'
|
||||
|
||||
authorize :update_todo
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module Mutations
|
||||
module Todos
|
||||
class Restore < ::Mutations::Todos::Base
|
||||
class Restore < ::Mutations::BaseMutation
|
||||
graphql_name 'TodoRestore'
|
||||
|
||||
authorize :update_todo
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
|
||||
module Mutations
|
||||
module Todos
|
||||
class RestoreMany < ::Mutations::Todos::Base
|
||||
class RestoreMany < ::Mutations::BaseMutation
|
||||
graphql_name 'TodoRestoreMany'
|
||||
|
||||
MAX_UPDATE_AMOUNT = 50
|
||||
|
|
|
|||
|
|
@ -46,12 +46,6 @@ module Mutations
|
|||
|
||||
response
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -29,12 +29,6 @@ module Mutations
|
|||
errors: result.errors
|
||||
}
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -53,11 +53,6 @@ module Mutations
|
|||
raise_resource_not_available_error!
|
||||
end
|
||||
end
|
||||
|
||||
# method used by `authorized_find!(id: id)`
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -42,10 +42,6 @@ module Mutations
|
|||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
|
||||
def interpret_quick_actions!(work_item, current_user, widget_params, attributes = {})
|
||||
return unless work_item.work_item_type.widgets.include?(::WorkItems::Widgets::Description)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,19 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Resolvers
|
||||
module DataTransfer
|
||||
module DataTransferArguments
|
||||
extend ActiveSupport::Concern
|
||||
|
||||
included do
|
||||
argument :from, Types::DateType,
|
||||
description:
|
||||
'Retain egress data for one year. Data for the current month will increase dynamically as egress occurs.',
|
||||
required: false
|
||||
argument :to, Types::DateType,
|
||||
description: 'End date for the data.',
|
||||
required: false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Resolvers
|
||||
module DataTransfer
|
||||
class GroupDataTransferResolver < BaseResolver
|
||||
include DataTransferArguments
|
||||
include Gitlab::Graphql::Authorize::AuthorizeResource
|
||||
|
||||
authorizes_object!
|
||||
authorize :read_usage_quotas
|
||||
|
||||
type Types::DataTransfer::GroupDataTransferType, null: false
|
||||
|
||||
alias_method :group, :object
|
||||
|
||||
def resolve(**args)
|
||||
return { egress_nodes: [] } unless Feature.enabled?(:data_transfer_monitoring, group)
|
||||
|
||||
results = if Feature.enabled?(:data_transfer_monitoring_mock_data, group)
|
||||
::DataTransfer::MockedTransferFinder.new.execute
|
||||
else
|
||||
::DataTransfer::GroupDataTransferFinder.new(
|
||||
group: group,
|
||||
from: args[:from],
|
||||
to: args[:to],
|
||||
user: current_user
|
||||
).execute.map(&:attributes)
|
||||
end
|
||||
|
||||
{ egress_nodes: results.to_a }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Resolvers
|
||||
module DataTransfer
|
||||
class ProjectDataTransferResolver < BaseResolver
|
||||
include DataTransferArguments
|
||||
include Gitlab::Graphql::Authorize::AuthorizeResource
|
||||
|
||||
authorizes_object!
|
||||
authorize :read_usage_quotas
|
||||
|
||||
type Types::DataTransfer::ProjectDataTransferType, null: false
|
||||
|
||||
alias_method :project, :object
|
||||
|
||||
def resolve(**args)
|
||||
return { egress_nodes: [] } unless Feature.enabled?(:data_transfer_monitoring, project.group)
|
||||
|
||||
results = if Feature.enabled?(:data_transfer_monitoring_mock_data, project.group)
|
||||
::DataTransfer::MockedTransferFinder.new.execute
|
||||
else
|
||||
::DataTransfer::ProjectDataTransferFinder.new(
|
||||
project: project,
|
||||
from: args[:from],
|
||||
to: args[:to],
|
||||
user: current_user
|
||||
).execute
|
||||
end
|
||||
|
||||
{ egress_nodes: results }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -1,59 +0,0 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module Resolvers
|
||||
class DataTransferResolver < BaseResolver
|
||||
argument :from, Types::DateType,
|
||||
description: 'Retain egress data for 1 year. Current month will increase dynamically as egress occurs.',
|
||||
required: false
|
||||
argument :to, Types::DateType,
|
||||
description: 'End date for the data.',
|
||||
required: false
|
||||
|
||||
type ::Types::DataTransfer::BaseType, null: false
|
||||
|
||||
def self.source
|
||||
raise NotImplementedError
|
||||
end
|
||||
|
||||
def self.project
|
||||
Class.new(self) do
|
||||
type Types::DataTransfer::ProjectDataTransferType, null: false
|
||||
|
||||
def self.source
|
||||
"Project"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def self.group
|
||||
Class.new(self) do
|
||||
type Types::DataTransfer::GroupDataTransferType, null: false
|
||||
|
||||
def self.source
|
||||
"Group"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def resolve(**_args)
|
||||
return unless Feature.enabled?(:data_transfer_monitoring)
|
||||
|
||||
# TODO: This is mock data as this feature is in development
|
||||
# Follow this epic for recent progress: https://gitlab.com/groups/gitlab-org/-/epics/9330
|
||||
start_date = Date.new(2023, 0o1, 0o1)
|
||||
date_for_index = ->(i) { (start_date + i.months).strftime('%Y-%m-%d') }
|
||||
|
||||
nodes = 0.upto(11).map do |i|
|
||||
{
|
||||
date: date_for_index.call(i),
|
||||
repository_egress: rand(70000..550000),
|
||||
artifacts_egress: rand(70000..550000),
|
||||
packages_egress: rand(70000..550000),
|
||||
registry_egress: rand(70000..550000)
|
||||
}
|
||||
end
|
||||
|
||||
{ egress_nodes: nodes }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -16,10 +16,6 @@ module Resolvers
|
|||
def resolve(id:)
|
||||
authorized_find!(id: id)
|
||||
end
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,10 +26,6 @@ module Resolvers
|
|||
|
||||
synthetic_notes.find { |note| note.discussion_id == sha }
|
||||
end
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -13,11 +13,5 @@ module Resolvers
|
|||
def resolve(id:)
|
||||
authorized_find!(id: id)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def find_object(id:)
|
||||
GitlabSchema.find_by_gid(id)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ module Types
|
|||
|
||||
field :egress_nodes, type: Types::DataTransfer::EgressNodeType.connection_type,
|
||||
description: 'Data nodes.',
|
||||
null: true # disallow null once data_transfer_monitoring feature flag is rolled-out!
|
||||
null: true # disallow null once data_transfer_monitoring feature flag is rolled-out! https://gitlab.com/gitlab-org/gitlab/-/issues/397693
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -26,12 +26,8 @@ module Types
|
|||
null: false
|
||||
|
||||
field :registry_egress, GraphQL::Types::BigInt,
|
||||
description: 'Registery egress for that project in that period of time.',
|
||||
description: 'Registry egress for that project in that period of time.',
|
||||
null: false
|
||||
|
||||
def total_egress
|
||||
object.values.select { |x| x.is_a?(Integer) }.sum
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -8,12 +8,14 @@ module Types
|
|||
|
||||
field :total_egress, GraphQL::Types::BigInt,
|
||||
description: 'Total egress for that project in that period of time.',
|
||||
null: true # disallow null once data_transfer_monitoring feature flag is rolled-out!
|
||||
null: true, # disallow null once data_transfer_monitoring feature flag is rolled-out! https://gitlab.com/gitlab-org/gitlab/-/issues/397693
|
||||
extras: [:parent]
|
||||
|
||||
def total_egress(**_)
|
||||
return unless Feature.enabled?(:data_transfer_monitoring)
|
||||
def total_egress(parent:)
|
||||
return unless Feature.enabled?(:data_transfer_monitoring, parent.group)
|
||||
return 40_000_000 if Feature.enabled?(:data_transfer_monitoring_mock_data, parent.group)
|
||||
|
||||
40_000_000
|
||||
object[:egress_nodes].sum('repository_egress + artifacts_egress + packages_egress + registry_egress')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -241,7 +241,7 @@ module Types
|
|||
|
||||
field :data_transfer, Types::DataTransfer::GroupDataTransferType,
|
||||
null: true,
|
||||
resolver: Resolvers::DataTransferResolver.group,
|
||||
resolver: Resolvers::DataTransfer::GroupDataTransferResolver,
|
||||
description: 'Data transfer data point for a specific period. This is mocked data under a development feature flag.'
|
||||
|
||||
def label(title:)
|
||||
|
|
|
|||
|
|
@ -567,8 +567,8 @@ module Types
|
|||
description: "Find runners visible to the current user."
|
||||
|
||||
field :data_transfer, Types::DataTransfer::ProjectDataTransferType,
|
||||
null: true, # disallow null once data_transfer_monitoring feature flag is rolled-out!
|
||||
resolver: Resolvers::DataTransferResolver.project,
|
||||
null: true, # disallow null once data_transfer_monitoring feature flag is rolled-out! https://gitlab.com/gitlab-org/gitlab/-/issues/391682
|
||||
resolver: Resolvers::DataTransfer::ProjectDataTransferResolver,
|
||||
description: 'Data transfer data point for a specific period. This is mocked data under a development feature flag.'
|
||||
|
||||
field :visible_forks, Types::ProjectType.connection_type,
|
||||
|
|
|
|||
|
|
@ -0,0 +1,9 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module AbuseReportsHelper
|
||||
def valid_image_mimetypes
|
||||
Gitlab::FileTypeDetection::SAFE_IMAGE_EXT
|
||||
.map { |extension| "image/#{extension}" }
|
||||
.to_sentence(last_word_connector: ' or ')
|
||||
end
|
||||
end
|
||||
|
|
@ -5,6 +5,7 @@ module Admin
|
|||
def batched_migration_status_badge_variant(migration)
|
||||
variants = {
|
||||
active: :info,
|
||||
finalizing: :info,
|
||||
paused: :warning,
|
||||
failed: :danger,
|
||||
finished: :success
|
||||
|
|
|
|||
|
|
@ -3,8 +3,11 @@
|
|||
class AbuseReport < ApplicationRecord
|
||||
include CacheMarkdownField
|
||||
include Sortable
|
||||
include Gitlab::FileTypeDetection
|
||||
include WithUploads
|
||||
|
||||
MAX_CHAR_LIMIT_URL = 512
|
||||
MAX_FILE_SIZE = 1.megabyte
|
||||
|
||||
cache_markdown_field :message, pipeline: :single_line
|
||||
|
||||
|
|
@ -42,6 +45,10 @@ class AbuseReport < ApplicationRecord
|
|||
before_validation :filter_empty_strings_from_links_to_spam
|
||||
validate :links_to_spam_contains_valid_urls
|
||||
|
||||
mount_uploader :screenshot, AttachmentUploader
|
||||
validates :screenshot, file_size: { maximum: MAX_FILE_SIZE }
|
||||
validate :validate_screenshot_is_image
|
||||
|
||||
scope :by_user_id, ->(id) { where(user_id: id) }
|
||||
scope :by_reporter_id, ->(id) { where(reporter_id: id) }
|
||||
scope :by_category, ->(category) { where(category: category) }
|
||||
|
|
@ -84,6 +91,20 @@ class AbuseReport < ApplicationRecord
|
|||
AbuseReportMailer.notify(id).deliver_later
|
||||
end
|
||||
|
||||
def screenshot_path
|
||||
return unless screenshot
|
||||
return screenshot.url unless screenshot.upload
|
||||
|
||||
asset_host = ActionController::Base.asset_host || Gitlab.config.gitlab.base_url
|
||||
local_path = Gitlab::Routing.url_helpers.abuse_report_upload_path(
|
||||
filename: screenshot.filename,
|
||||
id: screenshot.upload.model_id,
|
||||
model: 'abuse_report',
|
||||
mounted_as: 'screenshot')
|
||||
|
||||
Gitlab::Utils.append_path(asset_host, local_path)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def filter_empty_strings_from_links_to_spam
|
||||
|
|
@ -113,4 +134,24 @@ class AbuseReport < ApplicationRecord
|
|||
rescue ::Gitlab::UrlBlocker::BlockedUrlError
|
||||
errors.add(:links_to_spam, _('only supports valid HTTP(S) URLs'))
|
||||
end
|
||||
|
||||
def filename
|
||||
screenshot&.filename
|
||||
end
|
||||
|
||||
def valid_image_extensions
|
||||
Gitlab::FileTypeDetection::SAFE_IMAGE_EXT
|
||||
end
|
||||
|
||||
def validate_screenshot_is_image
|
||||
return if screenshot.blank?
|
||||
return if image?
|
||||
|
||||
errors.add(
|
||||
:screenshot,
|
||||
format(
|
||||
_('must match one of the following file types: %{extension_list}'),
|
||||
extension_list: valid_image_extensions.to_sentence(last_word_connector: ' or '))
|
||||
)
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ class PagesDeployment < ApplicationRecord
|
|||
end
|
||||
|
||||
def store_after_commit?
|
||||
Feature.enabled?(:pages_deploy_upload_file_outside_transaction)
|
||||
Feature.enabled?(:pages_deploy_upload_file_outside_transaction, project)
|
||||
end
|
||||
strong_memoize_attr :store_after_commit?
|
||||
|
||||
|
|
|
|||
|
|
@ -13,6 +13,14 @@ module Projects
|
|||
belongs_to :namespace
|
||||
|
||||
scope :current_month, -> { where(date: beginning_of_month) }
|
||||
scope :with_project_between_dates, ->(project, from, to) {
|
||||
where(project: project, date: from..to)
|
||||
}
|
||||
scope :with_namespace_between_dates, ->(namespace, from, to) {
|
||||
where(namespace: namespace, date: from..to)
|
||||
.group(:date, :namespace_id)
|
||||
.order(date: :desc)
|
||||
}
|
||||
|
||||
counter_attribute :repository_egress, returns_current: true
|
||||
counter_attribute :artifacts_egress, returns_current: true
|
||||
|
|
|
|||
|
|
@ -26,6 +26,17 @@
|
|||
= f.label :reported_from
|
||||
= f.text_field :reported_from_url, class: "form-control", readonly: true
|
||||
#js-links-to-spam{ data: { links: Array(@abuse_report.links_to_spam) } }
|
||||
|
||||
.form-group.row
|
||||
.col-lg-8
|
||||
= f.label :screenshot do
|
||||
%span
|
||||
= s_('ReportAbuse|Screenshot')
|
||||
.gl-font-weight-normal
|
||||
= s_('ReportAbuse|Screenshot of abuse')
|
||||
%div
|
||||
= render 'shared/file_picker_button', f: f, field: :screenshot, help_text: _("Screenshot must be less than 1 MB."), mime_types: valid_image_mimetypes
|
||||
|
||||
.form-group.row
|
||||
.col-lg-8
|
||||
= f.label :reason
|
||||
|
|
|
|||
|
|
@ -17,6 +17,9 @@
|
|||
= gl_tab_link_to admin_background_migrations_path({ tab: nil, database: params[:database] }), item_active: @current_tab == 'queued' do
|
||||
= _('Queued')
|
||||
= gl_tab_counter_badge limited_counter_with_delimiter(@relations_by_tab['queued'])
|
||||
= gl_tab_link_to admin_background_migrations_path({ tab: 'finalizing', database: params[:database] }), item_active: @current_tab == 'finalizing' do
|
||||
= _('Finalizing')
|
||||
= gl_tab_counter_badge limited_counter_with_delimiter(@relations_by_tab['finalizing'])
|
||||
= gl_tab_link_to admin_background_migrations_path({ tab: 'failed', database: params[:database] }), item_active: @current_tab == 'failed' do
|
||||
= _('Failed')
|
||||
= gl_tab_counter_badge limited_counter_with_delimiter(@relations_by_tab['failed'])
|
||||
|
|
|
|||
|
|
@ -1,9 +1,10 @@
|
|||
- classes = local_assigns.fetch(:classes, '')
|
||||
- mime_types = local_assigns.fetch(:mime_types, '')
|
||||
|
||||
%span.js-filepicker
|
||||
= render Pajamas::ButtonComponent.new(button_options: { class: "js-filepicker-button #{classes}" }) do
|
||||
= _("Choose file…")
|
||||
%span.file_name.js-filepicker-filename= _("No file chosen.")
|
||||
= f.file_field field, class: "js-filepicker-input hidden"
|
||||
%span.file_name.gl-ml-3.js-filepicker-filename= _("No file chosen.")
|
||||
= f.file_field field, class: "js-filepicker-input hidden", accept: mime_types
|
||||
- if help_text.present?
|
||||
.form-text.text-muted= help_text
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
- docs_link_url = help_page_path('user/project/integrations/webhooks', anchor: 'troubleshoot-webhooks')
|
||||
- docs_link_url = help_page_path('user/project/integrations/webhooks', anchor: 'troubleshooting')
|
||||
- link_start = '<a href="%{url}" target="_blank" rel="noopener noreferrer">'.html_safe % { url: docs_link_url }
|
||||
- link_end = '</a>'.html_safe
|
||||
|
||||
|
|
|
|||
|
|
@ -8,6 +8,6 @@
|
|||
= c.body do
|
||||
= s_('Webhooks|A webhook in this project was automatically disabled after being retried multiple times.')
|
||||
= succeed '.' do
|
||||
= link_to _('Learn more'), help_page_path('user/project/integrations/webhooks', anchor: 'troubleshoot-webhooks'), target: '_blank', rel: 'noopener noreferrer'
|
||||
= link_to _('Learn more'), help_page_path('user/project/integrations/webhooks', anchor: 'troubleshooting'), target: '_blank', rel: 'noopener noreferrer'
|
||||
= c.actions do
|
||||
= link_to s_('Webhooks|Go to webhooks'), project_hooks_path(@project, anchor: 'webhooks-index'), class: 'btn gl-alert-action btn-confirm gl-button'
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
---
|
||||
name: codeowners_default_owners
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/113594
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/394811
|
||||
name: data_transfer_monitoring_mock_data
|
||||
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/113392
|
||||
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/397693
|
||||
milestone: '15.11'
|
||||
type: development
|
||||
group: group::source code
|
||||
|
|
@ -43,6 +43,7 @@ options:
|
|||
- g_analytics_ci_cd_lead_time
|
||||
- g_analytics_ci_cd_time_to_restore_service
|
||||
- g_analytics_ci_cd_change_failure_rate
|
||||
- g_metrics_comparison_page
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@ options:
|
|||
- p_analytics_ci_cd_pipelines
|
||||
- p_analytics_ci_cd_deployment_frequency
|
||||
- p_analytics_ci_cd_lead_time
|
||||
- g_metrics_comparison_page
|
||||
distribution:
|
||||
- ce
|
||||
- ee
|
||||
|
|
|
|||
|
|
@ -37,6 +37,12 @@ scope path: :uploads do
|
|||
to: "uploads#show",
|
||||
constraints: { model: /alert_management_metric_image/, mounted_as: /file/, filename: %r{[^/]+} },
|
||||
as: 'alert_metric_image_upload'
|
||||
|
||||
# Abuse Reports Images
|
||||
get "-/system/:model/:mounted_as/:id/:filename",
|
||||
to: "uploads#show",
|
||||
constraints: { model: /abuse_report/, mounted_as: /screenshot/, filename: %r{[^/]+} },
|
||||
as: 'abuse_report_upload'
|
||||
end
|
||||
|
||||
# Redirect old note attachments path to new uploads path.
|
||||
|
|
|
|||
|
|
@ -7,6 +7,6 @@
|
|||
issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/387299 # (required) Link to the deprecation issue in GitLab
|
||||
body: | # (required) Do not modify this line, instead modify the lines below.
|
||||
Cookie authentication in the GitLab for Jira Cloud app is now deprecated in favor of OAuth authentication.
|
||||
You must [set up OAuth authentication](https://docs.gitlab.com/ee/integration/jira/connect-app.html#set-up-oauth-authentication)
|
||||
to continue to use the GitLab for Jira Cloud app. Without OAuth, you will not be able to manage linked namespaces.
|
||||
On self-managed, you must [set up OAuth authentication](https://docs.gitlab.com/ee/integration/jira/connect-app.html#set-up-oauth-authentication-for-self-managed-instances)
|
||||
to continue to use the GitLab for Jira Cloud app. Without OAuth, you can't manage linked namespaces.
|
||||
tiers: [Core, Premium, Ultimate] # (optional - may be required in the future) An array of tiers that the feature is available in currently. e.g., [Free, Silver, Gold, Core, Premium, Ultimate]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,10 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddScreenshotToAbuseReports < Gitlab::Database::Migration[2.1]
|
||||
# rubocop:disable Migration/AddLimitToTextColumns
|
||||
# limit is added in 20230327074932_add_text_limit_to_abuse_reports_screenshot
|
||||
def change
|
||||
add_column :abuse_reports, :screenshot, :text
|
||||
end
|
||||
# rubocop:enable Migration/AddLimitToTextColumns
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddProjectAccessTokenLimitToPlanLimits < Gitlab::Database::Migration[2.1]
|
||||
def change
|
||||
add_column(:plan_limits, :project_access_token_limit, :integer, default: 0, null: false)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class InsertProjectAccessTokenLimit < Gitlab::Database::Migration[2.1]
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
def up
|
||||
create_or_update_plan_limit('project_access_token_limit', 'premium_trial', 1)
|
||||
create_or_update_plan_limit('project_access_token_limit', 'ultimate_trial', 1)
|
||||
end
|
||||
|
||||
def down
|
||||
create_or_update_plan_limit('project_access_token_limit', 'premium_trial', 0)
|
||||
create_or_update_plan_limit('project_access_token_limit', 'ultimate_trial', 0)
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,26 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RerunRemoveInvalidDeployAccessLevel < Gitlab::Database::Migration[2.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
# clean up any rows with invalid access_level entries
|
||||
def up
|
||||
update_column_in_batches(:protected_environment_deploy_access_levels, :access_level, nil) do |table, query|
|
||||
query.where(
|
||||
table.grouping(table[:user_id].not_eq(nil).or(table[:group_id].not_eq(nil)))
|
||||
.and(table[:access_level].not_eq(nil)))
|
||||
end
|
||||
|
||||
update_column_in_batches(:protected_environment_deploy_access_levels, :group_id, nil) do |table, query|
|
||||
query.where(table[:user_id].not_eq(nil).and(table[:group_id].not_eq(nil)))
|
||||
end
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
|
||||
# we are setting access_level to NULL if group_id or user_id are present
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class AddTextLimitToAbuseReportsScreenshot < Gitlab::Database::Migration[2.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
add_text_limit :abuse_reports, :screenshot, 255
|
||||
end
|
||||
|
||||
def down
|
||||
remove_text_limit :abuse_reports, :screenshot
|
||||
end
|
||||
end
|
||||
|
|
@ -3,20 +3,11 @@
|
|||
class RemoveInvalidDeployAccessLevel < Gitlab::Database::Migration[2.1]
|
||||
disable_ddl_transaction!
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
|
||||
# clean up any rows with invalid access_level entries
|
||||
def up
|
||||
update_column_in_batches(:protected_environment_deploy_access_levels, :access_level, nil) do |table, query|
|
||||
query.where(
|
||||
table.grouping(table[:user_id].not_eq(nil).or(table[:group_id].not_eq(nil)))
|
||||
.and(table[:access_level].not_eq(nil)))
|
||||
end
|
||||
# no-op, moved to 20230322151605_rerun_remove_invalid_deploy_access_level.rb
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
|
||||
# we are setting access_level to NULL if group_id or user_id are present
|
||||
end
|
||||
end
|
||||
|
|
|
|||
|
|
@ -0,0 +1,29 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class EnsureCommitUserMentionsNoteIdBigintBackfillIsFinishedForGitlabDotCom < Gitlab::Database::Migration[2.1]
|
||||
include Gitlab::Database::MigrationHelpers::ConvertToBigint
|
||||
|
||||
restrict_gitlab_migration gitlab_schema: :gitlab_main
|
||||
disable_ddl_transaction!
|
||||
|
||||
def up
|
||||
return unless should_run?
|
||||
|
||||
ensure_batched_background_migration_is_finished(
|
||||
job_class_name: 'CopyColumnUsingBackgroundMigrationJob',
|
||||
table_name: 'commit_user_mentions',
|
||||
column_name: 'id',
|
||||
job_arguments: [['note_id'], ['note_id_convert_to_bigint']]
|
||||
)
|
||||
end
|
||||
|
||||
def down
|
||||
# no-op
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def should_run?
|
||||
com_or_dev_or_test_but_not_jh?
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class RemoveMemberRoleDownloadCode < Gitlab::Database::Migration[2.1]
|
||||
def change
|
||||
remove_column :member_roles, :download_code, :boolean, default: false
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1,68 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
class SwapCommitUserMentionsNoteIdToBigintForGitlabDotCom < Gitlab::Database::Migration[2.1]
|
||||
include Gitlab::Database::MigrationHelpers::ConvertToBigint
|
||||
|
||||
disable_ddl_transaction!
|
||||
|
||||
TABLE_NAME = 'commit_user_mentions'
|
||||
|
||||
def up
|
||||
return unless should_run?
|
||||
|
||||
swap
|
||||
end
|
||||
|
||||
def down
|
||||
return unless should_run?
|
||||
|
||||
swap
|
||||
end
|
||||
|
||||
def swap
|
||||
# This will replace the existing commit_user_mentions_on_commit_id_and_note_id_unique_index
|
||||
add_concurrent_index TABLE_NAME, [:commit_id, :note_id_convert_to_bigint], unique: true,
|
||||
name: 'commit_user_mentions_on_commit_id_and_note_id_convert_to_bigint'
|
||||
|
||||
# This will replace the existing index_commit_user_mentions_on_note_id
|
||||
add_concurrent_index TABLE_NAME, :note_id_convert_to_bigint, unique: true,
|
||||
name: 'index_commit_user_mentions_on_note_id_convert_to_bigint'
|
||||
|
||||
# This will replace the existing fk_rails_a6760813e0
|
||||
add_concurrent_foreign_key TABLE_NAME, :notes, column: :note_id_convert_to_bigint,
|
||||
name: 'fk_commit_user_mentions_note_id_convert_to_bigint',
|
||||
on_delete: :cascade
|
||||
|
||||
with_lock_retries(raise_on_exhaustion: true) do
|
||||
execute "LOCK TABLE notes, #{TABLE_NAME} IN ACCESS EXCLUSIVE MODE"
|
||||
|
||||
execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN note_id TO note_id_tmp"
|
||||
execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN note_id_convert_to_bigint TO note_id"
|
||||
execute "ALTER TABLE #{TABLE_NAME} RENAME COLUMN note_id_tmp TO note_id_convert_to_bigint"
|
||||
|
||||
function_name = Gitlab::Database::UnidirectionalCopyTrigger
|
||||
.on_table(TABLE_NAME, connection: connection)
|
||||
.name(:note_id, :note_id_convert_to_bigint)
|
||||
execute "ALTER FUNCTION #{quote_table_name(function_name)} RESET ALL"
|
||||
|
||||
# Swap defaults
|
||||
change_column_default TABLE_NAME, :note_id, nil
|
||||
change_column_default TABLE_NAME, :note_id_convert_to_bigint, 0
|
||||
|
||||
execute 'DROP INDEX IF EXISTS commit_user_mentions_on_commit_id_and_note_id_unique_index'
|
||||
rename_index TABLE_NAME, 'commit_user_mentions_on_commit_id_and_note_id_convert_to_bigint',
|
||||
'commit_user_mentions_on_commit_id_and_note_id_unique_index'
|
||||
|
||||
execute 'DROP INDEX IF EXISTS index_commit_user_mentions_on_note_id'
|
||||
rename_index TABLE_NAME, 'index_commit_user_mentions_on_note_id_convert_to_bigint',
|
||||
'index_commit_user_mentions_on_note_id'
|
||||
|
||||
execute "ALTER TABLE #{TABLE_NAME} DROP CONSTRAINT IF EXISTS fk_rails_a6760813e0"
|
||||
rename_constraint(TABLE_NAME, 'fk_commit_user_mentions_note_id_convert_to_bigint', 'fk_rails_a6760813e0')
|
||||
end
|
||||
end
|
||||
|
||||
def should_run?
|
||||
com_or_dev_or_test_but_not_jh?
|
||||
end
|
||||
end
|
||||
|
|
@ -0,0 +1 @@
|
|||
86ffe1f3b8048cf01b96f66683fa68f889051c8633c6b803ffdb03aa0a8d2864
|
||||
|
|
@ -0,0 +1 @@
|
|||
aedea3dd398210eb2d98a3ecefe3b02b518bce53d63d75160796eb0414574087
|
||||
|
|
@ -0,0 +1 @@
|
|||
198cf0597e4a513c6c47b9cd576765d40f564838d5c54e33216fd7a5d25220ae
|
||||
|
|
@ -0,0 +1 @@
|
|||
82c5c661c3fad14a0466e5669b59dca92084b8c77500d8ae3b97b34029277c94
|
||||
|
|
@ -0,0 +1 @@
|
|||
efbe3f66fecfb275f8b4276cedc2210a141f4c63cc10242daafb445b352a4b70
|
||||
|
|
@ -0,0 +1 @@
|
|||
7e3a9281e624341301d937d2422f0ff2d71367bfb42bf45ddcde7216e84ecb93
|
||||
|
|
@ -0,0 +1 @@
|
|||
5300b4b70078fe3dadbdf42e7884dee84794c0de5b32c26b6ec46622b2a433c4
|
||||
|
|
@ -0,0 +1 @@
|
|||
48f6ba4288122f400a0a2ef53a679cf6b4e9dc3052ec64e959066f6e30b3cd3a
|
||||
|
|
@ -10745,7 +10745,9 @@ CREATE TABLE abuse_reports (
|
|||
links_to_spam text[] DEFAULT '{}'::text[] NOT NULL,
|
||||
status smallint DEFAULT 1 NOT NULL,
|
||||
resolved_at timestamp with time zone,
|
||||
screenshot text,
|
||||
CONSTRAINT abuse_reports_links_to_spam_length_check CHECK ((cardinality(links_to_spam) <= 20)),
|
||||
CONSTRAINT check_4b0a5120e0 CHECK ((char_length(screenshot) <= 255)),
|
||||
CONSTRAINT check_ab1260fa6c CHECK ((char_length(reported_from_url) <= 512))
|
||||
);
|
||||
|
||||
|
|
@ -14462,12 +14464,12 @@ ALTER SEQUENCE clusters_kubernetes_namespaces_id_seq OWNED BY clusters_kubernete
|
|||
|
||||
CREATE TABLE commit_user_mentions (
|
||||
id bigint NOT NULL,
|
||||
note_id integer NOT NULL,
|
||||
note_id_convert_to_bigint integer DEFAULT 0 NOT NULL,
|
||||
mentioned_users_ids integer[],
|
||||
mentioned_projects_ids integer[],
|
||||
mentioned_groups_ids integer[],
|
||||
commit_id character varying NOT NULL,
|
||||
note_id_convert_to_bigint bigint DEFAULT 0 NOT NULL
|
||||
note_id bigint NOT NULL
|
||||
);
|
||||
|
||||
CREATE SEQUENCE commit_user_mentions_id_seq
|
||||
|
|
@ -17824,7 +17826,6 @@ CREATE TABLE member_roles (
|
|||
created_at timestamp with time zone NOT NULL,
|
||||
updated_at timestamp with time zone NOT NULL,
|
||||
base_access_level integer NOT NULL,
|
||||
download_code boolean DEFAULT false,
|
||||
read_code boolean DEFAULT false
|
||||
);
|
||||
|
||||
|
|
@ -19987,7 +19988,8 @@ CREATE TABLE plan_limits (
|
|||
enforcement_limit integer DEFAULT 0 NOT NULL,
|
||||
notification_limit integer DEFAULT 0 NOT NULL,
|
||||
dashboard_limit_enabled_at timestamp with time zone,
|
||||
web_hook_calls integer DEFAULT 0 NOT NULL
|
||||
web_hook_calls integer DEFAULT 0 NOT NULL,
|
||||
project_access_token_limit integer DEFAULT 0 NOT NULL
|
||||
);
|
||||
|
||||
CREATE SEQUENCE plan_limits_id_seq
|
||||
|
|
|
|||
|
|
@ -27,7 +27,43 @@ alternatives to server hooks include:
|
|||
|
||||
[Geo](geo/index.md) doesn't replicate server hooks to secondary nodes.
|
||||
|
||||
## Create server hooks for a repository
|
||||
## Set server hooks for a repository
|
||||
|
||||
::Tabs
|
||||
|
||||
:::TabTitle GitLab 15.11 and later
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/4629) in GitLab 15.11, `hooks set` command replaces direct file system access.
|
||||
|
||||
Prerequisites:
|
||||
|
||||
- The [storage name and relative path](repository_storage_types.md#from-project-name-to-hashed-path) for the repository.
|
||||
|
||||
To set server hooks for a repository:
|
||||
|
||||
1. Create tarball containing custom hooks:
|
||||
1. Write the code to make the server hook function as expected. Git server hooks can be in any programming language.
|
||||
Ensure the [shebang](https://en.wikipedia.org/wiki/Shebang_(Unix)) at the top reflects the language type. For
|
||||
example, if the script is in Ruby the shebang is probably `#!/usr/bin/env ruby`.
|
||||
|
||||
- To create a single server hook, create a file with a name that matches the hook type. For example, for a
|
||||
`pre-receive` server hook, the filename should be `pre-receive` with no extension.
|
||||
- To create many server hooks, create a directory for the hooks that matches the hook type. For example, for a
|
||||
`pre-receive` server hook, the directory name should be `pre-receive.d`. Put the files for the hook in that
|
||||
directory.
|
||||
|
||||
1. Ensure the server hook files are executable and do not match the backup file pattern (`*~`). The server hooks be
|
||||
in a `custom_hooks` directory that is at the root of the tarball.
|
||||
1. Create the custom hooks archive with the tar command. For example, `tar -cf custom_hooks.tar custom_hooks`.
|
||||
1. Run the `hooks set` command with required options to set the Git hooks for the repository. For example,
|
||||
`cat hooks.tar | gitaly hooks set --storage <storage> --repository <relative path> --config <config path>`.
|
||||
|
||||
- A path to a valid Gitaly configuration for the node is required to connect to the node and provided to the `--config` flag.
|
||||
- Custom hooks tarball must be passed via `stdin`. For example, `cat hooks.tar | gitaly hooks set --storage <storage> --repository <relative path> --config <config path>`.
|
||||
|
||||
If you implemented the server hook code correctly, it should execute when the Git hook is next triggered.
|
||||
|
||||
:::TabTitle GitLab 15.10 and earlier
|
||||
|
||||
To create server hooks for a repository:
|
||||
|
||||
|
|
@ -55,6 +91,8 @@ To create server hooks for a repository:
|
|||
|
||||
If the server hook code is properly implemented, it should execute when the Git hook is next triggered.
|
||||
|
||||
::EndTabs
|
||||
|
||||
### Gitaly Cluster
|
||||
|
||||
If you use [Gitaly Cluster](gitaly/index.md), the scripts must be copied to every Gitaly node that has a replica of the repository. Every Gitaly node
|
||||
|
|
@ -112,6 +150,16 @@ To create a global server hook for all repositories:
|
|||
If the server hook code is properly implemented, it should execute when the Git hook is next triggered. Hooks are executed in alphabetical order by filename in the hook type
|
||||
subdirectories.
|
||||
|
||||
## Remove server hooks for a repository using Gitaly CLI
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitaly/-/issues/4629) in GitLab 15.11, `hooks set` command replaces direct file system access.
|
||||
|
||||
To remove hooks using the Gitaly CLI, pass an empty tarball to `hook set` to indicate that the repository should contain no hooks. For example:
|
||||
|
||||
```shell
|
||||
cat empty_hooks.tar | gitaly hooks set --storage <storage> --repository <relative path> --config <config path>`.
|
||||
```
|
||||
|
||||
## Chained server hooks
|
||||
|
||||
GitLab can execute server hooks in a chain. GitLab searches for and executes server hooks in the following order:
|
||||
|
|
|
|||
|
|
@ -13355,7 +13355,7 @@ Returns [`[DoraMetric!]`](#dorametric).
|
|||
| <a id="egressnodeartifactsegress"></a>`artifactsEgress` | [`BigInt!`](#bigint) | Artifacts egress for that project in that period of time. |
|
||||
| <a id="egressnodedate"></a>`date` | [`String!`](#string) | First day of the node range. There is one node per month. |
|
||||
| <a id="egressnodepackagesegress"></a>`packagesEgress` | [`BigInt!`](#bigint) | Packages egress for that project in that period of time. |
|
||||
| <a id="egressnoderegistryegress"></a>`registryEgress` | [`BigInt!`](#bigint) | Registery egress for that project in that period of time. |
|
||||
| <a id="egressnoderegistryegress"></a>`registryEgress` | [`BigInt!`](#bigint) | Registry egress for that project in that period of time. |
|
||||
| <a id="egressnoderepositoryegress"></a>`repositoryEgress` | [`BigInt!`](#bigint) | Repository egress for that project in that period of time. |
|
||||
| <a id="egressnodetotalegress"></a>`totalEgress` | [`BigInt!`](#bigint) | Total egress for that project in that period of time. |
|
||||
|
||||
|
|
@ -14574,7 +14574,7 @@ Returns [`GroupDataTransfer`](#groupdatatransfer).
|
|||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="groupdatatransferfrom"></a>`from` | [`Date`](#date) | Retain egress data for 1 year. Current month will increase dynamically as egress occurs. |
|
||||
| <a id="groupdatatransferfrom"></a>`from` | [`Date`](#date) | Retain egress data for one year. Data for the current month will increase dynamically as egress occurs. |
|
||||
| <a id="groupdatatransferto"></a>`to` | [`Date`](#date) | End date for the data. |
|
||||
|
||||
##### `Group.descendantGroups`
|
||||
|
|
@ -18604,7 +18604,7 @@ Returns [`ProjectDataTransfer`](#projectdatatransfer).
|
|||
|
||||
| Name | Type | Description |
|
||||
| ---- | ---- | ----------- |
|
||||
| <a id="projectdatatransferfrom"></a>`from` | [`Date`](#date) | Retain egress data for 1 year. Current month will increase dynamically as egress occurs. |
|
||||
| <a id="projectdatatransferfrom"></a>`from` | [`Date`](#date) | Retain egress data for one year. Data for the current month will increase dynamically as egress occurs. |
|
||||
| <a id="projectdatatransferto"></a>`to` | [`Date`](#date) | End date for the data. |
|
||||
|
||||
##### `Project.deployment`
|
||||
|
|
|
|||
|
|
@ -39,31 +39,38 @@ several releases. Due to the limitations of partitioning and the related
|
|||
migrations, you should understand how partitioning fits your use case
|
||||
before attempting to leverage this feature.
|
||||
|
||||
## Determining when to use partitioning
|
||||
## Determine when to use partitioning
|
||||
|
||||
While partitioning can be very useful when properly applied, it's
|
||||
imperative to identify if the data and workload of a table naturally fit a
|
||||
partitioning scheme. There are a few details you have to understand
|
||||
to decide if partitioning is a good fit for your particular
|
||||
problem.
|
||||
partitioning scheme. Understand a few details to decide if partitioning
|
||||
is a good fit for your particular problem:
|
||||
|
||||
First, a table is partitioned on a partition key, which is a column or
|
||||
set of columns which determine how the data is split across the
|
||||
partitions. The partition key is used by the database when reading or
|
||||
writing data, to decide which partitions must be accessed. The
|
||||
partition key should be a column that would be included in a `WHERE`
|
||||
clause on almost all queries accessing that table.
|
||||
- **Table partitioning**. A table is partitioned on a partition key, which is a
|
||||
column or set of columns which determine how the data is split across the
|
||||
partitions. The partition key is used by the database when reading or
|
||||
writing data, to decide which partitions must be accessed. The
|
||||
partition key should be a column that would be included in a `WHERE`
|
||||
clause on almost all queries accessing that table.
|
||||
|
||||
Second, it's necessary to understand the strategy the database uses
|
||||
to split the data across the partitions. The scheme supported by the
|
||||
GitLab migration helpers is date-range partitioning, where each partition
|
||||
in the table contains data for a single month. In this case, the partitioning
|
||||
key must be a timestamp or date column. In order for this type of
|
||||
- **How the data is split**. What strategy does the database use
|
||||
to split the data across the partitions? The available choices are `range`,
|
||||
`hash`, and `list`.
|
||||
|
||||
## Determine the appropriate partitioning strategy
|
||||
|
||||
The available partitioning strategy choices are `range`, `hash`, and `list`.
|
||||
|
||||
### Range partitioning
|
||||
|
||||
The scheme best supported by the GitLab migration helpers is date-range partitioning,
|
||||
where each partition in the table contains data for a single month. In this case,
|
||||
the partitioning key must be a timestamp or date column. For this type of
|
||||
partitioning to work well, most queries must access data in a
|
||||
certain date range.
|
||||
|
||||
For a more concrete example, the `audit_events` table can be used, which
|
||||
was the first table to be partitioned in the application database
|
||||
For a more concrete example, consider using the `audit_events` table.
|
||||
It was the first table to be partitioned in the application database
|
||||
(scheduled for deployment with the GitLab 13.5 release). This
|
||||
table tracks audit entries of security events that happen in the
|
||||
application. In almost all cases, users want to see audit activity that
|
||||
|
|
@ -149,6 +156,31 @@ substantial. Partitioning should only be leveraged if the access patterns
|
|||
of the data support the partitioning strategy, otherwise performance
|
||||
suffers.
|
||||
|
||||
### Hash Partitioning
|
||||
|
||||
Hash partitioning splits a logical table into a series of partitioned
|
||||
tables. Each partition corresponds to the ID range that matches
|
||||
a hash and remainder. For example, if partitioning `BY HASH(id)`, rows
|
||||
with `hash(id) % 64 == 1` would end up in the partition
|
||||
`WITH (MODULUS 64, REMAINDER 1)`.
|
||||
|
||||
When hash partitioning, you must include a `WHERE hashed_column = ?` condition in
|
||||
every performance-sensitive query issued by the application. If this is not possible,
|
||||
hash partitioning may not be the correct fit for your use case.
|
||||
|
||||
Hash partitioning has one main advantage: it is the only type of partitioning that
|
||||
can enforce uniqueness on a single numeric `id` column. (While also possible with
|
||||
range partitioning, it's rarely the correct choice).
|
||||
|
||||
Hash partitioning has downsides:
|
||||
|
||||
- The number of partitions must be known up-front.
|
||||
- It's difficult to move new data to an extra partition if current partitions become too large.
|
||||
- Range queries, such as `WHERE id BETWEEN ? and ?`, are unsupported.
|
||||
- Lookups by other keys, such as `WHERE other_id = ?`, are unsupported.
|
||||
|
||||
For this reason, it's often best to choose a large number of hash partitions to accommodate future table growth.
|
||||
|
||||
## Partitioning a table (Range)
|
||||
|
||||
Unfortunately, tables can only be partitioned at their creation, making
|
||||
|
|
@ -264,6 +296,18 @@ for use by the application. This section will be updated when the
|
|||
migration helper is ready, for now development can be followed in the
|
||||
[Tracking Issue](https://gitlab.com/gitlab-org/gitlab/-/issues/241267).
|
||||
|
||||
## Partitioning a table (Hash)
|
||||
|
||||
Hash partitioning divides data into partitions based on a hash of their ID.
|
||||
It works well only if most queries against the table include a clause like `WHERE id = ?`,
|
||||
so that PostgreSQL can decide which partition to look in based on the ID or ids being requested.
|
||||
|
||||
Another key downside is that hash partitioning does not allow adding additional partitions after table creation.
|
||||
The correct number of partitions must be chosen up-front.
|
||||
|
||||
Hash partitioning is the only type of partitioning (aside from some complex uses of list partitioning) that can guarantee
|
||||
uniqueness of an ID across multiple partitions at the database level.
|
||||
|
||||
## Partitioning a table (List)
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/96815) in GitLab 15.4.
|
||||
|
|
|
|||
|
|
@ -190,26 +190,21 @@ This issue can occur when the request exceeds the
|
|||
[webhook timeout](../user/project/integrations/webhooks.md#webhook-fails-or-multiple-webhook-requests-are-triggered),
|
||||
which is set to 10 seconds by default.
|
||||
|
||||
Check the [service hook logs](../user/project/integrations/index.md#troubleshooting-integrations)
|
||||
for request failures or check the `/var/log/gitlab/gitlab-rails/production.log`
|
||||
file for messages like:
|
||||
For this issue, check:
|
||||
|
||||
```plaintext
|
||||
WebHook Error => Net::ReadTimeout
|
||||
```
|
||||
- [Integration webhook logs](../user/project/integrations/index.md#troubleshooting)
|
||||
for request failures.
|
||||
- `/var/log/gitlab/gitlab-rails/production.log` for messages like:
|
||||
|
||||
or
|
||||
```plaintext
|
||||
WebHook Error => Net::ReadTimeout
|
||||
```
|
||||
|
||||
```plaintext
|
||||
WebHook Error => execution expired
|
||||
```
|
||||
or
|
||||
|
||||
Or check for duplicate messages in `/var/log/gitlab/gitlab-rail`, like:
|
||||
|
||||
```plaintext
|
||||
2019-10-25_04:22:41.25630 2019-10-25T04:22:41.256Z 1584 TID-ovowh4tek WebHookWorker JID-941fb7f40b69dff3d833c99b INFO: start
|
||||
2019-10-25_04:22:41.25630 2019-10-25T04:22:41.256Z 1584 TID-ovowh4tek WebHookWorker JID-941fb7f40b69dff3d833c99b INFO: start
|
||||
```
|
||||
```plaintext
|
||||
WebHook Error => execution expired
|
||||
```
|
||||
|
||||
On self-managed GitLab instances, you can fix this issue by [increasing the webhook timeout value](../administration/instance_limits.md#webhook-timeout).
|
||||
|
||||
|
|
|
|||
|
|
@ -6,9 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# GitLab for Jira Cloud app **(FREE)**
|
||||
|
||||
You can integrate GitLab and Jira Cloud using the
|
||||
[GitLab for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud)
|
||||
app in the Atlassian Marketplace.
|
||||
With the [GitLab for Jira Cloud](https://marketplace.atlassian.com/apps/1221011/gitlab-com-for-jira-cloud) app,
|
||||
you can integrate GitLab and Jira Cloud.
|
||||
|
||||
Only Jira users with administrator access can install or configure
|
||||
the GitLab for Jira Cloud app.
|
||||
|
|
@ -18,7 +17,7 @@ the GitLab for Jira Cloud app.
|
|||
If you use GitLab.com and Jira Cloud, you can install the GitLab for Jira Cloud app.
|
||||
If you do not use both of these environments, use the [Jira DVCS Connector](dvcs/index.md) or
|
||||
[install the GitLab for Jira Cloud app manually](#install-the-gitlab-for-jira-cloud-app-manually).
|
||||
We recommend the GitLab for Jira Cloud app, because data is
|
||||
You should use the GitLab for Jira Cloud app because data is
|
||||
synchronized in real time. The DVCS connector updates data only once per hour.
|
||||
|
||||
To configure the GitLab for Jira Cloud app, you must have
|
||||
|
|
@ -61,9 +60,9 @@ After a namespace is added:
|
|||
|
||||
- All future commits, branches, and merge requests of all projects under that namespace
|
||||
are synced to Jira.
|
||||
- From GitLab 13.8, past merge request data is synced to Jira.
|
||||
- In GitLab 13.8 and later, past merge request data is synced to Jira.
|
||||
|
||||
Support for syncing past branch and commit data is tracked [in this issue](https://gitlab.com/gitlab-org/gitlab/-/issues/263240).
|
||||
For more information about syncing past branch and commit data, see [issue 263240](https://gitlab.com/gitlab-org/gitlab/-/issues/263240).
|
||||
|
||||
## Update the GitLab for Jira Cloud app
|
||||
|
||||
|
|
@ -73,15 +72,15 @@ for details.
|
|||
|
||||
If the app requires additional permissions, [the update must first be manually approved in Jira](https://developer.atlassian.com/platform/marketplace/upgrading-and-versioning-cloud-apps/#changes-that-require-manual-customer-approval).
|
||||
|
||||
## Set up OAuth authentication
|
||||
## Set up OAuth authentication for self-managed instances **(FREE SELF)**
|
||||
|
||||
The GitLab for Jira Cloud app is [switching to OAuth authentication](https://gitlab.com/gitlab-org/gitlab/-/issues/387299).
|
||||
To enable OAuth authentication, you must create an OAuth application on the GitLab instance.
|
||||
|
||||
Enabling OAuth authentication is:
|
||||
You must enable OAuth authentication to:
|
||||
|
||||
- Required to [connect the GitLab for Jira Cloud app for self-managed instances](#connect-the-gitlab-for-jira-cloud-app-for-self-managed-instances).
|
||||
- Recommended to [install the GitLab for Jira Cloud app manually](#install-the-gitlab-for-jira-cloud-app-manually).
|
||||
- [Connect the GitLab for Jira Cloud app for self-managed instances](#connect-the-gitlab-for-jira-cloud-app-for-self-managed-instances).
|
||||
- [Install the GitLab for Jira Cloud app manually](#install-the-gitlab-for-jira-cloud-app-manually).
|
||||
|
||||
To create an OAuth application:
|
||||
|
||||
|
|
@ -110,6 +109,7 @@ Prerequisites:
|
|||
- GitLab.com must serve as a proxy for the instance.
|
||||
- The instance must be publicly available.
|
||||
- The instance must be on version 15.7 or later.
|
||||
- You must set up [OAuth authentication](#set-up-oauth-authentication-for-self-managed-instances).
|
||||
|
||||
You can link self-managed instances after installing the GitLab for Jira Cloud app from the marketplace.
|
||||
Jira apps can only link to one URL per marketplace listing. The official listing links to GitLab.com.
|
||||
|
|
@ -123,7 +123,7 @@ It's not possible to create branches from Jira for self-managed instances. For m
|
|||
|
||||
To set up your self-managed instance for the GitLab for Jira Cloud app in GitLab 15.7 and later:
|
||||
|
||||
1. [Set up OAuth authentication](#set-up-oauth-authentication).
|
||||
1. [Set up OAuth authentication](#set-up-oauth-authentication-for-self-managed-instances).
|
||||
1. On the top bar, select **Main menu > Admin**.
|
||||
1. On the left sidebar, select **Settings > General** (`/admin/application_settings/general`).
|
||||
1. Expand the **GitLab for Jira App** section.
|
||||
|
|
@ -147,7 +147,7 @@ you can install the app manually.
|
|||
Prerequisites:
|
||||
|
||||
- The instance must be publicly available.
|
||||
- You must set up [OAuth authentication](#set-up-oauth-authentication).
|
||||
- You must set up [OAuth authentication](#set-up-oauth-authentication-for-self-managed-instances).
|
||||
|
||||
### Set up your Jira app
|
||||
|
||||
|
|
@ -202,9 +202,9 @@ For full instructions, review the Atlassian [guide to creating a marketplace lis
|
|||
To create a Marketplace listing:
|
||||
|
||||
1. Register as a Marketplace vendor.
|
||||
1. List your application using the application descriptor URL.
|
||||
1. List your application with the application descriptor URL.
|
||||
- Your manifest file is located at: `https://your.domain/your-path/-/jira_connect/app_descriptor.json`
|
||||
- We recommend you list your application as `private`, because public
|
||||
- You should list your application as `private` because public
|
||||
applications can be viewed and installed by any user.
|
||||
1. Generate test license tokens for your application.
|
||||
|
||||
|
|
@ -212,11 +212,11 @@ NOTE:
|
|||
This method uses [automated updates](#update-the-gitlab-for-jira-cloud-app)
|
||||
the same way as our GitLab.com Marketplace listing.
|
||||
|
||||
## Configure your GitLab instance to serve as a proxy for the GitLab for Jira Cloud app
|
||||
## Configure your GitLab instance to serve as a proxy for the GitLab for Jira Cloud app **(FREE SELF)**
|
||||
|
||||
A GitLab instance can serve as a proxy for other GitLab instances using the GitLab for Jira Cloud app.
|
||||
This can be useful if you are managing multiple GitLab instance but only want to [manually install](#install-the-gitlab-for-jira-cloud-app-manually)
|
||||
the GitLab for Jira app once.
|
||||
A GitLab instance can serve as a proxy for other GitLab instances through the GitLab for Jira Cloud app.
|
||||
You might want to use a proxy if you're managing multiple GitLab instances but only want to
|
||||
[manually install](#install-the-gitlab-for-jira-cloud-app-manually) the GitLab for Jira Cloud app once.
|
||||
|
||||
To configure your GitLab instance to serve as a proxy:
|
||||
|
||||
|
|
@ -225,9 +225,36 @@ To configure your GitLab instance to serve as a proxy:
|
|||
1. Expand the **GitLab for Jira App** section.
|
||||
1. Select **Enable public key storage**.
|
||||
1. Select **Save changes**.
|
||||
1. [Install the GitLab for Jira Cloud app manually](#install-the-gitlab-for-jira-cloud-app-manually)
|
||||
1. [Install the GitLab for Jira Cloud app manually](#install-the-gitlab-for-jira-cloud-app-manually).
|
||||
|
||||
Other GitLab instances using the proxy must configure the **Jira Connect Proxy URL** setting and the [OAuth application](#set-up-oauth-authentication) **Redirect URI** to point to the proxy instance.
|
||||
Other GitLab instances that use the proxy must configure the **Jira Connect Proxy URL** and the [OAuth application](#set-up-oauth-authentication-for-self-managed-instances) **Redirect URI** settings to point to the proxy instance.
|
||||
|
||||
## Security considerations
|
||||
|
||||
The GitLab for Jira Cloud app connects GitLab and Jira. Data must be shared between the two applications, and access must be granted in both directions.
|
||||
|
||||
### Access to GitLab through OAuth **(FREE SELF)**
|
||||
|
||||
GitLab does not share an access token with Jira. However, users must authenticate through OAuth to configure the app.
|
||||
|
||||
An access token is retrieved through a [PKCE](https://www.rfc-editor.org/rfc/rfc7636) OAuth flow and stored only on the client side.
|
||||
The app frontend that initializes the OAuth flow is a JavaScript application that's loaded from GitLab through an iframe on Jira.
|
||||
|
||||
The OAuth application must have the `api` scope, which grants complete read and write access to the API.
|
||||
This access includes all groups and projects, the container registry, and the package registry.
|
||||
However, the GitLab for Jira Cloud app only uses this access to:
|
||||
|
||||
- Display namespaces to be linked.
|
||||
- Link namespaces.
|
||||
|
||||
Access through OAuth is only needed for the time a user configures the GitLab for Jira Cloud app. For more information, see [Access token expiration](../oauth_provider.md#access-token-expiration).
|
||||
|
||||
### Access to Jira through access token
|
||||
|
||||
Jira shares an access token with GitLab to authenticate and authorize data pushes to Jira.
|
||||
As part of the app installation process, Jira sends a handshake request to GitLab containing the access token.
|
||||
The handshake is signed with an [asymmetric JWT](https://developer.atlassian.com/cloud/jira/platform/understanding-jwt-for-connect-apps/),
|
||||
and the access token is stored encrypted with `AES256-GCM` on GitLab.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
|
|
@ -243,7 +270,7 @@ You need to sign in or sign up before continuing.
|
|||
The GitLab for Jira Cloud app uses an iframe to add namespaces on the
|
||||
settings page. Some browsers block cross-site cookies, which can lead to this issue.
|
||||
|
||||
To resolve this issue, set up [OAuth authentication](#set-up-oauth-authentication) and enable the `jira_connect_oauth` [feature flag](../../administration/feature_flags.md).
|
||||
To resolve this issue, set up [OAuth authentication](#set-up-oauth-authentication-for-self-managed-instances) and enable the `jira_connect_oauth` [feature flag](../../administration/feature_flags.md).
|
||||
|
||||
### Manual installation fails
|
||||
|
||||
|
|
@ -285,29 +312,3 @@ To resolve this issue on GitLab self-managed, follow one of the solutions below,
|
|||
- Contact the [Jira Software Cloud support](https://support.atlassian.com/jira-software-cloud/) and ask to trigger a new installed lifecycle event for the GitLab for Jira Cloud app in your namespace.
|
||||
- In all GitLab versions:
|
||||
- Re-install the GitLab for Jira Cloud app. This might remove all already synced development panel data.
|
||||
|
||||
## Security considerations
|
||||
|
||||
The GitLab for Jira Cloud app connects GitLab and Jira, as data must be shared between the two applications and access must be granted in both directions.
|
||||
|
||||
## Access to GitLab through OAuth
|
||||
|
||||
GitLab does not share an access token with Jira. However, users must authenticate via OAuth to configure the app.
|
||||
|
||||
An access token is retrieved via [PKCE](https://www.rfc-editor.org/rfc/rfc7636) OAuth flow, and stored only on the client side.
|
||||
The app-frontend that initializes the OAuth flow is a JavaScript application, which is loaded from GitLab through an iframe on Jira.
|
||||
|
||||
The OAuth application requires the `api` scope that grants complete read/write access to the API, including to all groups and projects, the container registry, and the package registry.
|
||||
However, the GitLab for Jira Cloud app only uses this access to:
|
||||
|
||||
- Display namespaces to be linked.
|
||||
- Link namespaces.
|
||||
|
||||
Access through OAuth is only needed for the time a user configures the GitLab for Jira Cloud app. For more information, see [Access token expiration](../oauth_provider.md#access-token-expiration).
|
||||
|
||||
## Access to Jira through access token
|
||||
|
||||
Jira shares an access token with GitLab to authenticate and authorize data pushes to Jira.
|
||||
As part of the app installation process, Jira sends a handshake request to GitLab containing the access token.
|
||||
The handshake is signed with an [asymmetric JWT](https://developer.atlassian.com/cloud/jira/platform/understanding-jwt-for-connect-apps/)
|
||||
and the access token is stored encrypted with `AES256-GCM` on GitLab.
|
||||
|
|
|
|||
|
|
@ -976,8 +976,8 @@ This is a [breaking change](https://docs.gitlab.com/ee/development/deprecation_g
|
|||
Review the details carefully before upgrading.
|
||||
|
||||
Cookie authentication in the GitLab for Jira Cloud app is now deprecated in favor of OAuth authentication.
|
||||
You must [set up OAuth authentication](https://docs.gitlab.com/ee/integration/jira/connect-app.html#set-up-oauth-authentication)
|
||||
to continue to use the GitLab for Jira Cloud app. Without OAuth, you will not be able to manage linked namespaces.
|
||||
On self-managed, you must [set up OAuth authentication](https://docs.gitlab.com/ee/integration/jira/connect-app.html#set-up-oauth-authentication-for-self-managed-instances)
|
||||
to continue to use the GitLab for Jira Cloud app. Without OAuth, you can't manage linked namespaces.
|
||||
|
||||
</div>
|
||||
|
||||
|
|
|
|||
|
|
@ -359,7 +359,7 @@ The following package managers use lockfiles that GitLab analyzers are capable o
|
|||
| Go | Not applicable | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/go-modules/gosum/default/go.sum) <sup><strong><a href="#notes-regarding-parsing-lockfiles-1">1</a></strong></sup> |
|
||||
| NuGet | v1 | [4.9](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/csharp-nuget-dotnetcore/default/src/web.api/packages.lock.json#L2) |
|
||||
| npm | v1, v2, v3<sup><b><a href="#notes-regarding-parsing-lockfiles-2">2</a></b></sup> | [6.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-npm/default/package-lock.json#L4), [7.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-npm/lockfileVersion2/package-lock.json#L4), [9.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/scanner/parser/npm/fixtures/lockfile-v3/simple/package-lock.json#L4) |
|
||||
| yarn | v1 | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn/default/yarn.lock#L2) |
|
||||
| yarn | v1, v2<sup><b><a href="#notes-regarding-parsing-lockfiles-3">3</a></b></sup>, v3<sup><b><a href="#notes-regarding-parsing-lockfiles-3">3</a></b></sup> | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn/default/yarn.lock#L2), [2.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn-v2/default/yarn.lock), [3.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/js-yarn-v3/default/yarn.lock) |
|
||||
| Poetry | v1 | [1.x](https://gitlab.com/gitlab-org/security-products/analyzers/gemnasium/-/blob/master/qa/fixtures/python-poetry/default/poetry.lock) |
|
||||
|
||||
<!-- markdownlint-disable MD044 -->
|
||||
|
|
@ -377,6 +377,26 @@ The following package managers use lockfiles that GitLab analyzers are capable o
|
|||
Support for <code>lockfileVersion = 3</code> was <a href="https://gitlab.com/gitlab-org/gitlab/-/issues/365176">introduced</a> in GitLab 15.7.
|
||||
</p>
|
||||
</li>
|
||||
<li>
|
||||
<a id="notes-regarding-parsing-lockfiles-3"></a>
|
||||
<p>
|
||||
Support for Yarn <code>v2</code> and <code>v3</code> was <a href="https://gitlab.com/gitlab-org/gitlab/-/issues/263358">introduced in GitLab 15.11</a>. However, this feature is also available to versions of GitLab 15.0 and later.
|
||||
</p>
|
||||
<p>
|
||||
The following features are not supported for Yarn <code>v2</code> or <code>v3</code>:
|
||||
</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="https://yarnpkg.com/features/workspaces">workspaces</a>
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://yarnpkg.com/cli/patch">yarn patch</a>
|
||||
</li>
|
||||
</ul>
|
||||
<p>
|
||||
Yarn files that contain a patch, a workspace, or both, are still processed, but these features are ignored.
|
||||
</p>
|
||||
</li>
|
||||
</ol>
|
||||
<!-- markdownlint-enable MD044 -->
|
||||
|
||||
|
|
|
|||
|
|
@ -220,18 +220,10 @@ The following image shows a **Groups** and **Documentation** section:
|
|||
|
||||

|
||||
|
||||
#### Set default owner for a section **(PREMIUM SELF)**
|
||||
#### Set default owner for a section
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/371711) in GitLab 15.11 [with a flag](../../administration/feature_flags.md) named `codeowners_default_owners`. Disabled by default.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available,
|
||||
ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `codeowners_default_owners`.
|
||||
The feature is not ready for production use.
|
||||
|
||||
WARNING:
|
||||
To disable this feature flag after setting default owners per section, edit your
|
||||
CODEOWNERS file to [list Code Owners per line](#set-up-code-owners).
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/371711) in GitLab 15.11 [with a flag](../../administration/feature_flags.md) named `codeowners_default_owners`. Disabled by default.
|
||||
> - [Generally available](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/115888) in GitLab 15.11. Feature flag `codeowners_default_owners` removed.
|
||||
|
||||
If multiple file paths inside a section share the same ownership, define a default
|
||||
Code Owner for the section. All paths in that section inherit this default, unless
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue