Add latest changes from gitlab-org/gitlab@master

This commit is contained in:
GitLab Bot 2021-05-17 15:10:15 +00:00
parent a62238de73
commit 68c476dbd8
156 changed files with 2904 additions and 1427 deletions

View File

@ -9,8 +9,18 @@ build-qa-image:
- .build-images:rules:build-qa-image
stage: build-images
needs: []
variables:
QA_IMAGE: "${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_REF_SLUG}"
script:
- export QA_IMAGE="${CI_REGISTRY}/${CI_PROJECT_PATH}/gitlab-ee-qa:${CI_COMMIT_REF_SLUG}"
# With .git/hooks/post-checkout in place, Git tries to pull LFS objects, but the image doesn't have Git LFS, and we actually don't care about it for this specific so we just remove the file.
# Without removing the file, the error is as follows: "This repository is configured for Git LFS but 'git-lfs' was not found on your path. If you no longer wish to use Git LFS, remove this hook by deleting .git/hooks/post-checkout."
- rm .git/hooks/post-checkout
# Use $CI_MERGE_REQUEST_SOURCE_BRANCH_SHA so that GitLab image built in omnibus-gitlab-mirror and QA image are in sync.
# This falls back to $CI_COMMIT_SHA (the default checked out commit) for the non-merged result pipelines.
# See https://docs.gitlab.com/ee/development/testing_guide/end_to_end/index.html#with-pipeline-for-merged-results.
- if [ -n "$CI_MERGE_REQUEST_SOURCE_BRANCH_SHA" ]; then
git checkout -f ${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA};
fi
- /kaniko/executor --context=${CI_PROJECT_DIR} --dockerfile=${CI_PROJECT_DIR}/qa/Dockerfile --destination=${QA_IMAGE} --cache=true
retry: 2

View File

@ -128,7 +128,7 @@
.use-kaniko:
image:
name: gcr.io/kaniko-project/executor:debug-v1.3.0
name: registry.gitlab.com/gitlab-org/gitlab-build-images:kaniko
entrypoint: [""]
before_script:
- source scripts/utils.sh

View File

@ -2941,7 +2941,6 @@ Style/RegexpLiteralMixedPreserve:
- 'app/models/concerns/ci/maskable.rb'
- 'app/models/operations/feature_flag.rb'
- 'app/models/packages/go/module.rb'
- 'app/models/project_services/chat_message/base_message.rb'
- 'app/services/packages/conan/search_service.rb'
- 'app/services/projects/update_remote_mirror_service.rb'
- 'config/initializers/rspec_profiling.rb'

View File

@ -598,7 +598,6 @@ Rails/RenderInline:
# SupportedStyles: conservative, aggressive
Rails/ShortI18n:
Exclude:
- 'app/models/project_services/chat_message/pipeline_message.rb'
- 'app/uploaders/content_type_whitelist.rb'
# Offense count: 1144

View File

@ -1 +1 @@
2be01682b4a0ba12cad12b30bad4dc8876503f22
c93530dd0922e7554d6d1e486e830f72980fe083

View File

@ -333,7 +333,7 @@ export default {
ghostClass: 'gl-visibility-hidden',
},
i18n: {
dropzoneDescriptionText: __('Drop or %{linkStart}upload%{linkEnd} designs to attach'),
dropzoneDescriptionText: __('Drag your designs here or %{linkStart}click to upload%{linkEnd}.'),
},
};
</script>

View File

@ -14,6 +14,13 @@ export default {
GlTable,
},
inject: ['issuableId', 'issuableType'],
props: {
limitToHours: {
type: Boolean,
default: false,
required: false,
},
},
data() {
return { report: [], isLoading: true };
},
@ -60,7 +67,10 @@ export default {
},
formatTimeSpent(seconds) {
const negative = seconds < 0;
return (negative ? '- ' : '') + stringifyTime(parseSeconds(seconds));
return (
(negative ? '- ' : '') +
stringifyTime(parseSeconds(seconds, { limitToHours: this.limitToHours }))
);
},
},
fields: [

View File

@ -180,7 +180,7 @@ export default {
:title="__('Time tracking report')"
:hide-footer="true"
>
<time-tracking-report />
<time-tracking-report :limit-to-hours="limitToHours" />
</gl-modal>
<transition name="help-state-toggle">
<time-tracking-help-state v-if="showHelpState" />

View File

@ -178,7 +178,7 @@ export default {
class="labels-fetch-loading gl-align-items-center w-100 h-100"
size="md"
/>
<ul v-else class="list-unstyled mb-0">
<ul v-else class="list-unstyled gl-mb-0 gl-word-break-word">
<label-item
v-for="(label, index) in visibleLabels"
:key="label.id"

View File

@ -14,7 +14,7 @@ class DashboardController < Dashboard::ApplicationController
respond_to :html
feature_category :audit_events, [:activity]
feature_category :users, [:activity]
feature_category :issue_tracking, [:issues, :issues_calendar]
feature_category :code_review, [:merge_requests]

View File

@ -49,10 +49,9 @@ class GroupsController < Groups::ApplicationController
feature_category :subgroups, [
:index, :new, :create, :show, :edit, :update,
:destroy, :details, :transfer
:destroy, :details, :transfer, :activity
]
feature_category :audit_events, [:activity]
feature_category :issue_tracking, [:issues, :issues_calendar, :preview_markdown]
feature_category :code_review, [:merge_requests, :unfoldered_environment_names]
feature_category :projects, [:projects]

View File

@ -43,13 +43,12 @@ class ProjectsController < Projects::ApplicationController
feature_category :projects, [
:index, :show, :new, :create, :edit, :update, :transfer,
:destroy, :resolve, :archive, :unarchive, :toggle_star
:destroy, :resolve, :archive, :unarchive, :toggle_star, :activity
]
feature_category :source_code_management, [:remove_fork, :housekeeping, :refs]
feature_category :issue_tracking, [:preview_markdown, :new_issuable_address]
feature_category :importers, [:export, :remove_export, :generate_new_export, :download_export]
feature_category :audit_events, [:activity]
feature_category :code_review, [:unfoldered_environment_names]
def index

View File

@ -26,7 +26,6 @@ module Packages
.including_project_route
.including_tags
.for_projects(group_projects_visible_to_current_user.select(:id))
.processed
.sort_by_attribute("#{params[:order_by]}_#{params[:sort]}")
packages = filter_with_version(packages)

View File

@ -14,7 +14,6 @@ module Packages
def packages
result = base.nuget
.has_version
.processed
.with_name_like(@params[:package_name])
result = result.with_version(@params[:package_version]) if @params[:package_version].present?
result

View File

@ -13,7 +13,6 @@ module Packages
.including_project_route
.including_tags
.displayable
.processed
.find(@package_id)
end
end

View File

@ -17,7 +17,6 @@ module Packages
.including_build_info
.including_project_route
.including_tags
.processed
packages = filter_with_version(packages)
packages = filter_by_package_type(packages)
packages = filter_by_package_name(packages)

View File

@ -10,7 +10,7 @@ module Packages
private
def packages
base.pypi.has_version.processed
base.pypi.has_version
end
end
end

View File

@ -13,7 +13,7 @@ module Packages
private
def packages
base.pypi.has_version.processed
base.pypi.has_version
end
end
end

View File

@ -0,0 +1,76 @@
# frozen_string_literal: true
module Integrations
module ChatMessage
class AlertMessage < BaseMessage
attr_reader :title
attr_reader :alert_url
attr_reader :severity
attr_reader :events
attr_reader :status
attr_reader :started_at
def initialize(params)
@project_name = params[:project_name] || params.dig(:project, :path_with_namespace)
@project_url = params.dig(:project, :web_url) || params[:project_url]
@title = params.dig(:object_attributes, :title)
@alert_url = params.dig(:object_attributes, :url)
@severity = params.dig(:object_attributes, :severity)
@events = params.dig(:object_attributes, :events)
@status = params.dig(:object_attributes, :status)
@started_at = params.dig(:object_attributes, :started_at)
end
def attachments
[{
title: title,
title_link: alert_url,
color: attachment_color,
fields: attachment_fields
}]
end
def message
"Alert firing in #{project_name}"
end
private
def attachment_color
"#C95823"
end
def attachment_fields
[
{
title: "Severity",
value: severity.to_s.humanize,
short: true
},
{
title: "Events",
value: events,
short: true
},
{
title: "Status",
value: status.to_s.humanize,
short: true
},
{
title: "Start time",
value: format_time(started_at),
short: true
}
]
end
# This formats time into the following format
# April 23rd, 2020 1:06AM UTC
def format_time(time)
time = Time.zone.parse(time.to_s)
time.strftime("%B #{time.day.ordinalize}, %Y %l:%M%p %Z")
end
end
end
end

View File

@ -0,0 +1,88 @@
# frozen_string_literal: true
module Integrations
module ChatMessage
class BaseMessage
RELATIVE_LINK_REGEX = %r{!\[[^\]]*\]\((/uploads/[^\)]*)\)}.freeze
attr_reader :markdown
attr_reader :user_full_name
attr_reader :user_name
attr_reader :user_avatar
attr_reader :project_name
attr_reader :project_url
def initialize(params)
@markdown = params[:markdown] || false
@project_name = params[:project_name] || params.dig(:project, :path_with_namespace)
@project_url = params.dig(:project, :web_url) || params[:project_url]
@user_full_name = params.dig(:user, :name) || params[:user_full_name]
@user_name = params.dig(:user, :username) || params[:user_name]
@user_avatar = params.dig(:user, :avatar_url) || params[:user_avatar]
end
def user_combined_name
if user_full_name.present?
"#{user_full_name} (#{user_name})"
else
user_name
end
end
def summary
return message if markdown
format(message)
end
def pretext
summary
end
def fallback
format(message)
end
def attachments
raise NotImplementedError
end
def activity
raise NotImplementedError
end
private
def message
raise NotImplementedError
end
def format(string)
Slack::Messenger::Util::LinkFormatter.format(format_relative_links(string))
end
def format_relative_links(string)
string.gsub(RELATIVE_LINK_REGEX, "#{project_url}\\1")
end
def attachment_color
'#345'
end
def link(text, url)
"[#{text}](#{url})"
end
def pretty_duration(seconds)
parse_string =
if duration < 1.hour
'%M:%S'
else
'%H:%M:%S'
end
Time.at(seconds).utc.strftime(parse_string)
end
end
end
end

View File

@ -0,0 +1,87 @@
# frozen_string_literal: true
module Integrations
module ChatMessage
class DeploymentMessage < BaseMessage
attr_reader :commit_title
attr_reader :commit_url
attr_reader :deployable_id
attr_reader :deployable_url
attr_reader :environment
attr_reader :short_sha
attr_reader :status
attr_reader :user_url
def initialize(data)
super
@commit_title = data[:commit_title]
@commit_url = data[:commit_url]
@deployable_id = data[:deployable_id]
@deployable_url = data[:deployable_url]
@environment = data[:environment]
@short_sha = data[:short_sha]
@status = data[:status]
@user_url = data[:user_url]
end
def attachments
[{
text: "#{project_link} with job #{deployment_link} by #{user_link}\n#{commit_link}: #{commit_title}",
color: color
}]
end
def activity
{}
end
private
def message
if running?
"Starting deploy to #{environment}"
else
"Deploy to #{environment} #{humanized_status}"
end
end
def color
case status
when 'success'
'good'
when 'canceled'
'warning'
when 'failed'
'danger'
else
'#334455'
end
end
def project_link
link(project_name, project_url)
end
def deployment_link
link("##{deployable_id}", deployable_url)
end
def user_link
link(user_combined_name, user_url)
end
def commit_link
link(short_sha, commit_url)
end
def humanized_status
status == 'success' ? 'succeeded' : status
end
def running?
status == 'running'
end
end
end
end

View File

@ -0,0 +1,74 @@
# frozen_string_literal: true
module Integrations
module ChatMessage
class IssueMessage < BaseMessage
attr_reader :title
attr_reader :issue_iid
attr_reader :issue_url
attr_reader :action
attr_reader :state
attr_reader :description
def initialize(params)
super
obj_attr = params[:object_attributes]
obj_attr = HashWithIndifferentAccess.new(obj_attr)
@title = obj_attr[:title]
@issue_iid = obj_attr[:iid]
@issue_url = obj_attr[:url]
@action = obj_attr[:action]
@state = obj_attr[:state]
@description = obj_attr[:description] || ''
end
def attachments
return [] unless opened_issue?
return description if markdown
description_message
end
def activity
{
title: "Issue #{state} by #{user_combined_name}",
subtitle: "in #{project_link}",
text: issue_link,
image: user_avatar
}
end
private
def message
"[#{project_link}] Issue #{issue_link} #{state} by #{user_combined_name}"
end
def opened_issue?
action == 'open'
end
def description_message
[{
title: issue_title,
title_link: issue_url,
text: format(description),
color: '#C95823'
}]
end
def project_link
link(project_name, project_url)
end
def issue_link
link(issue_title, issue_url)
end
def issue_title
"#{Issue.reference_prefix}#{issue_iid} #{title}"
end
end
end
end

View File

@ -0,0 +1,83 @@
# frozen_string_literal: true
module Integrations
module ChatMessage
class MergeMessage < BaseMessage
attr_reader :merge_request_iid
attr_reader :source_branch
attr_reader :target_branch
attr_reader :action
attr_reader :state
attr_reader :title
def initialize(params)
super
obj_attr = params[:object_attributes]
obj_attr = HashWithIndifferentAccess.new(obj_attr)
@merge_request_iid = obj_attr[:iid]
@source_branch = obj_attr[:source_branch]
@target_branch = obj_attr[:target_branch]
@action = obj_attr[:action]
@state = obj_attr[:state]
@title = format_title(obj_attr[:title])
end
def attachments
[]
end
def activity
{
title: "Merge request #{state_or_action_text} by #{user_combined_name}",
subtitle: "in #{project_link}",
text: merge_request_link,
image: user_avatar
}
end
private
def format_title(title)
'*' + title.lines.first.chomp + '*'
end
def message
merge_request_message
end
def project_link
link(project_name, project_url)
end
def merge_request_message
"#{user_combined_name} #{state_or_action_text} merge request #{merge_request_link} in #{project_link}"
end
def merge_request_link
link(merge_request_title, merge_request_url)
end
def merge_request_title
"#{MergeRequest.reference_prefix}#{merge_request_iid} #{title}"
end
def merge_request_url
"#{project_url}/-/merge_requests/#{merge_request_iid}"
end
def state_or_action_text
case action
when 'approved', 'unapproved'
action
when 'approval'
'added their approval to'
when 'unapproval'
'removed their approval from'
else
state
end
end
end
end
end

View File

@ -0,0 +1,86 @@
# frozen_string_literal: true
module Integrations
module ChatMessage
class NoteMessage < BaseMessage
attr_reader :note
attr_reader :note_url
attr_reader :title
attr_reader :target
def initialize(params)
super
params = HashWithIndifferentAccess.new(params)
obj_attr = params[:object_attributes]
@note = obj_attr[:note]
@note_url = obj_attr[:url]
@target, @title = case obj_attr[:noteable_type]
when "Commit"
create_commit_note(params[:commit])
when "Issue"
create_issue_note(params[:issue])
when "MergeRequest"
create_merge_note(params[:merge_request])
when "Snippet"
create_snippet_note(params[:snippet])
end
end
def attachments
return note if markdown
description_message
end
def activity
{
title: "#{user_combined_name} #{link('commented on ' + target, note_url)}",
subtitle: "in #{project_link}",
text: formatted_title,
image: user_avatar
}
end
private
def message
"#{user_combined_name} #{link('commented on ' + target, note_url)} in #{project_link}: *#{formatted_title}*"
end
def format_title(title)
title.lines.first.chomp
end
def formatted_title
format_title(title)
end
def create_issue_note(issue)
["issue #{Issue.reference_prefix}#{issue[:iid]}", issue[:title]]
end
def create_commit_note(commit)
commit_sha = Commit.truncate_sha(commit[:id])
["commit #{commit_sha}", commit[:message]]
end
def create_merge_note(merge_request)
["merge request #{MergeRequest.reference_prefix}#{merge_request[:iid]}", merge_request[:title]]
end
def create_snippet_note(snippet)
["snippet #{Snippet.reference_prefix}#{snippet[:id]}", snippet[:title]]
end
def description_message
[{ text: format(note), color: attachment_color }]
end
def project_link
link(project_name, project_url)
end
end
end
end

View File

@ -0,0 +1,267 @@
# frozen_string_literal: true
module Integrations
module ChatMessage
class PipelineMessage < BaseMessage
MAX_VISIBLE_JOBS = 10
attr_reader :user
attr_reader :ref_type
attr_reader :ref
attr_reader :status
attr_reader :detailed_status
attr_reader :duration
attr_reader :finished_at
attr_reader :pipeline_id
attr_reader :failed_stages
attr_reader :failed_jobs
attr_reader :project
attr_reader :commit
attr_reader :committer
attr_reader :pipeline
def initialize(data)
super
@user = data[:user]
@user_name = data.dig(:user, :username) || 'API'
pipeline_attributes = data[:object_attributes]
@ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch'
@ref = pipeline_attributes[:ref]
@status = pipeline_attributes[:status]
@detailed_status = pipeline_attributes[:detailed_status]
@duration = pipeline_attributes[:duration].to_i
@finished_at = pipeline_attributes[:finished_at] ? Time.parse(pipeline_attributes[:finished_at]).to_i : nil
@pipeline_id = pipeline_attributes[:id]
# Get list of jobs that have actually failed (after exhausting all retries)
@failed_jobs = actually_failed_jobs(Array(data[:builds]))
@failed_stages = @failed_jobs.map { |j| j[:stage] }.uniq
@project = Project.find(data[:project][:id])
@commit = project.commit_by(oid: data[:commit][:id])
@committer = commit.committer
@pipeline = Ci::Pipeline.find(pipeline_id)
end
def pretext
''
end
def attachments
return message if markdown
[{
fallback: format(message),
color: attachment_color,
author_name: user_combined_name,
author_icon: user_avatar,
author_link: author_url,
title: s_("ChatMessage|Pipeline #%{pipeline_id} %{humanized_status} in %{duration}") %
{
pipeline_id: pipeline_id,
humanized_status: humanized_status,
duration: pretty_duration(duration)
},
title_link: pipeline_url,
fields: attachments_fields,
footer: project.name,
footer_icon: project.avatar_url(only_path: false),
ts: finished_at
}]
end
def activity
{
title: s_("ChatMessage|Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status}") %
{
pipeline_link: pipeline_link,
ref_type: ref_type,
ref_link: ref_link,
user_combined_name: user_combined_name,
humanized_status: humanized_status
},
subtitle: s_("ChatMessage|in %{project_link}") % { project_link: project_link },
text: s_("ChatMessage|in %{duration}") % { duration: pretty_duration(duration) },
image: user_avatar || ''
}
end
private
def actually_failed_jobs(builds)
succeeded_job_names = builds.map { |b| b[:name] if b[:status] == 'success' }.compact.uniq
failed_jobs = builds.select do |build|
# Select jobs which doesn't have a successful retry
build[:status] == 'failed' && !succeeded_job_names.include?(build[:name])
end
failed_jobs.uniq { |job| job[:name] }.reverse
end
def failed_stages_field
{
title: s_("ChatMessage|Failed stage").pluralize(failed_stages.length),
value: Slack::Messenger::Util::LinkFormatter.format(failed_stages_links),
short: true
}
end
def failed_jobs_field
{
title: s_("ChatMessage|Failed job").pluralize(failed_jobs.length),
value: Slack::Messenger::Util::LinkFormatter.format(failed_jobs_links),
short: true
}
end
def yaml_error_field
{
title: s_("ChatMessage|Invalid CI config YAML file"),
value: pipeline.yaml_errors,
short: false
}
end
def attachments_fields
fields = [
{
title: ref_type == "tag" ? s_("ChatMessage|Tag") : s_("ChatMessage|Branch"),
value: Slack::Messenger::Util::LinkFormatter.format(ref_link),
short: true
},
{
title: s_("ChatMessage|Commit"),
value: Slack::Messenger::Util::LinkFormatter.format(commit_link),
short: true
}
]
fields << failed_stages_field if failed_stages.any?
fields << failed_jobs_field if failed_jobs.any?
fields << yaml_error_field if pipeline.has_yaml_errors?
fields
end
def message
s_("ChatMessage|%{project_link}: Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status} in %{duration}") %
{
project_link: project_link,
pipeline_link: pipeline_link,
ref_type: ref_type,
ref_link: ref_link,
user_combined_name: user_combined_name,
humanized_status: humanized_status,
duration: pretty_duration(duration)
}
end
def humanized_status
case status
when 'success'
detailed_status == "passed with warnings" ? s_("ChatMessage|has passed with warnings") : s_("ChatMessage|has passed")
when 'failed'
s_("ChatMessage|has failed")
else
status
end
end
def attachment_color
case status
when 'success'
detailed_status == 'passed with warnings' ? 'warning' : 'good'
else
'danger'
end
end
def ref_url
if ref_type == 'tag'
"#{project_url}/-/tags/#{ref}"
else
"#{project_url}/-/commits/#{ref}"
end
end
def ref_link
"[#{ref}](#{ref_url})"
end
def project_url
project.web_url
end
def project_link
"[#{project.name}](#{project_url})"
end
def pipeline_failed_jobs_url
"#{project_url}/-/pipelines/#{pipeline_id}/failures"
end
def pipeline_url
if failed_jobs.any?
pipeline_failed_jobs_url
else
"#{project_url}/-/pipelines/#{pipeline_id}"
end
end
def pipeline_link
"[##{pipeline_id}](#{pipeline_url})"
end
def job_url(job)
"#{project_url}/-/jobs/#{job[:id]}"
end
def job_link(job)
"[#{job[:name]}](#{job_url(job)})"
end
def failed_jobs_links
failed = failed_jobs.slice(0, MAX_VISIBLE_JOBS)
truncated = failed_jobs.slice(MAX_VISIBLE_JOBS, failed_jobs.size)
failed_links = failed.map { |job| job_link(job) }
unless truncated.blank?
failed_links << s_("ChatMessage|and [%{count} more](%{pipeline_failed_jobs_url})") % {
count: truncated.size,
pipeline_failed_jobs_url: pipeline_failed_jobs_url
}
end
failed_links.join(I18n.t(:'support.array.words_connector'))
end
def stage_link(stage)
# All stages link to the pipeline page
"[#{stage}](#{pipeline_url})"
end
def failed_stages_links
failed_stages.map { |s| stage_link(s) }.join(I18n.t(:'support.array.words_connector'))
end
def commit_url
Gitlab::UrlBuilder.build(commit)
end
def commit_link
"[#{commit.title}](#{commit_url})"
end
def author_url
return unless user && committer
Gitlab::UrlBuilder.build(committer)
end
end
end
end

View File

@ -0,0 +1,120 @@
# frozen_string_literal: true
module Integrations
module ChatMessage
class PushMessage < BaseMessage
attr_reader :after
attr_reader :before
attr_reader :commits
attr_reader :ref
attr_reader :ref_type
def initialize(params)
super
@after = params[:after]
@before = params[:before]
@commits = params.fetch(:commits, [])
@ref_type = Gitlab::Git.tag_ref?(params[:ref]) ? 'tag' : 'branch'
@ref = Gitlab::Git.ref_name(params[:ref])
end
def attachments
return [] if new_branch? || removed_branch?
return commit_messages if markdown
commit_message_attachments
end
def activity
{
title: humanized_action(short: true),
subtitle: "in #{project_link}",
text: compare_link,
image: user_avatar
}
end
private
def humanized_action(short: false)
action, ref_link, target_link = compose_action_details
text = [user_combined_name, action, ref_type, ref_link]
text << target_link unless short
text.join(' ')
end
def message
humanized_action
end
def format(string)
Slack::Messenger::Util::LinkFormatter.format(string)
end
def commit_messages
commits.map { |commit| compose_commit_message(commit) }.join("\n\n")
end
def commit_message_attachments
[{ text: format(commit_messages), color: attachment_color }]
end
def compose_commit_message(commit)
author = commit[:author][:name]
id = Commit.truncate_sha(commit[:id])
title = commit[:title]
url = commit[:url]
"[#{id}](#{url}): #{title} - #{author}"
end
def new_branch?
Gitlab::Git.blank_ref?(before)
end
def removed_branch?
Gitlab::Git.blank_ref?(after)
end
def ref_url
if ref_type == 'tag'
"#{project_url}/-/tags/#{ref}"
else
"#{project_url}/commits/#{ref}"
end
end
def compare_url
"#{project_url}/compare/#{before}...#{after}"
end
def ref_link
"[#{ref}](#{ref_url})"
end
def project_link
"[#{project_name}](#{project_url})"
end
def compare_link
"[Compare changes](#{compare_url})"
end
def compose_action_details
if new_branch?
['pushed new', ref_link, "to #{project_link}"]
elsif removed_branch?
['removed', ref, "from #{project_link}"]
else
['pushed to', ref_link, "of #{project_link} (#{compare_link})"]
end
end
def attachment_color
'#345'
end
end
end
end

View File

@ -0,0 +1,63 @@
# frozen_string_literal: true
module Integrations
module ChatMessage
class WikiPageMessage < BaseMessage
attr_reader :title
attr_reader :wiki_page_url
attr_reader :action
attr_reader :description
def initialize(params)
super
obj_attr = params[:object_attributes]
obj_attr = HashWithIndifferentAccess.new(obj_attr)
@title = obj_attr[:title]
@wiki_page_url = obj_attr[:url]
@description = obj_attr[:message]
@action =
case obj_attr[:action]
when "create"
"created"
when "update"
"edited"
end
end
def attachments
return description if markdown
description_message
end
def activity
{
title: "#{user_combined_name} #{action} #{wiki_page_link}",
subtitle: "in #{project_link}",
text: title,
image: user_avatar
}
end
private
def message
"#{user_combined_name} #{action} #{wiki_page_link} in #{project_link}: *#{title}*"
end
def description_message
[{ text: format(@description), color: attachment_color }]
end
def project_link
"[#{project_name}](#{project_url})"
end
def wiki_page_link
"[wiki page](#{wiki_page_url})"
end
end
end
end

View File

@ -117,11 +117,6 @@ class Packages::Package < ApplicationRecord
scope :without_nuget_temporary_name, -> { where.not(name: Packages::Nuget::TEMPORARY_PACKAGE_NAME) }
scope :has_version, -> { where.not(version: nil) }
scope :processed, -> do
where.not(package_type: :nuget).or(
where.not(name: Packages::Nuget::TEMPORARY_PACKAGE_NAME)
)
end
scope :preload_files, -> { preload(:package_files) }
scope :last_of_each_version, -> { where(id: all.select('MAX(id) AS id').group(:version)) }
scope :limit_recent, ->(limit) { order_created_desc.limit(limit) }

View File

@ -62,17 +62,16 @@ module Pages
}
end
# TODO: remove support for legacy storage in 14.3 https://gitlab.com/gitlab-org/gitlab/-/issues/328712
# we support this till 14.3 to allow people to still use legacy storage if something goes very wrong
# on self-hosted installations, and we'll need some time to fix it
def legacy_source
raise LegacyStorageDisabledError unless Feature.enabled?(:pages_serve_from_legacy_storage, default_enabled: true)
return unless ::Settings.pages.local_store.enabled
{
type: 'file',
path: File.join(project.full_path, 'public/')
}
rescue LegacyStorageDisabledError => e
Gitlab::ErrorTracking.track_exception(e, project_id: project.id)
nil
end
end
end

