Commit b4ddc240 authored by 🤖 GitLab Bot 🤖's avatar 🤖 GitLab Bot 🤖
Browse files

Add latest changes from gitlab-org/gitlab@master

parent 3a966afb
44b902da883a92ec1f19c760a083f9bf51698e41
0bdcff0f59fb1bc52eb93e930e53965b19296c99
import Tracking from '~/tracking';
import api from '~/api';
import Api from '~/api';
// Snowplow tracking constants
const DESIGN_TRACKING_CONTEXT_SCHEMAS = {
VIEW_DESIGN_SCHEMA: 'iglu:com.gitlab/design_management_context/jsonschema/1-0-0',
};
const DESIGN_TRACKING_EVENTS = {
export const DESIGN_TRACKING_PAGE_NAME = 'projects:issues:design';
export const DESIGN_SNOWPLOW_EVENT_TYPES = {
VIEW_DESIGN: 'view_design',
CREATE_DESIGN: 'create_design',
UPDATE_DESIGN: 'update_design',
};
// Usage ping tracking constants
const DESIGN_ACTION = 'design_action';
export const DESIGN_TRACKING_PAGE_NAME = 'projects:issues:design';
export const DESIGN_USAGE_PING_EVENT_TYPES = {
DESIGN_ACTION: 'design_action',
};
/**
* Track "design detail" view in Snowplow
......@@ -25,7 +27,7 @@ export function trackDesignDetailView(
designVersion = 1,
latestVersion = false,
) {
const eventName = DESIGN_TRACKING_EVENTS.VIEW_DESIGN;
const eventName = DESIGN_SNOWPLOW_EVENT_TYPES.VIEW_DESIGN;
Tracking.event(DESIGN_TRACKING_PAGE_NAME, eventName, {
label: eventName,
......@@ -42,16 +44,16 @@ export function trackDesignDetailView(
}
export function trackDesignCreate() {
return Tracking.event(DESIGN_TRACKING_PAGE_NAME, DESIGN_TRACKING_EVENTS.CREATE_DESIGN);
return Tracking.event(DESIGN_TRACKING_PAGE_NAME, DESIGN_SNOWPLOW_EVENT_TYPES.CREATE_DESIGN);
}
export function trackDesignUpdate() {
return Tracking.event(DESIGN_TRACKING_PAGE_NAME, DESIGN_TRACKING_EVENTS.UPDATE_DESIGN);
return Tracking.event(DESIGN_TRACKING_PAGE_NAME, DESIGN_SNOWPLOW_EVENT_TYPES.UPDATE_DESIGN);
}
/**
* Track "design detail" view via usage ping
*/
export function usagePingDesignDetailView() {
api.trackRedisHllUserEvent(DESIGN_ACTION);
Api.trackRedisHllUserEvent(DESIGN_USAGE_PING_EVENT_TYPES.DESIGN_ACTION);
}
......@@ -204,7 +204,16 @@ export default {
onInput({ untouchedRawReferences, touchedReference }) {
this.store.addPendingReferences(untouchedRawReferences);
this.inputValue = `${touchedReference}`;
this.formatInput(touchedReference);
},
formatInput(touchedReference = '') {
const startsWithNumber = String(touchedReference).match(/^[0-9]/) !== null;
if (startsWithNumber) {
this.inputValue = `#${touchedReference}`;
} else {
this.inputValue = `${touchedReference}`;
}
},
onBlur(newValue) {
this.processAllReferences(newValue);
......
......@@ -17,7 +17,7 @@ export default function initSourcegraph() {
return;
}
const assetsUrl = new URL('/assets/webpack/sourcegraph/', window.location.href);
const assetsUrl = new URL(process.env.SOURCEGRAPH_PUBLIC_PATH, window.location.href);
const scriptPath = new URL('scripts/integration.bundle.js', assetsUrl).href;
window.SOURCEGRAPH_ASSETS_URL = assetsUrl.href;
......
......@@ -14,7 +14,7 @@ def authorize
authorized = uploader_class.workhorse_authorize(
has_length: false,
maximum_size: Gitlab::CurrentSettings.max_attachment_size.megabytes.to_i)
maximum_size: maximum_size.to_i)
render json: authorized
rescue SocketError
......@@ -33,6 +33,10 @@ def uploader_class
raise NotImplementedError
end
def maximum_size
raise NotImplementedError
end
def file_extension_whitelist
ImportExportUploader::EXTENSION_WHITELIST
end
......
......@@ -68,4 +68,8 @@ def import_rate_limit
def uploader_class
ImportExportUploader
end
def maximum_size
Gitlab::CurrentSettings.max_import_size.megabytes
end
end
......@@ -49,4 +49,8 @@ def whitelist_query_limiting
def uploader_class
ImportExportUploader
end
def maximum_size
Gitlab::CurrentSettings.max_import_size.megabytes
end
end
# frozen_string_literal: true
module Resolvers
class ProjectPipelineStatisticsResolver < BaseResolver
type Types::Ci::AnalyticsType, null: true
def resolve
weekly_stats = Gitlab::Ci::Charts::WeekChart.new(object)
monthly_stats = Gitlab::Ci::Charts::MonthChart.new(object)
yearly_stats = Gitlab::Ci::Charts::YearChart.new(object)
pipeline_times = Gitlab::Ci::Charts::PipelineTime.new(object)
{
week_pipelines_labels: weekly_stats.labels,
week_pipelines_totals: weekly_stats.total,
week_pipelines_successful: weekly_stats.success,
month_pipelines_labels: monthly_stats.labels,
month_pipelines_totals: monthly_stats.total,
month_pipelines_successful: monthly_stats.success,
year_pipelines_labels: yearly_stats.labels,
year_pipelines_totals: yearly_stats.total,
year_pipelines_successful: yearly_stats.success,
pipeline_times_labels: pipeline_times.labels,
pipeline_times_values: pipeline_times.pipeline_times
}
end
end
end
# frozen_string_literal: true
module Types
module Ci
# rubocop: disable Graphql/AuthorizeTypes
class AnalyticsType < BaseObject
graphql_name 'PipelineAnalytics'
field :week_pipelines_totals, [GraphQL::INT_TYPE], null: true,
description: 'Total weekly pipeline count'
field :week_pipelines_successful, [GraphQL::INT_TYPE], null: true,
description: 'Total weekly successful pipeline count'
field :week_pipelines_labels, [GraphQL::STRING_TYPE], null: true,
description: 'Labels for the weekly pipeline count'
field :month_pipelines_totals, [GraphQL::INT_TYPE], null: true,
description: 'Total monthly pipeline count'
field :month_pipelines_successful, [GraphQL::INT_TYPE], null: true,
description: 'Total monthly successful pipeline count'
field :month_pipelines_labels, [GraphQL::STRING_TYPE], null: true,
description: 'Labels for the monthly pipeline count'
field :year_pipelines_totals, [GraphQL::INT_TYPE], null: true,
description: 'Total yearly pipeline count'
field :year_pipelines_successful, [GraphQL::INT_TYPE], null: true,
description: 'Total yearly successful pipeline count'
field :year_pipelines_labels, [GraphQL::STRING_TYPE], null: true,
description: 'Labels for the yearly pipeline count'
field :pipeline_times_values, [GraphQL::INT_TYPE], null: true,
description: 'Pipeline times'
field :pipeline_times_labels, [GraphQL::STRING_TYPE], null: true,
description: 'Pipeline times labels'
end
end
end
......@@ -304,6 +304,13 @@ class ProjectType < BaseObject
description: 'Terraform states associated with the project',
resolver: Resolvers::Terraform::StatesResolver
field :pipeline_analytics, Types::Ci::AnalyticsType, null: true,
description: 'Pipeline analytics',
resolver: Resolvers::ProjectPipelineStatisticsResolver
field :total_pipeline_duration, GraphQL::INT_TYPE, null: true,
description: 'Total pipeline duration for all of the pipelines in a project'
def label(title:)
BatchLoader::GraphQL.for(title).batch(key: project) do |titles, loader, args|
LabelsFinder
......@@ -348,6 +355,10 @@ def container_repositories_count
project.container_repositories.size
end
def total_pipeline_duration
object.all_pipelines.total_duration
end
private
def project
......
......@@ -1843,6 +1843,7 @@ def after_import
wiki.repository.expire_content_cache
DetectRepositoryLanguagesWorker.perform_async(id)
ProjectCacheWorker.perform_async(self.id, [], [:repository_size])
# The import assigns iid values on its own, e.g. by re-using GitHub ids.
# Flush existing InternalId records for this project for consistency reasons.
......
......@@ -4,10 +4,11 @@ module Issues
class CloneService < Issuable::Clone::BaseService
CloneError = Class.new(StandardError)
def execute(issue, target_project)
def execute(issue, target_project, with_notes: false)
@target_project = target_project
@with_notes = with_notes
unless issue.can_clone?(current_user, @target_project)
unless issue.can_clone?(current_user, target_project)
raise CloneError, s_('CloneIssue|Cannot clone issue due to insufficient permissions!')
end
......@@ -17,6 +18,8 @@ def execute(issue, target_project)
super(issue, target_project)
notify_participants
queue_copy_designs
new_entity
......@@ -25,12 +28,14 @@ def execute(issue, target_project)
private
attr_reader :target_project
attr_reader :with_notes
def update_new_entity
# we don't call `super` because we want to be able to decide whether or not to copy all comments over.
update_new_entity_description
update_new_entity_attributes
copy_award_emoji
copy_notes if with_notes
end
def update_old_entity
......@@ -51,7 +56,7 @@ def create_new_entity
# Skip creation of system notes for existing attributes of the issue. The system notes of the old
# issue are copied over so we don't want to end up with duplicate notes.
CreateService.new(@target_project, @current_user, new_params).execute(skip_system_notes: true)
CreateService.new(target_project, current_user, new_params).execute(skip_system_notes: true)
end
def queue_copy_designs
......@@ -66,6 +71,10 @@ def queue_copy_designs
log_error(response.message) if response.error?
end
def notify_participants
notification_service.async.issue_cloned(original_entity, new_entity, current_user)
end
def add_note_from
SystemNoteService.noteable_cloned(new_entity, target_project,
original_entity, current_user,
......
......@@ -129,13 +129,14 @@ def move_issue_to_new_project(issue)
def clone_issue(issue)
target_project = params.delete(:target_clone_project)
with_notes = params.delete(:clone_with_notes)
return unless target_project &&
issue.can_clone?(current_user, target_project)
# we've pre-empted this from running in #execute, so let's go ahead and update the Issue now.
update(issue)
Issues::CloneService.new(project, current_user).execute(issue, target_project)
Issues::CloneService.new(project, current_user).execute(issue, target_project, with_notes: with_notes)
end
def create_merge_request_from_quick_action
......
......@@ -73,7 +73,7 @@ def perform(*args)
raise
ensure
job_tracker.remove(jid)
report_prometheus_metrics
report_prometheus_metrics(*args)
re_enqueue(*args) unless exception
end
......
---
title: Conan packages show build and commit information when published using CI
merge_request: 49426
author:
type: fixed
---
title: Make sure Sourcegraph asset always loads successfully
merge_request: 49030
author:
type: fixed
---
title: Implement a /clone_with_notes quick-action to quickly clone an Issue will all
its notes
merge_request: 48539
author:
type: added
---
title: Add CI/CD analytics GraphQL types
merge_request: 49384
author:
type: added
---
title: 'Geo: Add verification indexes for package files'
merge_request: 47372
author:
type: added
---
title: Upgrade Pages to 1.31.0
merge_request: 49352
author:
type: added
---
title: Update repository size after import
merge_request: 49319
author:
type: fixed
---
title: 'Add ability to type a number in related issues and prepend #'
merge_request: 48952
author:
type: changed
......@@ -553,6 +553,9 @@
Settings.cron_jobs['adjourned_projects_deletion_cron_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['adjourned_projects_deletion_cron_worker']['cron'] ||= '0 4 * * *'
Settings.cron_jobs['adjourned_projects_deletion_cron_worker']['job_class'] = 'AdjournedProjectsDeletionCronWorker'
Settings.cron_jobs['geo_verification_cron_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['geo_verification_cron_worker']['cron'] ||= '* * * * *'
Settings.cron_jobs['geo_verification_cron_worker']['job_class'] ||= 'Geo::VerificationCronWorker'
Settings.cron_jobs['geo_file_download_dispatch_worker'] ||= Settingslogic.new({})
Settings.cron_jobs['geo_file_download_dispatch_worker']['cron'] ||= '*/1 * * * *'
Settings.cron_jobs['geo_file_download_dispatch_worker']['job_class'] ||= 'Geo::FileDownloadDispatchWorker'
......
......@@ -29,9 +29,18 @@ const WEBPACK_MEMORY_TEST =
const NO_COMPRESSION = process.env.NO_COMPRESSION && process.env.NO_COMPRESSION !== 'false';
const NO_SOURCEMAPS = process.env.NO_SOURCEMAPS && process.env.NO_SOURCEMAPS !== 'false';
const WEBPACK_OUTPUT_PATH = path.join(ROOT_PATH, 'public/assets/webpack');
const WEBPACK_PUBLIC_PATH = '/assets/webpack/';
const SOURCEGRAPH_PACKAGE = '@sourcegraph/code-host-integration';
const VUE_VERSION = require('vue/package.json').version;
const VUE_LOADER_VERSION = require('vue-loader/package.json').version;
const WEBPACK_VERSION = require('webpack/package.json').version;
const SOURCEGRAPH_VERSION = require(path.join(SOURCEGRAPH_PACKAGE, 'package.json')).version;
const SOURCEGRAPH_PATH = path.join('sourcegraph', SOURCEGRAPH_VERSION, '/');
const SOURCEGRAPH_OUTPUT_PATH = path.join(WEBPACK_OUTPUT_PATH, SOURCEGRAPH_PATH);
const SOURCEGRAPH_PUBLIC_PATH = path.join(WEBPACK_PUBLIC_PATH, SOURCEGRAPH_PATH);
const devtool = IS_PRODUCTION ? 'source-map' : 'cheap-module-eval-source-map';
......@@ -143,7 +152,7 @@ if (VENDOR_DLL && !IS_PRODUCTION) {
dll = {
manifestPath: path.join(dllCachePath, 'vendor.dll.manifest.json'),
cacheFrom: dllCachePath,
cacheTo: path.join(ROOT_PATH, `public/assets/webpack/dll.${dllHash}/`),
cacheTo: path.join(WEBPACK_OUTPUT_PATH, `dll.${dllHash}/`),
publicPath: `dll.${dllHash}/vendor.dll.bundle.js`,
exists: null,
};
......@@ -157,8 +166,8 @@ module.exports = {
entry: generateEntries,
output: {
path: path.join(ROOT_PATH, 'public/assets/webpack'),
publicPath: '/assets/webpack/',
path: WEBPACK_OUTPUT_PATH,
publicPath: WEBPACK_PUBLIC_PATH,
filename: IS_PRODUCTION ? '[name].[contenthash:8].bundle.js' : '[name].bundle.js',
chunkFilename: IS_PRODUCTION ? '[name].[contenthash:8].chunk.js' : '[name].chunk.js',
globalObject: 'this', // allow HMR and web workers to play nice
......@@ -449,11 +458,11 @@ module.exports = {
new CopyWebpackPlugin([
{
from: path.join(ROOT_PATH, 'node_modules/pdfjs-dist/cmaps/'),
to: path.join(ROOT_PATH, 'public/assets/webpack/cmaps/'),
to: path.join(WEBPACK_OUTPUT_PATH, 'cmaps/'),
},
{
from: path.join(ROOT_PATH, 'node_modules/@sourcegraph/code-host-integration/'),
to: path.join(ROOT_PATH, 'public/assets/webpack/sourcegraph/'),
from: path.join(ROOT_PATH, 'node_modules', SOURCEGRAPH_PACKAGE, '/'),
to: SOURCEGRAPH_OUTPUT_PATH,
ignore: ['package.json'],
},
{
......@@ -461,7 +470,7 @@ module.exports = {
ROOT_PATH,
'node_modules/@gitlab/visual-review-tools/dist/visual_review_toolbar.js',
),
to: path.join(ROOT_PATH, 'public/assets/webpack'),
to: WEBPACK_OUTPUT_PATH,
},
]),
......@@ -555,6 +564,8 @@ module.exports = {
'process.env.IS_EE': JSON.stringify(IS_EE),
// This one is used to check against "EE" properly in application code
IS_EE: IS_EE ? 'window.gon && window.gon.ee' : JSON.stringify(false),
// This is used by Sourcegraph because these assets are loaded dnamically
'process.env.SOURCEGRAPH_PUBLIC_PATH': JSON.stringify(SOURCEGRAPH_PUBLIC_PATH),
}),
/* Pikaday has a optional dependency to moment.
......
# frozen_string_literal: true
class AddVerificationIndexesForPackageFiles < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DOWNTIME = false
PENDING_VERIFICATION_INDEX_NAME = "packages_packages_pending_verification"
FAILED_VERIFICATION_INDEX_NAME = "packages_packages_failed_verification"
NEEDS_VERIFICATION_INDEX_NAME = "packages_packages_needs_verification"
disable_ddl_transaction!
def up
add_concurrent_index :packages_package_files, :verified_at, where: "(verification_state = 0)", order: { verified_at: 'ASC NULLS FIRST' }, name: PENDING_VERIFICATION_INDEX_NAME
add_concurrent_index :packages_package_files, :verification_retry_at, where: "(verification_state = 3)", order: { verification_retry_at: 'ASC NULLS FIRST' }, name: FAILED_VERIFICATION_INDEX_NAME
add_concurrent_index :packages_package_files, :verification_state, where: "(verification_state = 0 OR verification_state = 3)", name: NEEDS_VERIFICATION_INDEX_NAME
end
def down
remove_concurrent_index_by_name :packages_package_files, PENDING_VERIFICATION_INDEX_NAME
remove_concurrent_index_by_name :packages_package_files, FAILED_VERIFICATION_INDEX_NAME
remove_concurrent_index_by_name :packages_package_files, NEEDS_VERIFICATION_INDEX_NAME
end
end
418481f8281f8908740d3a8378b420f4d83853aab139b3401f7e410fc97d2488
\ No newline at end of file
......@@ -22751,6 +22751,12 @@ CREATE UNIQUE INDEX one_canonical_wiki_page_slug_per_metadata ON wiki_page_slugs
CREATE INDEX package_name_index ON packages_packages USING btree (name);
CREATE INDEX packages_packages_failed_verification ON packages_package_files USING btree (verification_retry_at NULLS FIRST) WHERE (verification_state = 3);
CREATE INDEX packages_packages_needs_verification ON packages_package_files USING btree (verification_state) WHERE ((verification_state = 0) OR (verification_state = 3));
CREATE INDEX packages_packages_pending_verification ON packages_package_files USING btree (verified_at NULLS FIRST) WHERE (verification_state = 0);
CREATE INDEX partial_index_ci_builds_on_scheduled_at_with_scheduled_jobs ON ci_builds USING btree (scheduled_at) WHERE ((scheduled_at IS NOT NULL) AND ((type)::text = 'Ci::Build'::text) AND ((status)::text = 'scheduled'::text));
CREATE INDEX partial_index_deployments_for_legacy_successful_deployments ON deployments USING btree (id) WHERE ((finished_at IS NULL) AND (status = 2));
......
---
# Error: gitlab.AlertBoxCaution
#
# Makes sure CAUTION: alert boxes follow standard formatting.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: substitution
message: "CAUTION: alert boxes must be of the format 'CAUTION: **Caution:**'. 'Caution' can be replaced with 'Warning' or 'Important'."
link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#alert-boxes
level: warning
nonword: true
scope: raw
swap:
'CAUTION: *?\*\*.*\*\*': 'CAUTION: \*\*(?:Caution|Warning|Important):\*\*'
---
# Error: gitlab.AlertBoxDanger
#
# Makes sure DANGER: alert boxes follow standard formatting.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: substitution
message: "DANGER: alert boxes must be of the format 'DANGER: **Warning:**'. 'Warning' can be replaced with 'Important', 'Deprecated', or 'Required'."
link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#alert-boxes
level: error
nonword: true
scope: raw
swap:
'DANGER: *?\*\*.*\*\*': 'DANGER: \*\*(?:Warning|Important|Deprecated|Required):\*\*'
---
# Error: gitlab.AlertBoxNoteTip
#
# Makes sure NOTE: and TIP: alert boxes follow standard formatting.
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: substitution
message: "NOTE: and TIP: alert boxes must be of the format 'NOTE:' or 'TIP: **Tip:**"
link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#alert-boxes
level: warning
nonword: true
scope: raw
swap:
'NOTE: *?\*\*.*\*\*': 'NOTE: \*\*Note:\*\*'
'TIP: *?\*\*.*\*\*': 'TIP: \*\*Tip:\*\*'
---
# Error: gitlab.AlertBoxStyle
#
# Makes sure alert boxes follow standard formatting.
#
# Checks for 2 formatting issues:
# - Alert boxes with the note text on the same line
# - Alert boxes using blockquote formatting, like "> **Note:**"
#
# For a list of all options, see https://errata-ai.gitbook.io/vale/getting-started/styles
extends: existence
message: 'Alert box "%s" must use the formatting in the style guide.'
link: https://docs.gitlab.com/ee/development/documentation/styleguide.html#alert-boxes
level: error
scope: raw
raw: