Add latest changes from gitlab-org/gitlab@master
This commit is contained in:
parent
b27cd9649f
commit
aeda2f64b4
|
@ -1 +1 @@
|
|||
8b033b1763e80468b4f11a572e1425d1064692e2
|
||||
40e19e808a320ce357c2ce5edfa3cf09def58477
|
||||
|
|
|
@ -27,7 +27,8 @@ class PendingTodosFinder
|
|||
todos = by_target_id(todos)
|
||||
todos = by_target_type(todos)
|
||||
todos = by_discussion(todos)
|
||||
by_commit_id(todos)
|
||||
todos = by_commit_id(todos)
|
||||
by_action(todos)
|
||||
end
|
||||
|
||||
def by_project(todos)
|
||||
|
@ -69,4 +70,10 @@ class PendingTodosFinder
|
|||
todos
|
||||
end
|
||||
end
|
||||
|
||||
def by_action(todos)
|
||||
return todos if params[:action].blank?
|
||||
|
||||
todos.for_action(params[:action])
|
||||
end
|
||||
end
|
||||
|
|
|
@ -1152,8 +1152,6 @@ class MergeRequest < ApplicationRecord
|
|||
|
||||
# rubocop: disable CodeReuse/ServiceClass
|
||||
def mergeable_state?(skip_ci_check: false, skip_discussions_check: false)
|
||||
return false unless open?
|
||||
|
||||
if Feature.enabled?(:improved_mergeability_checks, self.project, default_enabled: :yaml)
|
||||
additional_checks = MergeRequests::Mergeability::RunChecksService.new(
|
||||
merge_request: self,
|
||||
|
@ -1164,6 +1162,7 @@ class MergeRequest < ApplicationRecord
|
|||
)
|
||||
additional_checks.execute.all?(&:success?)
|
||||
else
|
||||
return false unless open?
|
||||
return false if draft?
|
||||
return false if broken?
|
||||
return false unless skip_discussions_check || mergeable_discussions_state?
|
||||
|
|
|
@ -34,6 +34,8 @@ class Todo < ApplicationRecord
|
|||
ATTENTION_REQUESTED => :attention_requested
|
||||
}.freeze
|
||||
|
||||
ACTIONS_MULTIPLE_ALLOWED = [Todo::MENTIONED, Todo::DIRECTLY_ADDRESSED].freeze
|
||||
|
||||
belongs_to :author, class_name: "User"
|
||||
belongs_to :note
|
||||
belongs_to :project
|
||||
|
|
|
@ -22,9 +22,7 @@ module AlertManagement
|
|||
return result unless result.success?
|
||||
|
||||
issue = result.payload[:issue]
|
||||
update_title_for(issue)
|
||||
|
||||
SystemNoteService.new_alert_issue(alert, issue, user)
|
||||
perform_after_create_tasks(issue)
|
||||
|
||||
result
|
||||
end
|
||||
|
@ -56,6 +54,12 @@ module AlertManagement
|
|||
issue.update!(title: "#{DEFAULT_INCIDENT_TITLE} #{issue.iid}")
|
||||
end
|
||||
|
||||
def perform_after_create_tasks(issue)
|
||||
update_title_for(issue)
|
||||
|
||||
SystemNoteService.new_alert_issue(alert, issue, user)
|
||||
end
|
||||
|
||||
def error(message, issue = nil)
|
||||
ServiceResponse.error(payload: { issue: issue }, message: message)
|
||||
end
|
||||
|
@ -75,3 +79,5 @@ module AlertManagement
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
AlertManagement::CreateAlertIssueService.prepend_mod
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
module MergeRequests
|
||||
module Mergeability
|
||||
class CheckOpenStatusService < CheckBaseService
|
||||
def execute
|
||||
if merge_request.open?
|
||||
success
|
||||
else
|
||||
failure
|
||||
end
|
||||
end
|
||||
|
||||
def skip?
|
||||
false
|
||||
end
|
||||
|
||||
def cacheable?
|
||||
false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
|
@ -7,6 +7,7 @@ module MergeRequests
|
|||
# We want to have the cheapest checks first in the list,
|
||||
# that way we can fail fast before running the more expensive ones
|
||||
CHECKS = [
|
||||
CheckOpenStatusService,
|
||||
CheckDraftStatusService,
|
||||
CheckBrokenStatusService,
|
||||
CheckDiscussionsStatusService,
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#
|
||||
class TodoService
|
||||
include Gitlab::Utils::UsageData
|
||||
|
||||
# When create an issue we should:
|
||||
#
|
||||
# * create a todo for assignee if issue is assigned
|
||||
|
@ -229,8 +230,24 @@ class TodoService
|
|||
|
||||
return if users.empty?
|
||||
|
||||
users_with_pending_todos = pending_todos(users, attributes).distinct_user_ids
|
||||
users.reject! { |user| users_with_pending_todos.include?(user.id) && Feature.disabled?(:multiple_todos, user) }
|
||||
users_single_todos, users_multiple_todos = users.partition { |u| Feature.disabled?(:multiple_todos, u) }
|
||||
excluded_user_ids = []
|
||||
|
||||
if users_single_todos.present?
|
||||
excluded_user_ids += pending_todos(
|
||||
users_single_todos,
|
||||
attributes.slice(:project_id, :target_id, :target_type, :commit_id, :discussion)
|
||||
).distinct_user_ids
|
||||
end
|
||||
|
||||
if users_multiple_todos.present? && !Todo::ACTIONS_MULTIPLE_ALLOWED.include?(attributes.fetch(:action))
|
||||
excluded_user_ids += pending_todos(
|
||||
users_multiple_todos,
|
||||
attributes.slice(:project_id, :target_id, :target_type, :commit_id, :discussion, :action)
|
||||
).distinct_user_ids
|
||||
end
|
||||
|
||||
users.reject! { |user| excluded_user_ids.include?(user.id) }
|
||||
|
||||
todos = users.map do |user|
|
||||
issue_type = attributes.delete(:issue_type)
|
||||
|
|
|
@ -1,15 +1,13 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
# Currently we register validator only for `dev` or `test` environment
|
||||
if Gitlab.dev_or_test_env? || Gitlab::Utils.to_boolean(ENV['GITLAB_ENABLE_QUERY_ANALYZERS'], default: false)
|
||||
Gitlab::Database::QueryAnalyzer.instance.hook!
|
||||
Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(::Gitlab::Database::QueryAnalyzers::GitlabSchemasMetrics)
|
||||
Gitlab::Database::QueryAnalyzer.instance.hook!
|
||||
Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(::Gitlab::Database::QueryAnalyzers::GitlabSchemasMetrics)
|
||||
|
||||
if Rails.env.test? || Gitlab::Utils.to_boolean(ENV['ENABLE_CROSS_DATABASE_MODIFICATION_DETECTION'], default: false)
|
||||
Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification)
|
||||
end
|
||||
|
||||
Gitlab::Application.configure do |config|
|
||||
config.middleware.use(Gitlab::Middleware::QueryAnalyzer)
|
||||
end
|
||||
if Rails.env.test? || Gitlab::Utils.to_boolean(ENV['ENABLE_CROSS_DATABASE_MODIFICATION_DETECTION'], default: false)
|
||||
Gitlab::Database::QueryAnalyzer.instance.all_analyzers.append(::Gitlab::Database::QueryAnalyzers::PreventCrossDatabaseModification)
|
||||
end
|
||||
|
||||
Gitlab::Application.configure do |config|
|
||||
config.middleware.use(Gitlab::Middleware::QueryAnalyzer)
|
||||
end
|
||||
|
|
|
@ -101,11 +101,11 @@ understand the GitLab architecture.
|
|||
A complete architecture diagram is available in our
|
||||
[component diagram](#component-diagram) below.
|
||||
|
||||
![Simplified Component Overview](img/architecture_simplified.png)
|
||||
![Simplified Component Overview](img/architecture_simplified_v14_9.png)
|
||||
|
||||
<!--
|
||||
To update this diagram, GitLab team members can edit this source file:
|
||||
https://docs.google.com/drawings/d/1fBzAyklyveF-i-2q-OHUIqDkYfjjxC4mq5shwKSZHLs/edit.
|
||||
To update this diagram, use and update this source file:
|
||||
https://miro.com/app/board/uXjVOH3lzXo=/
|
||||
-->
|
||||
|
||||
### Component diagram
|
||||
|
|
Binary file not shown.
Before Width: | Height: | Size: 28 KiB |
Binary file not shown.
After Width: | Height: | Size: 44 KiB |
|
@ -81,10 +81,8 @@ If you use Gitpod and you get an error about Jira not being able to access the d
|
|||
|
||||
GitLab for Jira users can authenticate with GitLab using GitLab OAuth.
|
||||
|
||||
FLAG:
|
||||
By default this feature is not available. To make it available,
|
||||
ask an administrator to [enable the feature flag](../../administration/feature_flags.md) named `jira_connect_oauth`.
|
||||
The feature is not ready for production use.
|
||||
WARNING:
|
||||
This feature is not ready for production use. The feature flag should only be enabled in development.
|
||||
|
||||
The following steps describe setting up an environment to test the GitLab OAuth flow:
|
||||
|
||||
|
|
|
@ -6,7 +6,8 @@ info: To determine the technical writer assigned to the Stage/Group associated w
|
|||
|
||||
# Service Ping Guide **(FREE SELF)**
|
||||
|
||||
> Introduced in GitLab Ultimate 11.2, more statistics.
|
||||
> - Introduced in GitLab Ultimate 11.2, more statistics.
|
||||
> - In GitLab 14.1, [renamed from Usage Ping to Service Ping](https://gitlab.com/groups/gitlab-org/-/epics/5990). In 14.0 and earlier, use the Usage Ping documentation for the Rails commands appropriate to your version.
|
||||
|
||||
Service Ping is a GitLab process that collects and sends a weekly payload to GitLab.
|
||||
The payload provides important high-level data that helps our product, support,
|
||||
|
|
|
@ -54,7 +54,8 @@ To-do items aren't affected by [GitLab notification email settings](profile/noti
|
|||
|
||||
<!-- When the feature flag is removed, integrate this topic into the one above. -->
|
||||
|
||||
> [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28355) in GitLab 13.8 [with a flag](../administration/feature_flags.md) named `multiple_todos`. Disabled by default.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/issues/28355) in GitLab 13.8 [with a flag](../administration/feature_flags.md) named `multiple_todos`. Disabled by default.
|
||||
> - [Introduced](https://gitlab.com/gitlab-org/gitlab/-/merge_requests/82470) in GitLab 14.9: only mentions create multiple to-do items.
|
||||
|
||||
FLAG:
|
||||
On self-managed GitLab, by default this feature is not available. To make it available per user,
|
||||
|
@ -62,8 +63,11 @@ ask an administrator to [enable the feature flag](../administration/feature_flag
|
|||
On GitLab.com, this feature is not available.
|
||||
The feature is not ready for production use.
|
||||
|
||||
When you enable this feature, new actions for the same user on the same object
|
||||
create new to-do items.
|
||||
When you enable this feature:
|
||||
|
||||
- Every time you're mentioned, GitLab creates a new to-do item for you.
|
||||
- Other [actions that create to-do items](#actions-that-create-to-do-items)
|
||||
create one to-do item per action type on the issue, MR, and so on.
|
||||
|
||||
## Create a to-do item
|
||||
|
||||
|
|
|
@ -9,11 +9,35 @@ module Gitlab
|
|||
{
|
||||
image: 'illustrations/manual_action.svg',
|
||||
size: 'svg-394',
|
||||
title: 'Waiting for approval',
|
||||
content: "This job deploys to the protected environment \"#{subject.deployment&.environment&.name}\" which requires approvals. Use the Deployments API to approve or reject the deployment."
|
||||
title: _('Waiting for approval'),
|
||||
content: _("This job deploys to the protected environment \"%{environment}\" which requires approvals.") % { environment: subject.deployment&.environment&.name }
|
||||
}
|
||||
end
|
||||
|
||||
def has_action?
|
||||
true
|
||||
end
|
||||
|
||||
def action_icon
|
||||
nil
|
||||
end
|
||||
|
||||
def action_title
|
||||
nil
|
||||
end
|
||||
|
||||
def action_button_title
|
||||
_('Go to environments page to approve or reject')
|
||||
end
|
||||
|
||||
def action_path
|
||||
project_environments_path(subject.project)
|
||||
end
|
||||
|
||||
def action_method
|
||||
:get
|
||||
end
|
||||
|
||||
def self.matches?(build, user)
|
||||
build.waiting_for_deployment_approval?
|
||||
end
|
||||
|
|
|
@ -33,7 +33,7 @@ module Gitlab
|
|||
chain.add ::Gitlab::SidekiqMiddleware::BatchLoader
|
||||
chain.add ::Gitlab::SidekiqMiddleware::InstrumentationLogger
|
||||
chain.add ::Gitlab::SidekiqMiddleware::AdminMode::Server
|
||||
chain.add ::Gitlab::SidekiqMiddleware::QueryAnalyzer if Gitlab.dev_or_test_env? || Gitlab::Utils.to_boolean(ENV['GITLAB_ENABLE_QUERY_ANALYZERS'], default: false)
|
||||
chain.add ::Gitlab::SidekiqMiddleware::QueryAnalyzer
|
||||
chain.add ::Gitlab::SidekiqVersioning::Middleware
|
||||
chain.add ::Gitlab::SidekiqStatus::ServerMiddleware
|
||||
chain.add ::Gitlab::SidekiqMiddleware::WorkerContext::Server
|
||||
|
|
|
@ -16955,6 +16955,9 @@ msgstr ""
|
|||
msgid "Go to environments"
|
||||
msgstr ""
|
||||
|
||||
msgid "Go to environments page to approve or reject"
|
||||
msgstr ""
|
||||
|
||||
msgid "Go to epic"
|
||||
msgstr ""
|
||||
|
||||
|
@ -37837,6 +37840,9 @@ msgstr ""
|
|||
msgid "This job depends on upstream jobs that need to succeed in order for this job to be triggered"
|
||||
msgstr ""
|
||||
|
||||
msgid "This job deploys to the protected environment \"%{environment}\" which requires approvals."
|
||||
msgstr ""
|
||||
|
||||
msgid "This job does not have a trace."
|
||||
msgstr ""
|
||||
|
||||
|
@ -41246,6 +41252,9 @@ msgstr ""
|
|||
msgid "Wait for the file to load to copy its contents"
|
||||
msgstr ""
|
||||
|
||||
msgid "Waiting for approval"
|
||||
msgstr ""
|
||||
|
||||
msgid "Waiting for merge (open and assigned)"
|
||||
msgstr ""
|
||||
|
||||
|
|
|
@ -75,5 +75,15 @@ RSpec.describe PendingTodosFinder do
|
|||
|
||||
expect(todos).to contain_exactly(todo1, todo2)
|
||||
end
|
||||
|
||||
it 'supports retrieving of todos for a specific action' do
|
||||
todo = create(:todo, :pending, user: user, target: issue, action: Todo::MENTIONED)
|
||||
|
||||
create(:todo, :pending, user: user, target: issue, action: Todo::ASSIGNED)
|
||||
|
||||
todos = described_class.new(users, action: Todo::MENTIONED).execute
|
||||
|
||||
expect(todos).to contain_exactly(todo)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
|
@ -5,22 +5,10 @@ require 'spec_helper'
|
|||
RSpec.describe Gitlab::Ci::Status::Build::WaitingForApproval do
|
||||
let_it_be(:project) { create(:project, :repository) }
|
||||
let_it_be(:user) { create(:user) }
|
||||
let_it_be(:build) { create(:ci_build, :manual, environment: 'production', project: project) }
|
||||
|
||||
subject { described_class.new(Gitlab::Ci::Status::Core.new(build, user)) }
|
||||
|
||||
describe '#illustration' do
|
||||
let(:build) { create(:ci_build, :manual, environment: 'production', project: project) }
|
||||
|
||||
before do
|
||||
environment = create(:environment, name: 'production', project: project)
|
||||
create(:deployment, :blocked, project: project, environment: environment, deployable: build)
|
||||
end
|
||||
|
||||
it { expect(subject.illustration).to include(:image, :size) }
|
||||
it { expect(subject.illustration[:title]).to eq('Waiting for approval') }
|
||||
it { expect(subject.illustration[:content]).to include('This job deploys to the protected environment "production"') }
|
||||
end
|
||||
|
||||
describe '.matches?' do
|
||||
subject { described_class.matches?(build, user) }
|
||||
|
||||
|
@ -46,4 +34,39 @@ RSpec.describe Gitlab::Ci::Status::Build::WaitingForApproval do
|
|||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#illustration' do
|
||||
before do
|
||||
environment = create(:environment, name: 'production', project: project)
|
||||
create(:deployment, :blocked, project: project, environment: environment, deployable: build)
|
||||
end
|
||||
|
||||
it { expect(subject.illustration).to include(:image, :size) }
|
||||
it { expect(subject.illustration[:title]).to eq('Waiting for approval') }
|
||||
it { expect(subject.illustration[:content]).to include('This job deploys to the protected environment "production"') }
|
||||
end
|
||||
|
||||
describe '#has_action?' do
|
||||
it { expect(subject.has_action?).to be_truthy }
|
||||
end
|
||||
|
||||
describe '#action_icon' do
|
||||
it { expect(subject.action_icon).to be_nil }
|
||||
end
|
||||
|
||||
describe '#action_title' do
|
||||
it { expect(subject.action_title).to be_nil }
|
||||
end
|
||||
|
||||
describe '#action_button_title' do
|
||||
it { expect(subject.action_button_title).to eq('Go to environments page to approve or reject') }
|
||||
end
|
||||
|
||||
describe '#action_path' do
|
||||
it { expect(subject.action_path).to include('environments') }
|
||||
end
|
||||
|
||||
describe '#action_method' do
|
||||
it { expect(subject.action_method).to eq(:get) }
|
||||
end
|
||||
end
|
||||
|
|
|
@ -0,0 +1,43 @@
|
|||
# frozen_string_literal: true
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
RSpec.describe MergeRequests::Mergeability::CheckOpenStatusService do
|
||||
subject(:check_open_status) { described_class.new(merge_request: merge_request, params: {}) }
|
||||
|
||||
let(:merge_request) { build(:merge_request) }
|
||||
|
||||
describe '#execute' do
|
||||
before do
|
||||
expect(merge_request).to receive(:open?).and_return(open)
|
||||
end
|
||||
|
||||
context 'when the merge request is open' do
|
||||
let(:open) { true }
|
||||
|
||||
it 'returns a check result with status success' do
|
||||
expect(check_open_status.execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::SUCCESS_STATUS
|
||||
end
|
||||
end
|
||||
|
||||
context 'when the merge request is not open' do
|
||||
let(:open) { false }
|
||||
|
||||
it 'returns a check result with status failed' do
|
||||
expect(check_open_status.execute.status).to eq Gitlab::MergeRequests::Mergeability::CheckResult::FAILED_STATUS
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe '#skip?' do
|
||||
it 'returns false' do
|
||||
expect(check_open_status.skip?).to eq false
|
||||
end
|
||||
end
|
||||
|
||||
describe '#cacheable?' do
|
||||
it 'returns false' do
|
||||
expect(check_open_status.cacheable?).to eq false
|
||||
end
|
||||
end
|
||||
end
|
|
@ -47,7 +47,7 @@ RSpec.describe MergeRequests::Mergeability::RunChecksService do
|
|||
expect(service).not_to receive(:execute)
|
||||
end
|
||||
|
||||
expect(execute).to match_array([success_result, success_result, success_result])
|
||||
expect(execute).to match_array([success_result, success_result, success_result, success_result])
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -628,12 +628,32 @@ RSpec.describe TodoService do
|
|||
stub_feature_flags(multiple_todos: true)
|
||||
end
|
||||
|
||||
it 'creates a todo even if user already has a pending todo' do
|
||||
it 'creates a MENTIONED todo even if user already has a pending MENTIONED todo' do
|
||||
create(:todo, :mentioned, user: member, project: project, target: issue, author: author)
|
||||
|
||||
expect { service.update_issue(issue, author) }.to change(member.todos, :count)
|
||||
end
|
||||
|
||||
it 'creates a DIRECTLY_ADDRESSED todo even if user already has a pending DIRECTLY_ADDRESSED todo' do
|
||||
create(:todo, :directly_addressed, user: member, project: project, target: issue, author: author)
|
||||
|
||||
issue.update!(description: "#{member.to_reference}, what do you think?")
|
||||
|
||||
expect { service.update_issue(issue, author) }.to change(member.todos, :count)
|
||||
end
|
||||
|
||||
it 'creates an ASSIGNED todo even if user already has a pending MARKED todo' do
|
||||
create(:todo, :marked, user: john_doe, project: project, target: assigned_issue, author: author)
|
||||
|
||||
expect { service.reassigned_assignable(assigned_issue, author) }.to change(john_doe.todos, :count)
|
||||
end
|
||||
|
||||
it 'does not create an ASSIGNED todo if user already has an ASSIGNED todo' do
|
||||
create(:todo, :assigned, user: john_doe, project: project, target: assigned_issue, author: author)
|
||||
|
||||
expect { service.reassigned_assignable(assigned_issue, author) }.not_to change(john_doe.todos, :count)
|
||||
end
|
||||
|
||||
it 'creates multiple todos if a user is assigned and mentioned in a new issue' do
|
||||
assigned_issue.description = mentions
|
||||
service.new_issue(assigned_issue, author)
|
||||
|
|
Loading…
Reference in New Issue