View File

@ -21,9 +21,7 @@ module Pages
project.pages_lookup_path(trim_prefix: trim_prefix, domain: domain)
end
# TODO: remove in https://gitlab.com/gitlab-org/gitlab/-/issues/297524
# source can only be nil if pages_serve_from_legacy_storage FF is disabled
# we can remove this filtering once we remove legacy storage
# TODO: remove in https://gitlab.com/gitlab-org/gitlab/-/issues/328715
paths = paths.select(&:source)
paths.sort_by(&:prefix).reverse

View File

@ -1,74 +0,0 @@
# frozen_string_literal: true
module ChatMessage
class AlertMessage < BaseMessage
attr_reader :title
attr_reader :alert_url
attr_reader :severity
attr_reader :events
attr_reader :status
attr_reader :started_at
def initialize(params)
@project_name = params[:project_name] || params.dig(:project, :path_with_namespace)
@project_url = params.dig(:project, :web_url) || params[:project_url]
@title = params.dig(:object_attributes, :title)
@alert_url = params.dig(:object_attributes, :url)
@severity = params.dig(:object_attributes, :severity)
@events = params.dig(:object_attributes, :events)
@status = params.dig(:object_attributes, :status)
@started_at = params.dig(:object_attributes, :started_at)
end
def attachments
[{
title: title,
title_link: alert_url,
color: attachment_color,
fields: attachment_fields
}]
end
def message
"Alert firing in #{project_name}"
end
private
def attachment_color
"#C95823"
end
def attachment_fields
[
{
title: "Severity",
value: severity.to_s.humanize,
short: true
},
{
title: "Events",
value: events,
short: true
},
{
title: "Status",
value: status.to_s.humanize,
short: true
},
{
title: "Start time",
value: format_time(started_at),
short: true
}
]
end
# This formats time into the following format
# April 23rd, 2020 1:06AM UTC
def format_time(time)
time = Time.zone.parse(time.to_s)
time.strftime("%B #{time.day.ordinalize}, %Y %l:%M%p %Z")
end
end
end

View File

@ -1,86 +0,0 @@
# frozen_string_literal: true
module ChatMessage
class BaseMessage
RELATIVE_LINK_REGEX = /!\[[^\]]*\]\((\/uploads\/[^\)]*)\)/.freeze
attr_reader :markdown
attr_reader :user_full_name
attr_reader :user_name
attr_reader :user_avatar
attr_reader :project_name
attr_reader :project_url
def initialize(params)
@markdown = params[:markdown] || false
@project_name = params[:project_name] || params.dig(:project, :path_with_namespace)
@project_url = params.dig(:project, :web_url) || params[:project_url]
@user_full_name = params.dig(:user, :name) || params[:user_full_name]
@user_name = params.dig(:user, :username) || params[:user_name]
@user_avatar = params.dig(:user, :avatar_url) || params[:user_avatar]
end
def user_combined_name
if user_full_name.present?
"#{user_full_name} (#{user_name})"
else
user_name
end
end
def summary
return message if markdown
format(message)
end
def pretext
summary
end
def fallback
format(message)
end
def attachments
raise NotImplementedError
end
def activity
raise NotImplementedError
end
private
def message
raise NotImplementedError
end
def format(string)
Slack::Messenger::Util::LinkFormatter.format(format_relative_links(string))
end
def format_relative_links(string)
string.gsub(RELATIVE_LINK_REGEX, "#{project_url}\\1")
end
def attachment_color
'#345'
end
def link(text, url)
"[#{text}](#{url})"
end
def pretty_duration(seconds)
parse_string =
if duration < 1.hour
'%M:%S'
else
'%H:%M:%S'
end
Time.at(seconds).utc.strftime(parse_string)
end
end
end

View File

@ -1,85 +0,0 @@
# frozen_string_literal: true
module ChatMessage
class DeploymentMessage < BaseMessage
attr_reader :commit_title
attr_reader :commit_url
attr_reader :deployable_id
attr_reader :deployable_url
attr_reader :environment
attr_reader :short_sha
attr_reader :status
attr_reader :user_url
def initialize(data)
super
@commit_title = data[:commit_title]
@commit_url = data[:commit_url]
@deployable_id = data[:deployable_id]
@deployable_url = data[:deployable_url]
@environment = data[:environment]
@short_sha = data[:short_sha]
@status = data[:status]
@user_url = data[:user_url]
end
def attachments
[{
text: "#{project_link} with job #{deployment_link} by #{user_link}\n#{commit_link}: #{commit_title}",
color: color
}]
end
def activity
{}
end
private
def message
if running?
"Starting deploy to #{environment}"
else
"Deploy to #{environment} #{humanized_status}"
end
end
def color
case status
when 'success'
'good'
when 'canceled'
'warning'
when 'failed'
'danger'
else
'#334455'
end
end
def project_link
link(project_name, project_url)
end
def deployment_link
link("##{deployable_id}", deployable_url)
end
def user_link
link(user_combined_name, user_url)
end
def commit_link
link(short_sha, commit_url)
end
def humanized_status
status == 'success' ? 'succeeded' : status
end
def running?
status == 'running'
end
end
end

View File

@ -1,72 +0,0 @@
# frozen_string_literal: true
module ChatMessage
class IssueMessage < BaseMessage
attr_reader :title
attr_reader :issue_iid
attr_reader :issue_url
attr_reader :action
attr_reader :state
attr_reader :description
def initialize(params)
super
obj_attr = params[:object_attributes]
obj_attr = HashWithIndifferentAccess.new(obj_attr)
@title = obj_attr[:title]
@issue_iid = obj_attr[:iid]
@issue_url = obj_attr[:url]
@action = obj_attr[:action]
@state = obj_attr[:state]
@description = obj_attr[:description] || ''
end
def attachments
return [] unless opened_issue?
return description if markdown
description_message
end
def activity
{
title: "Issue #{state} by #{user_combined_name}",
subtitle: "in #{project_link}",
text: issue_link,
image: user_avatar
}
end
private
def message
"[#{project_link}] Issue #{issue_link} #{state} by #{user_combined_name}"
end
def opened_issue?
action == 'open'
end
def description_message
[{
title: issue_title,
title_link: issue_url,
text: format(description),
color: '#C95823'
}]
end
def project_link
link(project_name, project_url)
end
def issue_link
link(issue_title, issue_url)
end
def issue_title
"#{Issue.reference_prefix}#{issue_iid} #{title}"
end
end
end

View File

@ -1,81 +0,0 @@
# frozen_string_literal: true
module ChatMessage
class MergeMessage < BaseMessage
attr_reader :merge_request_iid
attr_reader :source_branch
attr_reader :target_branch
attr_reader :action
attr_reader :state
attr_reader :title
def initialize(params)
super
obj_attr = params[:object_attributes]
obj_attr = HashWithIndifferentAccess.new(obj_attr)
@merge_request_iid = obj_attr[:iid]
@source_branch = obj_attr[:source_branch]
@target_branch = obj_attr[:target_branch]
@action = obj_attr[:action]
@state = obj_attr[:state]
@title = format_title(obj_attr[:title])
end
def attachments
[]
end
def activity
{
title: "Merge request #{state_or_action_text} by #{user_combined_name}",
subtitle: "in #{project_link}",
text: merge_request_link,
image: user_avatar
}
end
private
def format_title(title)
'*' + title.lines.first.chomp + '*'
end
def message
merge_request_message
end
def project_link
link(project_name, project_url)
end
def merge_request_message
"#{user_combined_name} #{state_or_action_text} merge request #{merge_request_link} in #{project_link}"
end
def merge_request_link
link(merge_request_title, merge_request_url)
end
def merge_request_title
"#{MergeRequest.reference_prefix}#{merge_request_iid} #{title}"
end
def merge_request_url
"#{project_url}/-/merge_requests/#{merge_request_iid}"
end
def state_or_action_text
case action
when 'approved', 'unapproved'
action
when 'approval'
'added their approval to'
when 'unapproval'
'removed their approval from'
else
state
end
end
end
end

View File

@ -1,84 +0,0 @@
# frozen_string_literal: true
module ChatMessage
class NoteMessage < BaseMessage
attr_reader :note
attr_reader :note_url
attr_reader :title
attr_reader :target
def initialize(params)
super
params = HashWithIndifferentAccess.new(params)
obj_attr = params[:object_attributes]
@note = obj_attr[:note]
@note_url = obj_attr[:url]
@target, @title = case obj_attr[:noteable_type]
when "Commit"
create_commit_note(params[:commit])
when "Issue"
create_issue_note(params[:issue])
when "MergeRequest"
create_merge_note(params[:merge_request])
when "Snippet"
create_snippet_note(params[:snippet])
end
end
def attachments
return note if markdown
description_message
end
def activity
{
title: "#{user_combined_name} #{link('commented on ' + target, note_url)}",
subtitle: "in #{project_link}",
text: formatted_title,
image: user_avatar
}
end
private
def message
"#{user_combined_name} #{link('commented on ' + target, note_url)} in #{project_link}: *#{formatted_title}*"
end
def format_title(title)
title.lines.first.chomp
end
def formatted_title
format_title(title)
end
def create_issue_note(issue)
["issue #{Issue.reference_prefix}#{issue[:iid]}", issue[:title]]
end
def create_commit_note(commit)
commit_sha = Commit.truncate_sha(commit[:id])
["commit #{commit_sha}", commit[:message]]
end
def create_merge_note(merge_request)
["merge request #{MergeRequest.reference_prefix}#{merge_request[:iid]}", merge_request[:title]]
end
def create_snippet_note(snippet)
["snippet #{Snippet.reference_prefix}#{snippet[:id]}", snippet[:title]]
end
def description_message
[{ text: format(note), color: attachment_color }]
end
def project_link
link(project_name, project_url)
end
end
end

View File

@ -1,265 +0,0 @@
# frozen_string_literal: true
module ChatMessage
class PipelineMessage < BaseMessage
MAX_VISIBLE_JOBS = 10
attr_reader :user
attr_reader :ref_type
attr_reader :ref
attr_reader :status
attr_reader :detailed_status
attr_reader :duration
attr_reader :finished_at
attr_reader :pipeline_id
attr_reader :failed_stages
attr_reader :failed_jobs
attr_reader :project
attr_reader :commit
attr_reader :committer
attr_reader :pipeline
def initialize(data)
super
@user = data[:user]
@user_name = data.dig(:user, :username) || 'API'
pipeline_attributes = data[:object_attributes]
@ref_type = pipeline_attributes[:tag] ? 'tag' : 'branch'
@ref = pipeline_attributes[:ref]
@status = pipeline_attributes[:status]
@detailed_status = pipeline_attributes[:detailed_status]
@duration = pipeline_attributes[:duration].to_i
@finished_at = pipeline_attributes[:finished_at] ? Time.parse(pipeline_attributes[:finished_at]).to_i : nil
@pipeline_id = pipeline_attributes[:id]
# Get list of jobs that have actually failed (after exhausting all retries)
@failed_jobs = actually_failed_jobs(Array(data[:builds]))
@failed_stages = @failed_jobs.map { |j| j[:stage] }.uniq
@project = Project.find(data[:project][:id])
@commit = project.commit_by(oid: data[:commit][:id])
@committer = commit.committer
@pipeline = Ci::Pipeline.find(pipeline_id)
end
def pretext
''
end
def attachments
return message if markdown
[{
fallback: format(message),
color: attachment_color,
author_name: user_combined_name,
author_icon: user_avatar,
author_link: author_url,
title: s_("ChatMessage|Pipeline #%{pipeline_id} %{humanized_status} in %{duration}") %
{
pipeline_id: pipeline_id,
humanized_status: humanized_status,
duration: pretty_duration(duration)
},
title_link: pipeline_url,
fields: attachments_fields,
footer: project.name,
footer_icon: project.avatar_url(only_path: false),
ts: finished_at
}]
end
def activity
{
title: s_("ChatMessage|Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status}") %
{
pipeline_link: pipeline_link,
ref_type: ref_type,
ref_link: ref_link,
user_combined_name: user_combined_name,
humanized_status: humanized_status
},
subtitle: s_("ChatMessage|in %{project_link}") % { project_link: project_link },
text: s_("ChatMessage|in %{duration}") % { duration: pretty_duration(duration) },
image: user_avatar || ''
}
end
private
def actually_failed_jobs(builds)
succeeded_job_names = builds.map { |b| b[:name] if b[:status] == 'success' }.compact.uniq
failed_jobs = builds.select do |build|
# Select jobs which doesn't have a successful retry
build[:status] == 'failed' && !succeeded_job_names.include?(build[:name])
end
failed_jobs.uniq { |job| job[:name] }.reverse
end
def failed_stages_field
{
title: s_("ChatMessage|Failed stage").pluralize(failed_stages.length),
value: Slack::Messenger::Util::LinkFormatter.format(failed_stages_links),
short: true
}
end
def failed_jobs_field
{
title: s_("ChatMessage|Failed job").pluralize(failed_jobs.length),
value: Slack::Messenger::Util::LinkFormatter.format(failed_jobs_links),
short: true
}
end
def yaml_error_field
{
title: s_("ChatMessage|Invalid CI config YAML file"),
value: pipeline.yaml_errors,
short: false
}
end
def attachments_fields
fields = [
{
title: ref_type == "tag" ? s_("ChatMessage|Tag") : s_("ChatMessage|Branch"),
value: Slack::Messenger::Util::LinkFormatter.format(ref_link),
short: true
},
{
title: s_("ChatMessage|Commit"),
value: Slack::Messenger::Util::LinkFormatter.format(commit_link),
short: true
}
]
fields << failed_stages_field if failed_stages.any?
fields << failed_jobs_field if failed_jobs.any?
fields << yaml_error_field if pipeline.has_yaml_errors?
fields
end
def message
s_("ChatMessage|%{project_link}: Pipeline %{pipeline_link} of %{ref_type} %{ref_link} by %{user_combined_name} %{humanized_status} in %{duration}") %
{
project_link: project_link,
pipeline_link: pipeline_link,
ref_type: ref_type,
ref_link: ref_link,
user_combined_name: user_combined_name,
humanized_status: humanized_status,
duration: pretty_duration(duration)
}
end
def humanized_status
case status
when 'success'
detailed_status == "passed with warnings" ? s_("ChatMessage|has passed with warnings") : s_("ChatMessage|has passed")
when 'failed'
s_("ChatMessage|has failed")
else
status
end
end
def attachment_color
case status
when 'success'
detailed_status == 'passed with warnings' ? 'warning' : 'good'
else
'danger'
end
end
def ref_url
if ref_type == 'tag'
"#{project_url}/-/tags/#{ref}"
else
"#{project_url}/-/commits/#{ref}"
end
end
def ref_link
"[#{ref}](#{ref_url})"
end
def project_url
project.web_url
end
def project_link
"[#{project.name}](#{project_url})"
end
def pipeline_failed_jobs_url
"#{project_url}/-/pipelines/#{pipeline_id}/failures"
end
def pipeline_url
if failed_jobs.any?
pipeline_failed_jobs_url
else
"#{project_url}/-/pipelines/#{pipeline_id}"
end
end
def pipeline_link
"[##{pipeline_id}](#{pipeline_url})"
end
def job_url(job)
"#{project_url}/-/jobs/#{job[:id]}"
end
def job_link(job)
"[#{job[:name]}](#{job_url(job)})"
end
def failed_jobs_links
failed = failed_jobs.slice(0, MAX_VISIBLE_JOBS)
truncated = failed_jobs.slice(MAX_VISIBLE_JOBS, failed_jobs.size)
failed_links = failed.map { |job| job_link(job) }
unless truncated.blank?
failed_links << s_("ChatMessage|and [%{count} more](%{pipeline_failed_jobs_url})") % {
count: truncated.size,
pipeline_failed_jobs_url: pipeline_failed_jobs_url
}
end
failed_links.join(I18n.translate(:'support.array.words_connector'))
end
def stage_link(stage)
# All stages link to the pipeline page
"[#{stage}](#{pipeline_url})"
end
def failed_stages_links
failed_stages.map { |s| stage_link(s) }.join(I18n.translate(:'support.array.words_connector'))
end
def commit_url
Gitlab::UrlBuilder.build(commit)
end
def commit_link
"[#{commit.title}](#{commit_url})"
end
def author_url
return unless user && committer
Gitlab::UrlBuilder.build(committer)
end
end
end

View File

@ -1,118 +0,0 @@
# frozen_string_literal: true
module ChatMessage
class PushMessage < BaseMessage
attr_reader :after
attr_reader :before
attr_reader :commits
attr_reader :ref
attr_reader :ref_type
def initialize(params)
super
@after = params[:after]
@before = params[:before]
@commits = params.fetch(:commits, [])
@ref_type = Gitlab::Git.tag_ref?(params[:ref]) ? 'tag' : 'branch'
@ref = Gitlab::Git.ref_name(params[:ref])
end
def attachments
return [] if new_branch? || removed_branch?
return commit_messages if markdown
commit_message_attachments
end
def activity
{
title: humanized_action(short: true),
subtitle: "in #{project_link}",
text: compare_link,
image: user_avatar
}
end
private
def humanized_action(short: false)
action, ref_link, target_link = compose_action_details
text = [user_combined_name, action, ref_type, ref_link]
text << target_link unless short
text.join(' ')
end
def message
humanized_action
end
def format(string)
Slack::Messenger::Util::LinkFormatter.format(string)
end
def commit_messages
commits.map { |commit| compose_commit_message(commit) }.join("\n\n")
end
def commit_message_attachments
[{ text: format(commit_messages), color: attachment_color }]
end
def compose_commit_message(commit)
author = commit[:author][:name]
id = Commit.truncate_sha(commit[:id])
title = commit[:title]
url = commit[:url]
"[#{id}](#{url}): #{title} - #{author}"
end
def new_branch?
Gitlab::Git.blank_ref?(before)
end
def removed_branch?
Gitlab::Git.blank_ref?(after)
end
def ref_url
if ref_type == 'tag'
"#{project_url}/-/tags/#{ref}"
else
"#{project_url}/commits/#{ref}"
end
end
def compare_url
"#{project_url}/compare/#{before}...#{after}"
end
def ref_link
"[#{ref}](#{ref_url})"
end
def project_link
"[#{project_name}](#{project_url})"
end
def compare_link
"[Compare changes](#{compare_url})"
end
def compose_action_details
if new_branch?
['pushed new', ref_link, "to #{project_link}"]
elsif removed_branch?
['removed', ref, "from #{project_link}"]
else
['pushed to', ref_link, "of #{project_link} (#{compare_link})"]
end
end
def attachment_color
'#345'
end
end
end

View File

@ -1,61 +0,0 @@
# frozen_string_literal: true
module ChatMessage
class WikiPageMessage < BaseMessage
attr_reader :title
attr_reader :wiki_page_url
attr_reader :action
attr_reader :description
def initialize(params)
super
obj_attr = params[:object_attributes]
obj_attr = HashWithIndifferentAccess.new(obj_attr)
@title = obj_attr[:title]
@wiki_page_url = obj_attr[:url]
@description = obj_attr[:message]
@action =
case obj_attr[:action]
when "create"
"created"
when "update"
"edited"
end
end
def attachments
return description if markdown
description_message
end
def activity
{
title: "#{user_combined_name} #{action} #{wiki_page_link}",
subtitle: "in #{project_link}",
text: title,
image: user_avatar
}
end
private
def message
"#{user_combined_name} #{action} #{wiki_page_link} in #{project_link}: *#{title}*"
end
def description_message
[{ text: format(@description), color: attachment_color }]
end
def project_link
"[#{project_name}](#{project_url})"
end
def wiki_page_link
"[wiki page](#{wiki_page_url})"
end
end
end

View File

@ -185,19 +185,19 @@ class ChatNotificationService < Integration
def get_message(object_kind, data)
case object_kind
when "push", "tag_push"
ChatMessage::PushMessage.new(data) if notify_for_ref?(data)
Integrations::ChatMessage::PushMessage.new(data) if notify_for_ref?(data)
when "issue"
ChatMessage::IssueMessage.new(data) unless update?(data)
Integrations::ChatMessage::IssueMessage.new(data) unless update?(data)
when "merge_request"
ChatMessage::MergeMessage.new(data) unless update?(data)
Integrations::ChatMessage::MergeMessage.new(data) unless update?(data)
when "note"
ChatMessage::NoteMessage.new(data)
Integrations::ChatMessage::NoteMessage.new(data)
when "pipeline"
ChatMessage::PipelineMessage.new(data) if should_pipeline_be_notified?(data)
Integrations::ChatMessage::PipelineMessage.new(data) if should_pipeline_be_notified?(data)
when "wiki_page"
ChatMessage::WikiPageMessage.new(data)
Integrations::ChatMessage::WikiPageMessage.new(data)
when "deployment"
ChatMessage::DeploymentMessage.new(data)
Integrations::ChatMessage::DeploymentMessage.new(data)
end
end

View File

@ -39,7 +39,7 @@ class SlackService < ChatNotificationService
end
def get_message(object_kind, data)
return ChatMessage::AlertMessage.new(data) if object_kind == 'alert'
return Integrations::ChatMessage::AlertMessage.new(data) if object_kind == 'alert'
super
end

View File

@ -26,25 +26,13 @@ module Issuable
end
def delete_todos(actor, issuable)
if Feature.enabled?(:destroy_issuable_todos_async, actor, default_enabled: :yaml)
TodosDestroyer::DestroyedIssuableWorker
.perform_async(issuable.id, issuable.class.name)
else
TodosDestroyer::DestroyedIssuableWorker
.new
.perform(issuable.id, issuable.class.name)
end
TodosDestroyer::DestroyedIssuableWorker
.perform_async(issuable.id, issuable.class.name)
end
def delete_label_links(actor, issuable)
if Feature.enabled?(:destroy_issuable_label_links_async, actor, default_enabled: :yaml)
Issuable::LabelLinksDestroyWorker
.perform_async(issuable.id, issuable.class.name)
else
Issuable::LabelLinksDestroyWorker
.new
.perform(issuable.id, issuable.class.name)
end
Issuable::LabelLinksDestroyWorker
.perform_async(issuable.id, issuable.class.name)
end
end
end

View File

@ -16,12 +16,17 @@ module Spam
def execute
spamcheck_result = nil
spamcheck_attribs = {}
spamcheck_error = false
external_spam_check_round_trip_time = Benchmark.realtime do
spamcheck_result, spamcheck_attribs = spamcheck_verdict
spamcheck_result, spamcheck_attribs, spamcheck_error = spamcheck_verdict
end
# assign result to a var and log it before reassigning to nil when monitorMode is true
label = spamcheck_error ? 'ERROR' : spamcheck_result.to_s.upcase
histogram.observe( { result: label }, external_spam_check_round_trip_time )
# assign result to a var for logging it before reassigning to nil when monitorMode is true
original_spamcheck_result = spamcheck_result
spamcheck_result = nil if spamcheck_attribs&.fetch("monitorMode", "false") == "true"
@ -83,8 +88,9 @@ module Spam
end
rescue StandardError => e
Gitlab::ErrorTracking.log_exception(e)
# Default to ALLOW if any errors occur
[ALLOW, attribs]
[ALLOW, attribs, true]
end
end
@ -95,5 +101,9 @@ module Spam
def logger
@logger ||= Gitlab::AppJsonLogger.build
end
def histogram
@histogram ||= Gitlab::Metrics.histogram(:gitlab_spamcheck_request_duration_seconds, 'Request duration to the anti-spam service')
end
end
end

View File

@ -1,2 +1,2 @@
%p
= _('%{username} changed the draft status of merge request %{mr_reference}' % {username: sanitize_name(@updated_by_user.name), mr_reference: @merge_request.to_reference })
%p= html_escape(_('%{username} changed the draft status of merge request %{mr_link}')) % { username: link_to(@updated_by_user.name, user_url(@updated_by_user)),
mr_link: merge_request_reference_link(@merge_request) }

View File

@ -6,7 +6,7 @@
- issuable_mr = @issuable_meta_data[issuable.id].merge_requests_count
- if issuable_mr > 0
%li.issuable-mr.gl-display-none.gl-sm-display-block.has-tooltip{ title: _('Related merge requests') }
%li.issuable-mr.gl-display-none.gl-sm-display-block.has-tooltip{ title: _('Related merge requests'), data: { testid: 'merge-requests' } }
= sprite_icon('merge-request', css_class: "gl-vertical-align-middle")
= issuable_mr

View File

@ -0,0 +1,5 @@
---
title: Change wording for design management upload
merge_request: 61782
author:
type: other

View File

@ -0,0 +1,5 @@
---
title: Remove pages_update_legacy_storage feature flag
merge_request: 60005
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Remove pages_serve_from_legacy_storage feature flag
merge_request: 60010
author:
type: added

View File

@ -0,0 +1,5 @@
---
title: Remove issuable destroy service related FFs
merge_request: 61764
author:
type: other

View File

@ -0,0 +1,5 @@
---
title: Prepare devops adoption database structure for migration
merge_request: 60733
author:
type: other

View File

@ -0,0 +1,5 @@
---
title: Observe limit to hours setting in timelog report
merge_request: 61849
author: Lee Tickett @leetickett
type: added

View File

@ -0,0 +1,5 @@
---
title: Add duplicated gin trigram index on notes table (note) to replace existing
merge_request: 61430
author:
type: performance

View File

@ -0,0 +1,5 @@
---
title: Add link to email notifying of MR changing draft status
merge_request: 61891
author:
type: changed

View File

@ -0,0 +1,5 @@
---
title: Apply rate-limit cache to branches endpoint
merge_request: 61723
author:
type: performance

View File

@ -0,0 +1,5 @@
---
title: Send in-product marketing email usage data
merge_request: 56752
author:
type: changed

View File

@ -5,4 +5,4 @@ rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/330876
milestone: '13.12'
type: development
group: group::source code
default_enabled: false
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: destroy_issuable_label_links_async
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/60487
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325689
milestone: '13.12'
type: development
group: group::code review
default_enabled: false

View File

@ -1,8 +0,0 @@
---
name: destroy_issuable_todos_async
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/57830
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/325689
milestone: '13.11'
type: development
group: group::code review
default_enabled: false

View File

@ -1,8 +0,0 @@
---
name: pages_serve_from_legacy_storage
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297228
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/297524
milestone: '13.8'
type: development
group: group::release
default_enabled: true

View File

@ -1,8 +0,0 @@
---
name: pages_update_legacy_storage
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/50683
rollout_issue_url: https://gitlab.com/gitlab-org/gitlab/-/issues/296138
milestone: '13.9'
type: development
group: group::release
default_enabled: true

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_create_0_sent
name: "count_sent_first_email_of_the_create_track_for_in_product_marketing_emails"
description: Total sent emails of the create track's first email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,22 @@
---
key_path: counts.in_product_marketing_email_create_0_cta_clicked
name: "count_clicks_on_the_first_email_of_the_create_track_for_in_product_marketing_emails"
description: Total clicks on the create track's first email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_create_1_sent
name: "count_sent_second_email_of_the_create_track_for_in_product_marketing_emails"
description: Total sent emails of the create track's second email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,22 @@
---
key_path: counts.in_product_marketing_email_create_1_cta_clicked
name: "count_clicks_on_the_second_email_of_the_create_track_for_in_product_marketing_emails"
description: Total clicks on the create track's second email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_create_2_sent
name: "count_sent_third_email_of_the_create_track_for_in_product_marketing_emails"
description: Total sent emails of the create track's third email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_create_2_cta_clicked
name: "count_clicks_on_the_third_email_of_the_create_track_for_in_product_marketing_emails"
description: Total clicks on the create track's third email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_verify_0_sent
name: "count_sent_first_email_of_the_verify_track_for_in_product_marketing_emails"
description: Total sent emails of the verify track's first email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_verify_0_cta_clicked
name: "count_clicks_on_the_first_email_of_the_verify_track_for_in_product_marketing_emails"
description: Total clicks on the verify track's first email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_verify_1_sent
name: "count_sent_second_email_of_the_verify_track_for_in_product_marketing_emails"
description: Total sent emails of the verify track's second email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,22 @@
---
key_path: counts.in_product_marketing_email_verify_1_cta_clicked
name: "count_clicks_on_the_second_email_of_the_verify_track_for_in_product_marketing_emails"
description: Total clicks on the verify track's second email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_verify_2_sent
name: "count_sent_third_email_of_the_verify_track_for_in_product_marketing_emails"
description: Total sent emails of the verify track's third email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_verify_2_cta_clicked
name: "count_clicks_on_the_third_email_of_the_verify_track_for_in_product_marketing_emails"
description: Total clicks on the verify track's third email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_trial_0_sent
name: "count_sent_first_email_of_the_trial_track_for_in_product_marketing_emails"
description: Total sent emails of the trial track's first email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_trial_0_cta_clicked
name: "count_clicks_on_the_first_email_of_the_trial_track_for_in_product_marketing_emails"
description: Total clicks on the verify trial's first email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_trial_1_sent
name: "count_sent_second_email_of_the_trial_track_for_in_product_marketing_emails"
description: Total sent emails of the trial track's second email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,22 @@
---
key_path: counts.in_product_marketing_email_trial_1_cta_clicked
name: "count_clicks_on_the_second_email_of_the_trial_track_for_in_product_marketing_emails"
description: Total clicks on the trial track's second email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_trial_2_sent
name: "count_sent_third_email_of_the_trial_track_for_in_product_marketing_emails"
description: Total sent emails of the trial track's third email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_trial_2_cta_clicked
name: "count_clicks_on_the_third_email_of_the_trial_track_for_in_product_marketing_emails"
description: Total clicks on the trial track's third email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_team_0_sent
name: "count_sent_first_email_of_the_trial_team_for_in_product_marketing_emails"
description: Total sent emails of the team track's first email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_team_0_cta_clicked
name: "count_clicks_on_the_first_email_of_the_team_track_for_in_product_marketing_emails"
description: Total clicks on the team track's first email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_team_1_sent
name: "count_sent_second_email_of_the_team_track_for_in_product_marketing_emails"
description: Total sent emails of the team track's second email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,22 @@
---
key_path: counts.in_product_marketing_email_team_1_cta_clicked
name: "count_clicks_on_the_second_email_of_the_team_track_for_in_product_marketing_emails"
description: Total clicks on the team track's second email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_team_2_sent
name: "count_sent_third_email_of_the_team_track_for_in_product_marketing_emails"
description: Total sent emails of the team track's third email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,21 @@
---
key_path: counts.in_product_marketing_email_team_2_cta_clicked
name: "count_clicks_on_the_third_email_of_the_team_track_for_in_product_marketing_emails"
description: Total clicks on the team track's third email
product_section:
product_stage: growth
product_group: group::activation
product_category: onboarding
value_type: number
status: implemented
milestone: "13.12"
introduced_by_url: https://gitlab.com/gitlab-org/gitlab/-/merge_requests/56752
time_frame: all
data_source: database
distribution:
- ce
- ee
tier:
- free
- premium
- ultimate

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddSnapshotNamespaceId < ActiveRecord::Migration[6.0]
def change
add_column :analytics_devops_adoption_snapshots, :namespace_id, :integer
end
end

View File

@ -0,0 +1,7 @@
# frozen_string_literal: true
class AddDisplayNamespaceIdToSegments < ActiveRecord::Migration[6.0]
def change
add_column :analytics_devops_adoption_segments, :display_namespace_id, :integer
end
end

View File

@ -0,0 +1,32 @@
# frozen_string_literal: true
class AddDevopsAdoptionIndexes < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
SEGMENTS_INDEX_NAME = 'idx_devops_adoption_segments_namespaces_pair'
SNAPSHOT_END_TIME_INDEX_NAME = 'idx_devops_adoption_segments_namespace_end_time'
SNAPSHOT_RECORDED_AT_INDEX_NAME = 'idx_devops_adoption_segments_namespace_recorded_at'
def up
add_concurrent_index :analytics_devops_adoption_snapshots, [:namespace_id, :end_time],
name: SNAPSHOT_END_TIME_INDEX_NAME
add_concurrent_index :analytics_devops_adoption_snapshots, [:namespace_id, :recorded_at],
name: SNAPSHOT_RECORDED_AT_INDEX_NAME
add_concurrent_index :analytics_devops_adoption_segments, [:display_namespace_id, :namespace_id],
unique: true, name: SEGMENTS_INDEX_NAME
add_concurrent_foreign_key :analytics_devops_adoption_snapshots, :namespaces, column: :namespace_id
add_concurrent_foreign_key :analytics_devops_adoption_segments, :namespaces, column: :display_namespace_id
end
def down
remove_foreign_key :analytics_devops_adoption_segments, :namespaces, column: :display_namespace_id
remove_foreign_key :analytics_devops_adoption_snapshots, :namespaces, column: :namespace_id
remove_concurrent_index_by_name :analytics_devops_adoption_segments, SEGMENTS_INDEX_NAME
remove_concurrent_index_by_name :analytics_devops_adoption_snapshots, SNAPSHOT_RECORDED_AT_INDEX_NAME
remove_concurrent_index_by_name :analytics_devops_adoption_snapshots, SNAPSHOT_END_TIME_INDEX_NAME
end
end

View File

@ -0,0 +1,18 @@
# frozen_string_literal: true
class RemoveObsoleteSegmentsField < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
disable_ddl_transaction!
def up
with_lock_retries do
remove_column :analytics_devops_adoption_segments, :name
end
end
def down
add_column :analytics_devops_adoption_segments, :name, :text
add_text_limit :analytics_devops_adoption_segments, :name, 255
end
end

View File

@ -0,0 +1,16 @@
# frozen_string_literal: true
class CopyAdoptionSnapshotNamespace < ActiveRecord::Migration[6.0]
def up
execute <<-SQL
UPDATE analytics_devops_adoption_snapshots snapshots
SET namespace_id = segments.namespace_id
FROM analytics_devops_adoption_segments segments
WHERE snapshots.namespace_id IS NULL AND segments.id = snapshots.segment_id
SQL
end
def down
execute 'UPDATE analytics_devops_adoption_snapshots SET namespace_id = NULL'
end
end

View File

@ -0,0 +1,14 @@
# frozen_string_literal: true
class CopyAdoptionSegmentsNamespace < ActiveRecord::Migration[6.0]
def up
execute <<-SQL
UPDATE analytics_devops_adoption_segments SET display_namespace_id = namespace_id
WHERE display_namespace_id IS NULL
SQL
end
def down
execute 'UPDATE analytics_devops_adoption_segments SET display_namespace_id = NULL'
end
end

View File

@ -0,0 +1,26 @@
# frozen_string_literal: true
# See https://docs.gitlab.com/ee/development/migration_style_guide.html
# for more information on how to write migrations for GitLab.
class CreateIndexOnNotesNote < ActiveRecord::Migration[6.0]
include Gitlab::Database::MigrationHelpers
DUPLICATE_INDEX_NAME = 'index_notes_on_note_gin_trigram'
CURRENT_INDEX_NAME = 'index_notes_on_note_trigram'
disable_ddl_transaction!
# https://gitlab.com/gitlab-org/gitlab/-/issues/218410#note_565624409
# We are having troubles with the index, and some inserts are taking a long time
# so in this migration we are recreating the index
def up
add_concurrent_index :notes, :note, name: DUPLICATE_INDEX_NAME, using: :gin, opclass: :gin_trgm_ops
remove_concurrent_index_by_name :notes, CURRENT_INDEX_NAME
end
def down
add_concurrent_index :notes, :note, name: CURRENT_INDEX_NAME, using: :gin, opclass: :gin_trgm_ops
remove_concurrent_index_by_name :notes, DUPLICATE_INDEX_NAME
end
end

View File

@ -0,0 +1 @@
476dc70eae87ad3ee30e6be8c1afb4a2aec23a09b96daba2afbd9c4e2edb12b9

View File

@ -0,0 +1 @@
ebdeb56647f3a7ff5620141833c90b796a9ddfed39234bcf8063ca5b3df6c1f3

View File

@ -0,0 +1 @@
7f6862205e8c315da8433083fc5391f8889951f62d466e0048063322a46f9cc7

View File

@ -0,0 +1 @@
c4a4b214f15a1a8d7f6832782d50077189281ca9a9b1b746a0a3bc3af4a47e3c

View File

@ -0,0 +1 @@
77e2b8c1c6054a80122f97dda1e843149fefb7bf6694fdfa897d691d61162d81

View File

@ -0,0 +1 @@
c5fe6f74822168599ad5069bb7c793ec96a4bba99d15ad29cb161ef24291b56d

View File

@ -0,0 +1 @@
2d11da499f49964f37cc0a2c541cf58182416ae7b6b0e762a135b327099de1a4

View File

@ -9103,12 +9103,11 @@ ALTER SEQUENCE analytics_devops_adoption_segment_selections_id_seq OWNED BY anal
CREATE TABLE analytics_devops_adoption_segments (
id bigint NOT NULL,
name text,
last_recorded_at timestamp with time zone,
created_at timestamp with time zone NOT NULL,
updated_at timestamp with time zone NOT NULL,
namespace_id integer,
CONSTRAINT check_4be7a006fd CHECK ((char_length(name) <= 255))
display_namespace_id integer
);
CREATE SEQUENCE analytics_devops_adoption_segments_id_seq
@ -9133,7 +9132,8 @@ CREATE TABLE analytics_devops_adoption_snapshots (
security_scan_succeeded boolean NOT NULL,
end_time timestamp with time zone NOT NULL,
total_projects_count integer,
code_owners_used_count integer
code_owners_used_count integer,
namespace_id integer
);
CREATE SEQUENCE analytics_devops_adoption_snapshots_id_seq
@ -22133,6 +22133,12 @@ CREATE INDEX idx_container_repositories_on_exp_cleanup_status_and_start_date ON
CREATE INDEX idx_deployment_clusters_on_cluster_id_and_kubernetes_namespace ON deployment_clusters USING btree (cluster_id, kubernetes_namespace);
CREATE INDEX idx_devops_adoption_segments_namespace_end_time ON analytics_devops_adoption_snapshots USING btree (namespace_id, end_time);
CREATE INDEX idx_devops_adoption_segments_namespace_recorded_at ON analytics_devops_adoption_snapshots USING btree (namespace_id, recorded_at);
CREATE UNIQUE INDEX idx_devops_adoption_segments_namespaces_pair ON analytics_devops_adoption_segments USING btree (display_namespace_id, namespace_id);
CREATE INDEX idx_eaprpb_external_approval_rule_id ON external_approval_rules_protected_branches USING btree (external_approval_rule_id);
CREATE INDEX idx_elastic_reindexing_slices_on_elastic_reindexing_subtask_id ON elastic_reindexing_slices USING btree (elastic_reindexing_subtask_id);
@ -23667,7 +23673,7 @@ CREATE INDEX index_notes_on_discussion_id ON notes USING btree (discussion_id);
CREATE INDEX index_notes_on_line_code ON notes USING btree (line_code);
CREATE INDEX index_notes_on_note_trigram ON notes USING gin (note gin_trgm_ops);
CREATE INDEX index_notes_on_note_gin_trigram ON notes USING gin (note gin_trgm_ops);
CREATE INDEX index_notes_on_noteable_id_and_noteable_type_and_system ON notes USING btree (noteable_id, noteable_type, system);
@ -25224,6 +25230,9 @@ ALTER TABLE ONLY project_features
ALTER TABLE ONLY ci_pipelines
ADD CONSTRAINT fk_190998ef09 FOREIGN KEY (external_pull_request_id) REFERENCES external_pull_requests(id) ON DELETE SET NULL;
ALTER TABLE ONLY analytics_devops_adoption_segments
ADD CONSTRAINT fk_190a24754d FOREIGN KEY (display_namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY user_details
ADD CONSTRAINT fk_190e4fcc88 FOREIGN KEY (provisioned_by_group_id) REFERENCES namespaces(id) ON DELETE SET NULL;
@ -25440,6 +25449,9 @@ ALTER TABLE ONLY users
ALTER TABLE ONLY geo_event_log
ADD CONSTRAINT fk_78a6492f68 FOREIGN KEY (repository_updated_event_id) REFERENCES geo_repository_updated_events(id) ON DELETE CASCADE;
ALTER TABLE ONLY analytics_devops_adoption_snapshots
ADD CONSTRAINT fk_78c9eac821 FOREIGN KEY (namespace_id) REFERENCES namespaces(id) ON DELETE CASCADE;
ALTER TABLE ONLY lists
ADD CONSTRAINT fk_7a5553d60f FOREIGN KEY (label_id) REFERENCES labels(id) ON DELETE CASCADE;

View File

@ -129,6 +129,7 @@ The following metrics are available:
| `pipeline_graph_links_per_job_ratio` | Histogram | 13.9 | Ratio of links to job per graph | |
| `gitlab_ci_pipeline_security_orchestration_policy_processing_duration_seconds` | Histogram | 13.12 | Time in seconds it takes to process Security Policies in CI/CD pipeline | |
| `gitlab_ci_difference_live_vs_actual_minutes` | Histogram | 13.12 | Difference between CI minute consumption counted while jobs were running (live) vs when jobs are complete (actual). Used to enforce CI minute consumption limits on long running jobs. | `plan` |
| `gitlab_spamcheck_request_duration_seconds` | Histogram | 13.12 | The duration for requests between Rails and the anti-spam engine | |
## Metrics controlled by a feature flag

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